程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> JAVA綜合教程 >> Java項目——聊天器,java聊天器

Java項目——聊天器,java聊天器

編輯:JAVA綜合教程

Java項目——聊天器,java聊天器


准備工作:

1.在服務端和客戶端項目中都建立中間傳遞對象,implements序列化

 

 1 public class ContextDemo implements Serializable {
 2 
 3     // 0:上線 1:發送信息 2:下線 3:抖窗 4:發送文件
 4     private int type;
 5     private HashSet<String> clients;
 6     private String info;
 7     private String name;
 8     private String time;
 9     private String last;
10     private ArrayList<Byte> list2;
11 
12     public String getLast() {
13         return last;
14     }
15 
16     public void setLast(String last) {
17         this.last = last;
18     }
19     public ArrayList<Byte> getList2() {
20         return list2;
21     }
22 
23     public void setList2(ArrayList<Byte> list2) {
24         this.list2 = list2;
25     }
26 
27     public String getName() {
28         return name;
29     }
30 
31     public void setName(String name) {
32         this.name = name;
33     }
34 
35     public int getType() {
36         return type;
37     }
38 
39     public void setType(int type) {
40         this.type = type;
41     }
42 
43     public HashSet<String> getClients() {
44         return clients;
45     }
46 
47     public void setClients(HashSet<String> clients) {
48         this.clients = clients;
49     }
50 
51     public String getInfo() {
52         return info;
53     }
54 
55     public void setInfo(String info) {
56         this.info = info;
57     }
58 
59     public String getTime() {
60         return time;
61     }
62 
63     public void setTime(String time) {
64         this.time = time;
65     }
66 
67 }

 

2.服務端實現監聽

服務端靜態創建一個可以監聽客戶端連接的serversocket和可以存儲在線用戶名與socket的Hashmap,服務端開啟監聽,並在監聽到任意客戶端的連接時開啟一個新的服務端監聽線程(將該用戶的socket通過構造函數傳遞給這個線程)

 1 public static ServerSocket ss;
 2     public static HashMap<String, Socket> online;
 3     public static Socket socket;
 4 
 5     static {
 6         try {
 7             ss = new ServerSocket(8080);
 8             System.out.println("服務器已開啟");
 9             online = new HashMap<String, Socket>();
10         } catch (IOException e) {
11             e.printStackTrace();
12         }
13     }
14 
15     public void action() {
16         try {
17             while (true) {
18                 Socket s = ss.accept();
19                 System.out.println("服務器正在監聽");
20                 new Server_Thread(s).start();
21             }
22         } catch (IOException e) {
23             // TODO Auto-generated catch block
24             e.printStackTrace();
25         }
26     }
27 
28     public static void main(String[] args) {
29 
30         new Chat_Server().action();
31 
32     }

線程中定義

(1)發送給全部在線用戶的方法,主要是通過創建Hashmap的iterator來實現遍歷,獲取到每一個在線用戶的socket,並用這個用戶的socket來建立outputstream進行消息的傳遞

 

 1 // 定義發送給全部用戶的方法
 2         public void sendtoall(ContextDemo servercontext) {
 3             Collection<Socket> clients = online.values();
 4             Iterator<Socket> iterator = clients.iterator();
 5             ObjectOutputStream oo;
 6             while (iterator.hasNext()) {
 7 
 8                 Socket socket = iterator.next();
 9                 try {
10                     oo = new ObjectOutputStream(socket.getOutputStream());
11                     oo.writeObject(servercontext);
12                     oo.flush();
13                 } catch (IOException e) {
14                     // TODO Auto-generated catch block
15                     e.printStackTrace();
16                 }
17             }
18         }

 

