• 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() + "
    ", attrset);
    25                         break;
    26                     }

    2.发送消息

    (1)客户端获取到list中选中的用户(若不选则为群发),将该选中用户、自己的用户名、时间、要发送的信息等内容封装进对象,设置type为1(发送信息识别码),将对象传递给服务器,在自己的聊天界面添加聊天的内容,随后清空list表的选中状态以及发送框的内容(发送按钮与回车键均可发送消息)

     1 // 发送按钮
     2         JButton btnNewButton = new JButton("u53D1u9001");
     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+"说:
    " + info + "
    ", 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() + "对我说:
    " + info + "
    ", 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() + "
    ", 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 + "您发送了一个屏幕抖动
    ", 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() + "对你抖了一下屏 
    ");
    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 + "您发送了一个文件
    ", 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() + "对你发送了一个文件
    ");
     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                     }
  • 相关阅读:
    PAT-字符串处理-A 1001 A+B Format (20分)
    PAT-字符串处理-B 1048 数字加密 (20分)
    数据库-第二章 关系数据库-2.3 关系的完整性
    数据库-第二章 关系数据库-2.2 关系操作
    数据库-第二章 关系数据库-2.1 关系数据结构及形式化定义
    IDLE打开Python报错 api-ms-win-crt-runtimel1-1-0.dll缺失的解决方案
    老毛桃pe安装系统
    LeetCode 213. House Robber II (动态规划)
    LeetCode 198. House Robber(DP)
    LeetCode 211. Add and Search Word
  • 原文地址:https://www.cnblogs.com/ccw95/p/5969469.html
Copyright © 2020-2023  润新知