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                     }

 

posted @ 2016-10-17 13:43  龙之天族  阅读(818)  评论(0编辑  收藏  举报