(2)發送給指定用戶的方法,方法實現與發送給全部用戶的方法基本一致,只是需要進行判斷,如果選中的用戶中包含遍歷出來的在線用戶,再取socket進行發送

 1 // 定義發送給指定用戶的方法
 2         public void sendtothis(ContextDemo servercontext) {
 3             HashSet<String> clients = clientcontext.getClients();
 4             Set<String> oo = online.keySet();
 5             Iterator<String> it = oo.iterator();
 6             //如果用的同一個輸出流對象,可能會因前一個未寫完而發生錯誤
 7             ObjectOutputStream ooo;
 8             while (it.hasNext()) {
 9                 String name = it.next();
10                 if (clients.contains(name)) {
11                     Socket s = online.get(name);
12                     try {
13                         ooo = new ObjectOutputStream(s.getOutputStream());
14                         ooo.writeObject(servercontext);
15                         ooo.flush();
16                     } catch (IOException e) {
17                         // TODO Auto-generated catch block
18                         e.printStackTrace();
19                     }
20                 }
21             }
22         }

注意:此時應該在其中單獨定義一個objectoutputstream,因為寫出的時候有時間差!!!此bug耗費10小時尋找!!!!(關掉一個客戶端後,另外一個報IOexcption)

線程開始不停地監聽從客戶端發過來的信息(中間傳遞對象),並判斷type,通過switch語句執行不同的操作

 

1 @Override
2         public void run() {
3             try {
4                 while (true) {
5                     in = new ObjectInputStream(socket.getInputStream());
6                     clientcontext = (ContextDemo) in.readObject();
7 
8                     // 分析type的種類,來用以判斷執行哪種操作
9                     switch (clientcontext.getType()) {

 

 

 

 

 

一、注冊

界面:

 

獲取到用戶輸入的用戶名密碼,進行一系列的判斷,與配置文件中的數值進行比對,如果無誤則保存當前用戶輸入的用戶名、密碼進配置文件,並成功登陸到聊天室界面(通過構造函數傳遞socket和username),否則則報錯

 1 try {
 2             Properties userPro = new Properties();
 3             userPro.load(new FileInputStream("Users.properties"));
 4             
 5             String username = usertext.getText();
 6             String passwordFirst = new String(password1.getPassword());
 7             String passwordLast = new String(password2.getPassword());
 8             
 9             if (username.length() != 0) {
10                 
11                 if (userPro.containsKey(username)) {
12                     JOptionPane.showMessageDialog(getContentPane(), "用戶名已經存在!");
13                 } else {
14                     
15                     if(passwordFirst.equals(passwordLast)){
16                         if(passwordFirst.length()!=0){
17                             userPro.setProperty(username, passwordFirst);
18                             userPro.store(new FileOutputStream("Users.properties"), "用戶名——密碼");
19                             
20                             //進入聊天界面
21                             Socket socket = new Socket("localhost", 8080);
22                             ChatRoom chatRoom = new ChatRoom(username,socket);
23                             chatRoom.setVisible(true);
24                             setVisible(false);
25                         }else {
26                             JOptionPane.showMessageDialog(getContentPane(), "密碼不能為空");
27                         }
28                     }else {
29                         JOptionPane.showMessageDialog(getContentPane(), "兩次輸入密碼不一致");
30                     }
31                 }
32             } else {
33                 JOptionPane.showMessageDialog(getContentPane(), "用戶名不能為空");
34             }
35         }
36         catch (FileNotFoundException e) {
37             // TODO Auto-generated catch block
38             e.printStackTrace();
39         } catch (IOException e) {
40             // TODO Auto-generated catch block
41             e.printStackTrace();
42         }

 

 

二、登錄

界面:

 

用戶輸入用戶名和密碼,此時通過與項目自帶的properties配置文件中的內容進行比對,如果有記錄,則可以進入到聊天室(通過設置了每個testfield和登錄按鈕的keypressed事件,可通過檢測按下回車按鈕進入),若沒有,則要求進入注冊界面。

注意:如可以進入到聊天室界面,需要將此時新建的socket和用戶名通過聊天室界面的構造函數傳給聊天室。

 1 try {
 2             Properties properties = new Properties();
 3             properties.load(new FileInputStream("Users.properties"));
 4             
 5             String usernameString = textusername.getText();
 6             String pasString = new String(password1.getPassword());
 7             
 8             if(properties.containsKey(usernameString)){
 9                 if(properties.getProperty(usernameString).equals(pasString)){
10                     Socket socket = new Socket("localhost", 8080);
11                     ChatRoom chatRoom = new ChatRoom(usernameString,socket);
12                     chatRoom.setVisible(true);
13                     setVisible(false);
14                 }else {
15                     JOptionPane.showMessageDialog(getContentPane(), "密碼輸入錯誤");
16                 }
17             }else {
18                 JOptionPane.showMessageDialog(getContentPane(), "該用戶名不存在");
19             }

 

三、聊天室主界面

界面:

 

1.本用戶上線報告服務器+服務器將該用戶上線信息發送給全部用戶

(1)客戶端的構造函數中,將本用戶的socket,用戶名,當前系統時間,中間傳遞對象的類型(上線類型為0),封裝進中間傳遞對象並通過socket的outputstream發送給服務端,並開啟客戶端線程進行監控服務端傳過來的信息

 1 // 上線則匯報給服務器
 2         try {
 3             
 4             out = new ObjectOutputStream(socket.getOutputStream());
 5             // 創建傳輸對象
 6             ContextDemo clientcontext = new ContextDemo();
 7             clientcontext.setType(0);
 8             clientcontext.setName(username);
 9             SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
10             clientcontext.setTime(sdf.format(new Date()));
11             // 發送給服務端
12             out.writeObject(clientcontext);
13             out.flush();
14             // 開啟客戶端線程
15             new Client_Thread().start();
16 
17         } catch (IOException e) {
18             // TODO Auto-generated catch block
19             e.printStackTrace();
20         }

客戶端線程開始監聽

1 @Override
2         public void run() {
3 
4             try {
5                 while (true) {
6                     System.out.println("客戶端線程啟動");
7                     in = new ObjectInputStream(socket.getInputStream());
8                     final ContextDemo servercontext = (ContextDemo) in.readObject();
9                     switch (servercontext.getType()) {

(2)服務端得到該用戶的中間傳遞對象,判斷出執行上線操作,執行相應的switch語句,將用戶名與socket存入hashmap,並創建當前用戶的上線信息,對象類型type,以及在線用戶名的集合封裝進對象發送給所有的在線用戶

 

 1 // 上線
 2                     case 0:
 3                     // 添加在線用戶進online
 4                     {
 5 
 6                         online.put(clientcontext.getName(), socket);
 7 
 8                         ContextDemo serverContext = new ContextDemo();
 9                         // 將用戶上線信息發送給各客戶端
10                         serverContext.setType(0);
11                         serverContext.setInfo(clientcontext.getTime() + " " + clientcontext.getName() + " 上線啦!");
12                         // 將在線用戶用戶名全部發給客戶端
13                         HashSet<String> set = new HashSet<String>();
14                         set.addAll(online.keySet());
15                         serverContext.setClients(set);
16                         sendtoall(serverContext);
17                         break;
18                     }

(3)客戶端監聽到信息,判斷出為上下線更新操作,先清空在線列表集合,在將所要取得的各種信息從對象中取得,並獲取到在線人數集合中數目以實現在線人數顯示,並將上線消息顯示在testArea中

 1 case 0:
 2                     // 重新裝填容器
 3                     {
 4                         // 清空容器
 5                         online.clear();
 6                         HashSet<String> set = servercontext.getClients();
 7                         Iterator<String> iterator = set.iterator();
 8                         while (iterator.hasNext()) {
 9                             String name = iterator.next();
10                             if (username.equals(name)) {
11                                 online.add(name + "(本機)");
12 
13                             } else {
14                                 online.add(name);
15                             }
16                         }
17 
18                         // 顯示在list中
19                         listmodel = new UUListModel(online);
20                         count = listmodel.getSize();
21                         list.setBorder(new TitledBorder(UIManager.getBorder("TitledBorder.border"), "在線用戶:"+count+"人",
22                                 TitledBorder.LEADING, TitledBorder.TOP, null, new Color(255, 0, 0)));
23                         list.setModel(listmodel);
24                         docs.insertString(docs.getLength(), servercontext.getInfo() + "\n", attrset);
25                         break;
26                     }

2.發送消息

(1)客戶端獲取到list中選中的用戶(若不選則為群發),將該選中用戶、自己的用戶名、時間、要發送的信息等內容封裝進對象,設置type為1(發送信息識別碼),將對象傳遞給服務器,在自己的聊天界面添加聊天的內容,隨後清空list表的選中狀態以及發送框的內容(發送按鈕與回車鍵均可發送消息)

 

 1 // 發送按鈕
 2         JButton btnNewButton = new JButton("\u53D1\u9001");
 3         btnNewButton.addActionListener(new ActionListener() {
 4             public void actionPerformed(ActionEvent arg0) {
 5 
 6                 List selected = list.getSelectedValuesList();
 7                 String info = textArea_1.getText();
 8 
 9                 if (selected.size() < 1) {
10                     // 在客戶端中,容器online中本機的名字後面多加了字符,所以在客戶端不能與hashmap中的key匹配,所以本機收不到本機傳來的信息
11                     selected = online;
12                 }
13 
14                 if (info.equals("")) {
15                     JOptionPane.showMessageDialog(getContentPane(), "不能發送空信息");
16                     return;
17                 }
18 
19                 ContextDemo clientcontext = new ContextDemo();
20                 clientcontext.setInfo(info);
21                 SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
22                 String time = sdf.format(new Date());
23                 clientcontext.setTime(time);
24                 clientcontext.setType(1);// 發信息
25                 clientcontext.setName(username);
26                 HashSet<String> people = new HashSet<String>();
27                 people.addAll(selected);
28                 
29                 clientcontext.setClients(people);
30 
31                 // 清空發送頁面
32                 textArea_1.setText("");
33                 // 發送界面獲得焦點
34                 textArea_1.requestFocus();
35                 // 列表消除選中狀態
36                 list.clearSelection();
37 
38                 try {
39                     out = new ObjectOutputStream(ChatRoom.socket.getOutputStream());
40                     out.writeObject(clientcontext);
41                     out.flush();
42                 } catch (IOException e) {
43                     // TODO Auto-generated catch block
44                     e.printStackTrace();
45                 }
46 
47                 try {
48                     docs.insertString(docs.getLength(), time + " " + "我對"+selected+"說:\n" + info + "\n", attrset);
49                 } catch (BadLocationException e) {
50                     // TODO Auto-generated catch block
51                     e.printStackTrace();
52                 }
53             }
54         });

 

(2)服務器判斷出為發送消息後,將得到的信息、時間等消息進行封裝,再通過發送給指定用戶的方法將封裝好的對象傳遞給指定的用戶

 1 // 發信息
 2                     case 1: {
 3                         ContextDemo servercontext = new ContextDemo();
 4                         servercontext.setType(1);
 5                         servercontext.setName(clientcontext.getName());
 6                         servercontext.setInfo(clientcontext.getInfo());
 7                         servercontext.setTime(clientcontext.getTime());
 8 
 9                         sendtothis(servercontext);
10                         break;
11                     }

(3)指定的客戶端收到對象後判斷出了是要進行發送消息的操作,解封對象,取得消息等信息,在消息窗口顯示

1 // 發信息
2                     case 1: {
3                         String info = servercontext.getInfo();
4                         String time = servercontext.getTime();
5                         docs.insertString(docs.getLength(),
6                                 time + " " + servercontext.getName() + "對我說:\n" + info + "\n", attrset);
7                         break;
8                     }

3.下線

(1)聊天室頁面添加窗口關閉的監聽事件,在其後彈出對話框確定是否退出,若退出則設置type為2(下線識別碼)、時間等信息封裝進對象發送給服務器

 1 // 下線操作
 2                 this.addWindowListener(new WindowAdapter() {
 3                     @Override
 4                     public void windowClosing(WindowEvent e) {
 5                         
 6                         int result = JOptionPane.showConfirmDialog(getContentPane(),"您確定要離開聊天室");
 7                         if (result == 0) {
 8                             ContextDemo clientcontext = new ContextDemo();
 9                             clientcontext.setType(2);
10                             SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
11                             clientcontext.setTime(sdf.format(new Date()));
12                             clientcontext.setName(username);
13 
14                             try {
15                                 out = new ObjectOutputStream(socket.getOutputStream());
16                                 out.writeObject(clientcontext);
17                                 out.flush();
18                             } catch (IOException e1) {
19                                 // TODO Auto-generated catch block
20                                 e1.printStackTrace();
21                             }
22                         }
23                         }
24                 });

(2)服務器判斷為是下線操作後,首先建立服務端對象,設置type為2,用當前用戶傳遞過來的socket傳遞此對象給即將下線的客戶端批准其下線,隨後用下線用戶的用戶名在Hashmap中刪除此用戶,隨後新建另一服務端對象,封裝下線的信息、時間、當前在線用戶名等內容發送給其余所有在線的客戶端,讓他們執行上下線更新操作,並在case的最後用return退出whlie(true)循環,在finally中關閉掉輸入輸出流對象與socket對象,意在此客戶端與服務端的線程關閉

 1 // 下線
 2                     case 2: {
 3                         // 通知請求下線客戶端,批准下線
 4                         ContextDemo servercontext1 = new ContextDemo();
 5                         servercontext1.setType(2);
 6                         out = new ObjectOutputStream(socket.getOutputStream());
 7                         out.writeObject(servercontext1);
 8                         out.flush();//需要時間
 9 
10                         // 刷新在線hashmap
11                         online.remove(clientcontext.getName());
12 
13                         // 通知其他在線用戶,該用戶已下線
14                         ContextDemo servercontext2 = new ContextDemo();
15                         servercontext2.setType(0);
16                         servercontext2.setInfo(clientcontext.getTime() + " " + clientcontext.getName() + "用戶已下線 ");
17                         HashSet<String> set = new HashSet<String>();
18                         set.addAll(online.keySet());
19                         servercontext2.setClients(set);
20                         sendtoall(servercontext2);
21                         // 退出當前循環,不再監聽該客戶端傳來的信息
22                         return;
23                     }

(3)

1)即將下線的客戶端接收到對象後,判斷出是執行下線操作,用return退出while(true),並在finally中關閉掉socket與輸入輸出流對象,並用System.exit(0)退出虛擬機斷線

1 // 下線
2                     case 2:{
3                         return;
4                     }

2)其余在線客戶端接收到對象,判斷是要進行上下線操作,所以執行與上線更新時一樣的操作

 1 // 上下線刷新操作
 2                     case 0:
 3                     // 重新裝填容器
 4                     {
 5                         // 清空容器
 6                         online.clear();
 7                         HashSet<String> set = servercontext.getClients();
 8                         Iterator<String> iterator = set.iterator();
 9                         while (iterator.hasNext()) {
10                             String name = iterator.next();
11                             if (username.equals(name)) {
12                                 online.add(name + "(本機)");
13 
14                             } else {
15                                 online.add(name);
16                             }
17                         }
18 
19                         // 顯示在list中
20                         listmodel = new UUListModel(online);
21                         count = listmodel.getSize();
22                         list.setBorder(new TitledBorder(UIManager.getBorder("TitledBorder.border"), "在線用戶:"+count+"人",
23                                 TitledBorder.LEADING, TitledBorder.TOP, null, new Color(255, 0, 0)));
24                         list.setModel(listmodel);
25                         docs.insertString(docs.getLength(), servercontext.getInfo() + "\n", attrset);
26                         break;
27                     }

4.抖窗

(1)客戶端將列表中得到的用戶名封裝進對象,設置type為3,再將時間等信息封裝進對象,將對象發送給服務端

 1 btnShakeFrame.addActionListener(new ActionListener() {
 2             public void actionPerformed(ActionEvent e) {
 3 
 4                 List selected = list.getSelectedValuesList();
 5 
 6                 if (selected.size() < 1) {
 7                     // 在客戶端中,容器online中本機的名字後面多加了字符,所以在客戶端不能與hashmap中的key匹配,所以本機收不到本機傳來的信息
 8                     selected = online;
 9                 }
10 
11                 ContextDemo clientcontext = new ContextDemo();
12                 clientcontext.setType(3);
13                 SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
14                 String time = sdf.format(new Date());
15                 clientcontext.setTime(time);
16                 clientcontext.setName(username);
17                 HashSet<String> set = new HashSet<String>();
18                 set.addAll(selected);
19                 clientcontext.setClients(set);
20 
21                 // 列表消除選中狀態
22                 list.clearSelection();
23 
24                 try {
25                     out = new ObjectOutputStream(socket.getOutputStream());
26                     out.writeObject(clientcontext);
27                     out.flush();
28                 } catch (IOException e1) {
29                     // TODO Auto-generated catch block
30                     e1.printStackTrace();
31                 }
32 
33                 try {
34                     docs.insertString(docs.getLength(), time + "您發送了一個屏幕抖動\n", attrset);
35                 } catch (BadLocationException e1) {
36                     // TODO Auto-generated catch block
37                     e1.printStackTrace();
38                 }
39             }
40         });

(2)服務端判斷出是要進行抖窗操作後,封裝有用的信息進對象,並通過發送給指定用戶方法進行發送

1 // 抖窗
2                     case 3: {
3                         ContextDemo servercontext = new ContextDemo();
4                         servercontext.setType(3);
5                         servercontext.setInfo(clientcontext.getTime() + " " + clientcontext.getName() + "對你抖了一下屏 \n");
6 
7                         sendtothis(servercontext);
8                         break;
9                     }

(3)指定的客戶端判斷要進行抖屏,先解封有用的信息進消息顯示窗口,然後再調用封裝好的抖屏方法進行抖屏操作

1 // 抖窗
2                     case 3: {
3                         String info = servercontext.getInfo();
4                         docs.insertString(docs.getLength(), info, attrset);
5                         shakeFrame();
6                         break;
7                     }
 1 public void shakeFrame() {
 2         int x = ChatRoom.this.getX();
 3         int y = ChatRoom.this.getY();
 4         for (int i = 0; i < 20; i++) {
 5             if ((i & 1) == 0) {
 6                 x += 8;
 7                 y += 8;
 8             } else {
 9                 x -= 8;
10                 y -= 8;
11             }
12             ChatRoom.this.setLocation(x, y);
13             try {
14                 Thread.sleep(50);
15             } catch (InterruptedException e1) {
16                 e1.printStackTrace();
17             }
18         }
19     }

5.發送文件

(1)客戶端先獲取到想要發送文件給哪個用戶的用戶名,隨後彈出文件選擇框,構建文件的抽象路徑,並得到後綴名,其後通過文件的輸入流將所得到的文件一個字節一個字節的讀入到Arraylist<byte>集合中,將後綴名保存到一個字符串中,將這些與其他有用的信息一起封裝進對象,將對象發送給服務器

  1 btnSendFile.addActionListener(new ActionListener() {
  2             public void actionPerformed(ActionEvent e) {
  3                 
  4                 List selected = list.getSelectedValuesList();
  5                 if (selected.size() < 1) {
  6                     JOptionPane.showMessageDialog(getContentPane(), "必須選擇一名用戶");
  7                     return;
  8                 }
  9                 if (selected.toString().contains(username+"(本機)")) {
 10                     JOptionPane.showMessageDialog(getContentPane(), "不能向自己發送文件");
 11                     return;
 12                 }
 13                 
 14                 JFileChooser chooser = new JFileChooser();
 15                 chooser.setDialogTitle("選擇文件框"); 
 16                 chooser.showDialog(getContentPane(), "選擇");
 17                 
 18                 //判斷是否拿到文件
 19                 if(chooser.getSelectedFile()!=null){
 20                     path = chooser.getSelectedFile().getPath();
 21                     file = new File(path);
 22                     //獲取文件的後綴名
 23                     int i =file.getName().indexOf(".");
 24                     last = file.getName().substring(i);
 25                 
 26                     //判斷文件是否為空
 27                     if(file.length()==0){
 28                         JOptionPane.showMessageDialog(getContentPane(), "文件為空,不能傳送");
 29                         return;
 30                     }
 31                 }
 32                 
 33                 ContextDemo clientcontext = new ContextDemo();
 34                 //發送文件(基礎工作)
 35                 clientcontext.setType(4);
 36                 //保存後綴名
 37                 clientcontext.setLast(last);
 38                 clientcontext.setName(username);
 39                 HashSet<String> set = new HashSet<String>();
 40                 set.addAll(selected);
 41                 clientcontext.setClients(set);
 42                 SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
 43                 String time = sdf.format(new Date());
 44                 clientcontext.setTime(time);
 45                 
 46                 //發送文件(文件部分操作)
 47                 list2 = new ArrayList<Byte>();
 48                 try {
 49                     input = new FileInputStream(file);
 50                     
 51                     int result = -1;
 52                     
 53                     while((result = input.read()) != -1)
 54                     {
 55                         list2.add((byte)result);
 56                     }
 57                     
 58                     
 59                     
 60                 } catch (FileNotFoundException e2) {
 61                     // TODO Auto-generated catch block
 62                     e2.printStackTrace();
 63                 } catch (IOException e1) {
 64                     // TODO Auto-generated catch block
 65                     e1.printStackTrace();
 66                 }finally {
 67                     
 68                     try {
 69                         if(input != null)
 70                         {
 71                             input.close();
 72                         }
 73                     } catch (IOException e1) {
 74                         e1.printStackTrace();
 75                     }
 76                 }
 77                 
 78                 clientcontext.setList2(list2);
 79                 
 80                 
 81                 // 列表消除選中狀態
 82                 list.clearSelection();
 83                 
 84                 //發送給服務端
 85                 try {
 86                     out = new ObjectOutputStream(socket.getOutputStream());
 87                     out.writeObject(clientcontext);
 88                     out.flush();
 89                 } catch (IOException e1) {
 90                     // TODO Auto-generated catch block
 91                     e1.printStackTrace();
 92                 }
 93 
 94                 try {
 95                     docs.insertString(docs.getLength(), time + "您發送了一個文件\n", attrset);
 96                 } catch (BadLocationException e1) {
 97                     // TODO Auto-generated catch block
 98                     e1.printStackTrace();
 99                 }
100             }
101         });
102         

(2)服務端判斷出是要進行文件的發送操作,將所有有用的信息封裝進對象發送給指定的用戶

 1 // 發送文件
 2                     case 4: {
 3                         ContextDemo servercontext = new ContextDemo();
 4                         servercontext.setList2(clientcontext.getList2());
 5                         servercontext.setLast(clientcontext.getLast());
 6                         servercontext.setInfo(clientcontext.getTime() + " " + clientcontext.getName() + "對你發送了一個文件\n");
 7                         servercontext.setType(4);
 8 
 9                         sendtothis(servercontext);
10 
11                         break;
12                     }

(3)指定客戶端收到對象後,先將字節集合解封出來,用iterator將字節寫入一個字節數組,再通過緩沖字節流讀入字節,通過解封出來的後綴名構造好新的文件後,通過緩沖字節流寫入文件,並接收到需要的信息顯示在消息窗口中

 1 //接收到文件
 2                     case 4:
 3                     {
 4                         ArrayList<Byte> list3 = new ArrayList<Byte>();
 5                         list3 = servercontext.getList2();
 6                         Iterator<Byte> it = list3.iterator();
 7                         byte[] dedao = new byte[10000000];
 8                         int i = 0;
 9                         while(it.hasNext()){
10                             dedao[i] = it.next();
11                             i++;
12                         }
13                         
14                         
15                         ii = new ByteArrayInputStream(dedao);
16                         inputStream = new BufferedInputStream(ii,10000);
17                         //獲取後綴名
18                         String thLast = servercontext.getLast();
19                         output = new FileOutputStream("sourse/dedao"+thLast);
20                         outputStream = new BufferedOutputStream(output,10000);
21                         
22                         byte[] b = new byte[10000];//暫存讀取的字節內容
23                         int result = -1;
24                         while((result = inputStream.read(b)) != -1)
25                         {
26                             outputStream.write(b, 0, result);
27                         }
28                         output.flush();
29                         
30                         
31                         
32                         String info = servercontext.getInfo();
33                         docs.insertString(docs.getLength(), info, attrset);
34                         break;
35                     }

 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved