zoukankan      html  css  js  c++  java
  • TCP创建多人聊天室

    群聊-聊天室

    群聊:任何时候,任何一个客户端都可以向其它客户端发送和接受数据,服务器只起到转发的作用。

    1、首先创建一个聊天室的简易版(版本1)。

    需求:可以多个用户同时访问服务端,并且可以不断各自请求服务端获取响应的数据。

    可以多个用户同时访问服务端:这个需要在服务端创建多线程,使服务端的监听套接字,可以被多个客户端使用。

    可以不断各自请求服务端获取响应的数据:这个只需要在客户端的数据发送和接受处加上一层死循环,在服务端的外层套上一层死循环即可。

    需要改进的不足之处:

    1、客户端只能自己对自己说话,还没有实现群聊的效果。

    2、代码比较多,不易于维护。

    3、客户端的接收和发送数据没有分离,必须等到指定者发送数据,才能接收指定者的消息。

    服务端

    代码:

     1 package 在线聊天室;
     2 
     3 import java.io.DataInputStream;
     4 import java.io.DataOutputStream;
     5 import java.io.IOException;
     6 import java.net.ServerSocket;
     7 import java.net.Socket;
     8 
     9 /**
    10  * 模拟单人聊天室
    11  * @author liuzeyu12a
    12  *
    13  */
    14 public class Chat {
    15     public static void main(String[] args) throws Exception {
    16         //建立服务器端套接字,绑定本地端口
    17         ServerSocket server = new ServerSocket(9999);
    18             while(true){
    19                 new Thread(()->{
    20                     Socket client = null;
    21                     try {
    22                         //监听客户端
    23                         client = server.accept();
    24                     } catch (IOException e) {
    25                         e.printStackTrace();
    26                     }
    27                     System.out.println("一个客户端建立了连接...");
    28                     
    29                     //接受客户端的消息
    30                     DataInputStream dis = null;
    31                     DataOutputStream dos = null;
    32                     try {
    33                         dis = new DataInputStream(client.getInputStream());
    34                         dos = new DataOutputStream(client.getOutputStream());
    35                     } catch (IOException e) {
    36                         e.printStackTrace();
    37                     }
    38                     
    39                     boolean isRunning = true;
    40                     while(isRunning) {
    41                         String msg = null;
    42                         try {
    43                             msg = dis.readUTF();
    44                         } catch (IOException e) {
    45                             e.printStackTrace();
    46                         }
    47                         //返回回去给客户端    
    48                         try {
    49                             dos.writeUTF(msg);
    50                             dos.flush();
    51                         } catch (IOException e) {
    52                             isRunning = false;  //客户端断开即停止读写数据
    53                         }
    54                     }
    55                     
    56                     //释放资源
    57                     try {
    58                         if(null!=dos)
    59                         dos.close();
    60                     } catch (IOException e) {
    61                         e.printStackTrace();
    62                     }
    63                     try {
    64                         if(null!=dis)
    65                         dis.close();
    66                     } catch (IOException e) {
    67                         e.printStackTrace();
    68                     }
    69                     try {
    70                         if(null!=client)
    71                         client.close();
    72                     } catch (IOException e) {
    73                         e.printStackTrace();
    74                     }
    75                 }).start();
    76                 
    77             }
    78     }
    79 }
    View Code

    客户端

    代码:

     1 package 在线聊天室;
     2 
     3 import java.io.BufferedReader;
     4 import java.io.DataInputStream;
     5 import java.io.DataOutputStream;
     6 import java.io.IOException;
     7 import java.io.InputStreamReader;
     8 import java.net.Socket;
     9 
    10 /**
    11  * TCP模拟单人聊天室
    12  * @author liuzeyu12a
    13  *
    14  */
    15 public class Client {
    16     public static void main(String[] args) throws IOException, IOException {
    17         //建立客户端套接字
    18         Socket client = new Socket("localhost",9999);
    19         
    20         //发送数据
    21         BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
    22         DataInputStream dis = new DataInputStream(client.getInputStream());
    23         DataOutputStream dos = new DataOutputStream(client.getOutputStream());
    24         boolean isRunning = true;
    25         while(isRunning) {
    26             String msg = reader.readLine();
    27             dos.writeUTF(msg);
    28             //客户端接收服务器的响应
    29     
    30             String respond = dis.readUTF();
    31             System.out.println(respond);
    32         }
    33         //关闭
    34         client.close();
    35     }
    36 }
    View Code

    2、我们将版本1的2,3问题进行改善一下(版本2)。

    封装:

    1)将服务器的接受和发送数据用一个Channel 类进行封装,这样子一个client 就对应了一个Channel对象了

    2)将客户端的接收和发送分离开,使用两个线程进行分割,这样子接收数据和发送数据就可以不用同时进行了(为群聊做准备)。

    将关闭资源的系列用一个ChatUtils工具类包装起来,使用Closeable接口。

     1 package 在线聊天室;
     2 
     3 import java.io.Closeable;
     4 import java.io.IOException;
     5 /**
     6  * 用于聊天室一些流释放资源
     7  * @author liuzeyu12a
     8  *
     9  */
    10 public class ChatUtils {
    11 
    12     static public void close(Closeable...closeables) {
    13         for(Closeable target :closeables) {
    14             if(null!=target) {
    15                 try {
    16                     target.close();
    17                 } catch (IOException e) {
    18                     e.printStackTrace();
    19                 }
    20             }
    21         }
    22     }
    23 }

    利用面向对象思想对服务端进行封装

     1 package 在线聊天室;
     2 
     3 import java.io.DataInputStream;
     4 import java.io.DataOutputStream;
     5 import java.io.IOException;
     6 import java.net.ServerSocket;
     7 import java.net.Socket;
     8 
     9 /**
    10  * 1)将服务器的接受和发送数据用一个Channel 类进行封装,
    11  * 这样子一个client 就对应了一个Channel对象了
    12 
    13 2)将客户端的接收和发送分离开,
    14 使用两个线程进行分割,这样子接收数据和发送数据就可以不用同时进行了
    15 (为群聊做准备)。
    16  * @author liuzeyu12a
    17  *
    18  */
    19 public class Chat2 {
    20     public static void main(String[] args) throws Exception {
    21         System.out.println("-----Server-----");
    22         //建立服务器端地址,并绑定本地端口
    23         ServerSocket server = new ServerSocket(8989);
    24         
    25         //这边加上死循环是为了接受多个客户的请求
    26         while(true) {
    27                 //监听
    28                 Socket    client = server.accept();        
    29                 System.out.println("一个客户端建立了连接");
    30                 new Thread(new Channel(client)).start();
    31         }
    32         
    33     }
    34     //静态内部类,封装处理客户端的数据
    35     static class Channel implements Runnable{
    36         private DataInputStream dis;
    37         private DataOutputStream dos;
    38         private Socket client;
    39         private boolean isRunning;
    40         //构造器
    41         public Channel(Socket client) {
    42             this.client = client;
    43             this.isRunning = true;
    44             try {
    45                 dis = new DataInputStream(
    46                         client.getInputStream());
    47                 dos = new DataOutputStream(
    48                         client.getOutputStream());
    49             } catch (IOException e) {
    50                 release();
    51             }
    52         }
    53         @Override
    54         public void run() {
    55             while(isRunning) {
    56                 String msg = receive();
    57                 if(!msg.equals(""))
    58                 send(msg);
    59             }
    60         }
    61         
    62         //发送数据
    63         public void send(String msg) {
    64             try {
    65                 dos.writeUTF(msg);
    66                 dos.flush();
    67             } catch (IOException e) {
    68                 System.out.println("发送数据失败");
    69                 release();
    70             }
    71         }
    72         
    73         //接受数据
    74         public String receive() {
    75             try {
    76                 String msg = "";
    77                 msg = dis.readUTF();
    78                 return msg;
    79             } catch (IOException e) {
    80                 isRunning = false;
    81                 System.out.println("接受数据失败");
    82                 release();
    83             }
    84             return "";
    85         }
    86         
    87         //释放资源
    88         public void release() {
    89             ChatUtils.close(client,dos,dis);
    90         }
    91     }
    92 }
    View Code 

    客户端的发送:

     1 package 在线聊天室;
     2 
     3 import java.io.BufferedReader;
     4 import java.io.DataOutputStream;
     5 import java.io.IOException;
     6 import java.io.InputStreamReader;
     7 import java.net.Socket;
     8 
     9 /**
    10  * 为聊天室Client2 的发送功能服务
    11  * @author liuzeyu12a
    12  *
    13  */
    14 public class Send implements Runnable{
    15     //准备数据
    16     private BufferedReader reader;
    17     //发送数据
    18     private DataOutputStream dos;
    19     private Socket client;
    20     private boolean isRunning;
    21     //构造器
    22     public Send(Socket client) {
    23         this.client = client ;
    24         this.isRunning = true;
    25         reader= new BufferedReader(
    26                 new InputStreamReader(System.in));
    27         try {
    28             dos= new DataOutputStream(client.getOutputStream());
    29         } catch (IOException e) {
    30             System.out.println("DataOutputStream对象创建失败");
    31             release();
    32         }    
    33     }
    34     @Override
    35     public void run() {
    36         while(isRunning) {
    37             send("");
    38         }
    39     }
    40     
    41     //发送数据
    42     public void send(String msg) {
    43         try {
    44             msg = getMsgFromConsole();
    45             dos.writeUTF(msg);
    46             dos.flush();
    47         } catch (IOException e) {
    48             System.out.println("数据发送失败");
    49             release();
    50         }
    51     }
    52     
    53     public String getMsgFromConsole(){
    54         try {
    55             return reader.readLine();
    56         } catch (IOException e) {
    57             e.printStackTrace();
    58         }
    59         return null;
    60     }
    61     //释放资源
    62     public void release() {
    63         isRunning = false;
    64         ChatUtils.close(dos,client,reader);
    65     }
    66 }
    View Code

    客户端的接收:

     1 package 在线聊天室;
     2 
     3 import java.io.DataInputStream;
     4 import java.io.IOException;
     5 import java.net.Socket;
     6 
     7 /**
     8  * 为聊天室Client2 的接收功能服务
     9  * @author liuzeyu12a
    10  *
    11  */
    12 public class Receive implements Runnable{
    13 
    14     private boolean isRunning;
    15     private DataInputStream dis; 
    16     private Socket  client;
    17     //构造器
    18     public Receive(Socket  client) {
    19         this.client = client;
    20         this.isRunning = true;
    21         try {
    22             dis = new DataInputStream(client.getInputStream());
    23         } catch (IOException e) {
    24             System.out.println("DataInputStream对象创建失败失败");
    25             release();
    26         }
    27     }
    28     @Override
    29     public void run() {
    30         while(isRunning) {
    31             String msg = "";
    32             msg = recevie();
    33             if(!msg.equals(""))
    34             System.out.println(msg);
    35         }        
    36     }
    37     
    38     public String recevie() {
    39         String respone = null;
    40         try {
    41             respone = dis.readUTF();
    42             return respone;
    43         } catch (IOException e) {
    44             release();
    45             System.out.println("数据接收失败");
    46         }
    47         return null;
    48     }
    49     
    50 
    51     //释放资源
    52     public void release() {
    53         isRunning = false;
    54         ChatUtils.close(dis,client);
    55     }
    56 }
    View Code

    客户端的封装:

     1 package 在线聊天室;
     2 
     3 import java.io.IOException;
     4 import java.net.Socket;
     5 
     6 /**
     7  * 1)将服务器的接受和发送数据用一个Channel 类进行封装,
     8  * 这样子一个client 就对应了一个Channel对象了
     9 
    10 2)将客户端的接收和发送分离开,
    11 使用两个线程进行分割,这样子接收数据和发送数据就可以不用同时进行了
    12 (为群聊做准备)。
    13  * @author liuzeyu12a
    14  *
    15  */
    16 public class Client2 {
    17     public static void main(String[] args) throws IOException, IOException {
    18         System.out.println("-----Server-----");
    19         //创建Socket套接字,绑定服务器端口
    20         Socket  client  =new Socket("localhost",8989);
    21         
    22         //发送数据
    23         new Thread(new Send(client)).start();
    24         //接收数据
    25         new Thread(new Receive(client)).start();
    26     }
    27 }
    View Code

    3、实现简单的群聊功能。

    服务器可以实现数据的转发功能,客户端不再局限于自己对话自己,是一个典型的群聊案例,重点理解如何将name进行传递。

    客户端接受:

     1 package 在线聊天室过渡版;
     2 
     3 import java.io.DataInputStream;
     4 import java.io.IOException;
     5 import java.net.Socket;
     6 
     7 /**
     8  * 为聊天室Client2 的接收功能服务
     9  * @author liuzeyu12a
    10  *
    11  */
    12 public class Receive implements Runnable{
    13 
    14     private boolean isRunning;
    15     private DataInputStream dis; 
    16     private Socket  client;
    17     //构造器
    18     public Receive(Socket  client) {
    19         this.client = client;
    20         this.isRunning = true;
    21         try {
    22             dis = new DataInputStream(client.getInputStream());
    23         } catch (IOException e) {
    24             System.out.println("DataInputStream对象创建失败失败");
    25             release();
    26         }
    27     }
    28     @Override
    29     public void run() {
    30         while(isRunning) {
    31             String msg = "";
    32             msg = receive();
    33             if(!msg.equals("")) {
    34                 System.out.println(msg);
    35             }
    36 
    37         }        
    38     }
    39     public String receive() {
    40         String respone = null;
    41         try {
    42             respone = dis.readUTF();
    43             return respone;
    44         } catch (IOException e) {
    45             release();
    46             System.out.println("数据接收失败");
    47         }
    48         return "";
    49     }
    50     
    51     //释放资源
    52     public void release() {
    53         isRunning = false;
    54         ChatUtils.close(dis,client);
    55     }
    56 }
    View Code

    客户端发送:

     1 package 在线聊天室过渡版;
     2 
     3 import java.io.BufferedReader;
     4 import java.io.DataOutputStream;
     5 import java.io.IOException;
     6 import java.io.InputStreamReader;
     7 import java.net.Socket;
     8 
     9 /**
    10  * 为聊天室Client2 的发送功能服务
    11  * @author liuzeyu12a
    12  *
    13  */
    14 public class Send implements Runnable{
    15     //准备数据
    16     private BufferedReader reader;
    17     //发送数据
    18     private DataOutputStream dos;
    19     private Socket client;
    20     private boolean isRunning;
    21     private String name;
    22     //构造器
    23     public Send(Socket client,String name) {
    24         this.client = client ;
    25         this.isRunning = true;
    26         //获取名称
    27         this.name = name;
    28         reader= new BufferedReader(
    29                 new InputStreamReader(System.in));
    30         try {
    31             dos= new DataOutputStream(client.getOutputStream());
    32             send(name); //发送名称
    33         } catch (IOException e) {
    34             System.out.println("DataOutputStream对象创建失败");
    35             release();
    36         }    
    37     }
    38     @Override
    39     public void run() {
    40         while(isRunning) {
    41             String msg = null;
    42             try {
    43                 msg = reader.readLine();
    44             } catch (IOException e) {
    45                 System.out.println("数据写入失败");
    46                 release();
    47             }
    48             send(msg);
    49         
    50         }
    51     }
    52     public void send(String msg) {
    53         try {
    54             dos.writeUTF(msg);
    55             dos.flush();
    56         } catch (IOException e) {
    57             System.out.println("数据发送失败");
    58             release();
    59         }
    60     }
    61     //释放资源
    62     public void release() {
    63         ChatUtils.close(dos,client,reader);
    64     }
    65 }
    View Code

    客户端封装:

     1 package 在线聊天室过渡版;
     2 
     3 import java.io.BufferedReader;
     4 import java.io.IOException;
     5 import java.io.InputStreamReader;
     6 import java.net.Socket;
     7 
     8 /**
     9  * 可以实现简单的群聊了。
    10  * @author liuzeyu12a
    11  *
    12  */
    13 public class Client2 {
    14     public static void main(String[] args) throws IOException, IOException {
    15         System.out.println("-----Client-----");
    16         System.out.println("请输入用户名:");
    17         BufferedReader reader = new BufferedReader(
    18                 new InputStreamReader(System.in));
    19         String name = reader.readLine();
    20 
    21         //创建Socket套接字,绑定服务器端口
    22         Socket  client  =new Socket("localhost",8989);
    23         
    24         //发送数据
    25         new Thread(new Send(client,name)).start();
    26         //接收数据
    27         new Thread(new Receive(client)).start();
    28     }
    29 }
    View Code

    服务端:

      1 package 在线聊天室过渡版;
      2 
      3 import java.io.DataInputStream;
      4 import java.io.DataOutputStream;
      5 import java.io.IOException;
      6 import java.net.ServerSocket;
      7 import java.net.Socket;
      8 import java.util.concurrent.CopyOnWriteArrayList;
      9 
     10 /**
     11  * 可以实现简单的群聊了。
     12  * @author liuzeyu12a
     13  *
     14  */
     15 public class Chat2 {
     16     //用于存储客户端的容器,涉及到多线程的并发操作,
     17     //使用CopyOnWriteArrayList保证线程的安全
     18     private static CopyOnWriteArrayList<Channel> all = 
     19             new CopyOnWriteArrayList<Channel>();
     20     public static void main(String[] args) throws Exception {
     21         System.out.println("-----Server-----");
     22         //建立服务器端地址,并绑定本地端口
     23         ServerSocket server = new ServerSocket(8989);
     24         
     25         //这边加上死循环是为了接受多个客户的请求
     26         while(true) {
     27                 //监听
     28                 Socket    client = server.accept();
     29                 Channel c = new Channel(client);
     30                 all.add(c);   //添加一个客户端
     31                 System.out.println("一个客户端建立了连接");
     32                 new Thread(c).start();
     33         }        
     34     }
     35     //静态内部类,封装处理客户端的数据
     36     static class Channel implements Runnable{
     37         private DataInputStream dis;
     38         private DataOutputStream dos;
     39         private Socket client;
     40         private boolean isRunning;
     41         private String name;
     42         //构造器
     43         public Channel(Socket client) {
     44 
     45             this.client = client;
     46             this.isRunning = true;
     47             try {
     48                 dis = new DataInputStream(
     49                         client.getInputStream());
     50                 dos = new DataOutputStream(
     51                         client.getOutputStream());
     52                 this.name = receive(); //接收客户端的名称
     53                 this.send("欢迎光临聊天室..");
     54                 this.sendOther(this.name+"来到了聊天室...", true);
     55             } catch (IOException e) {
     56                 release();
     57             }
     58         }
     59         @Override
     60         public void run() {
     61             while(isRunning) {
     62                 String msg = receive();
     63                 if(!msg.equals("")) {
     64                     //send(msg);
     65                     sendOther(msg,false);
     66                 }
     67 
     68             }
     69         }
     70         
     71         //发送数据
     72         public void send(String msg) {
     73             try {
     74                 dos.writeUTF(msg);
     75                 dos.flush();
     76             } catch (IOException e) {
     77                 System.out.println("发送数据失败");
     78                 release();
     79             }
     80         }
     81         /**
     82          * 获取自己的消息,然后发送给其它人
     83          * boolean isSys表示是否为系统消息
     84          * @return
     85          */
     86         public void sendOther(String msg,boolean isSys) {
     87             for(Channel other:all) {
     88                 if(other == this) {  //不再自己发给自己了
     89                     continue;
     90                 }            
     91                 if(!isSys) {
     92                     other.send(this.name+"对大家说:"+msg); //发送给自己
     93                 }else {
     94                     other.send(msg);
     95                 }
     96             }
     97         }
     98         
     99         //接受数据
    100         public String receive() {
    101             try {
    102                 String msg = "";
    103                 msg = dis.readUTF();
    104                 return msg;
    105             } catch (IOException e) {
    106                 isRunning = false;
    107                 System.out.println("接受数据失败");
    108                 release();
    109             }
    110             return "";
    111         }
    112         
    113         //释放资源
    114         public void release() {
    115             this.isRunning = false;
    116             ChatUtils.close(client,dos,dis);
    117             all.remove(this);
    118             this.sendOther(this.name+"离开了聊天室...", true);
    119         }
    120     }
    121 }
    View Code

    4、群聊功能升级(可以实现私聊某一个人@)。

    只需要在发送消息的地方动手脚,其它的代码不变即可。

    约定私聊的格式:@xxx:消息内容

     1 /**
     2          * 获取自己的消息,然后发送给其它人
     3          * boolean isSys表示是否为系统消息
     4          * 添加私聊的功能:可以向某一特定的用户发送数据
     5          * 约定格式:@xxx:数据
     6          * @return
     7          */
     8         public void sendOther(String msg,boolean isSys) {
     9             //判断数据是否以@开头
    10             boolean isPrivate = msg.startsWith("@");
    11             if(isPrivate) {
    12                 //寻找:
    13                 int index = msg.indexOf(":");
    14                 //截取名字
    15                 String targetName = msg.substring(1, index);
    16                 //截取消息内容
    17                 String datas = msg.substring(index+1);
    18                 for(Channel other :all) {
    19                     if(other.name.equals(targetName)) {
    20                         other.send(this.name+"悄悄对你说:"+datas);
    21                     }
    22                 }
    23                 
    24             }else {
    25                 for(Channel other:all) {
    26                     if(other == this) {  //不再自己发给自己了
    27                         continue;
    28                     }            
    29                     if(!isSys) {
    30                         other.send(this.name+"对大家说:"+msg); //发送给自己
    31                     }else {
    32                         other.send(msg);
    33                     }
    34                 }
    35             }
    36             
    37         }

    服务端:

      1 package 在线聊天室终极版;
      2 
      3 import java.io.DataInputStream;
      4 import java.io.DataOutputStream;
      5 import java.io.IOException;
      6 import java.net.ServerSocket;
      7 import java.net.Socket;
      8 import java.util.concurrent.CopyOnWriteArrayList;
      9 
     10 /**
     11  * 可以实现简单的群聊了。
     12  * @author liuzeyu12a
     13  *
     14  */
     15 public class Chat2 {
     16     //用于存储客户端的容器,涉及到多线程的并发操作,
     17     //使用CopyOnWriteArrayList保证线程的安全
     18     private static CopyOnWriteArrayList<Channel> all = 
     19             new CopyOnWriteArrayList<Channel>();
     20     public static void main(String[] args) throws Exception {
     21         System.out.println("-----Server-----");
     22         //建立服务器端地址,并绑定本地端口
     23         ServerSocket server = new ServerSocket(8989);
     24         
     25         //这边加上死循环是为了接受多个客户的请求
     26         while(true) {
     27                 //监听
     28                 Socket    client = server.accept();
     29                 Channel c = new Channel(client);
     30                 all.add(c);   //添加一个客户端
     31                 System.out.println("一个客户端建立了连接");
     32                 new Thread(c).start();
     33         }        
     34     }
     35     //静态内部类,封装处理客户端的数据
     36     static class Channel implements Runnable{
     37         private DataInputStream dis;
     38         private DataOutputStream dos;
     39         private Socket client;
     40         private boolean isRunning;
     41         private String name;
     42         //构造器
     43         public Channel(Socket client) {
     44 
     45             this.client = client;
     46             this.isRunning = true;
     47             try {
     48                 dis = new DataInputStream(
     49                         client.getInputStream());
     50                 dos = new DataOutputStream(
     51                         client.getOutputStream());
     52                 this.name = receive(); //接收客户端的名称
     53                 this.send("欢迎光临聊天室..");
     54                 this.sendOther(this.name+"来到了聊天室...", true);
     55             } catch (IOException e) {
     56                 release();
     57             }
     58         }
     59         @Override
     60         public void run() {
     61             while(isRunning) {
     62                 String msg = receive();
     63                 if(!msg.equals("")) {
     64                     //send(msg);
     65                     sendOther(msg,false);
     66                 }
     67 
     68             }
     69         }
     70         
     71         //发送数据
     72         public void send(String msg) {
     73             try {
     74                 dos.writeUTF(msg);
     75                 dos.flush();
     76             } catch (IOException e) {
     77                 System.out.println("发送数据失败");
     78                 release();
     79             }
     80         }
     81         /**
     82          * 获取自己的消息,然后发送给其它人
     83          * boolean isSys表示是否为系统消息
     84          * 添加私聊的功能:可以向某一特地呢的用户发送数据
     85          * 约定格式:@xxx:数据
     86          * @return
     87          */
     88         public void sendOther(String msg,boolean isSys) {
     89             //判断数据是否以@开头
     90             boolean isPrivate = msg.startsWith("@");
     91             if(isPrivate) {
     92                 //寻找:
     93                 int index = msg.indexOf(":");
     94                 //截取名字
     95                 String targetName = msg.substring(1, index);
     96                 //截取消息内容
     97                 String datas = msg.substring(index+1);
     98                 for(Channel other :all) {
     99                     if(other.name.equals(targetName)) {
    100                         other.send(this.name+"悄悄对你说:"+datas);
    101                     }
    102                 }
    103                 
    104             }else {
    105                 for(Channel other:all) {
    106                     if(other == this) {  //不再自己发给自己了
    107                         continue;
    108                     }            
    109                     if(!isSys) {
    110                         other.send(this.name+"对大家说:"+msg); //发送给自己
    111                     }else {
    112                         other.send(msg);
    113                     }
    114                 }
    115             }
    116             
    117         }
    118         
    119         //接受数据
    120         public String receive() {
    121             try {
    122                 String msg = "";
    123                 msg = dis.readUTF();
    124                 return msg;
    125             } catch (IOException e) {
    126                 isRunning = false;
    127                 System.out.println("接受数据失败");
    128                 release();
    129             }
    130             return "";
    131         }
    132         
    133         //释放资源
    134         public void release() {
    135             this.isRunning = false;
    136             ChatUtils.close(client,dos,dis);
    137             all.remove(this);
    138             this.sendOther(this.name+"离开了聊天室...", true);
    139         }
    140     }
    141 }
    View Code

    截图:

    小结:

    1、模拟多人聊天室,代码比较多,重点在于多线程,TCP数据的传递,面向对象的封装。

    2、利用面向对象的思想可以对代码进行封装,简化代码,提高代码的可维护性。

    3、多个客户端可以在服务端使用容器进行装载。

    3、在使用容器中,多线程如果涉及到多个同步的操作,如聊天室中可能在聊天中忽然有人退出,有人加入,

    容易造成数据的错误发送和接收,可以使用JUC并发容器CopyOnWriteArrayList(再操作容器前copy一个副本存起来,一旦数据有错,就启用副本数据

    来保证数据的安全性)。

  • 相关阅读:
    解决ssh: connect to host github.com port 22: Connection refused
    sudo/su命令免密执行
    Linux tar.gz、tar、bz2、zip 等解压缩、压缩命令详解
    项目实战——校验文件名和邮箱地址
    项目实战:判断闰年平年并输出某月的天数
    ubuntu软件更新时出现没有Release文件
    项目实战:根据出生日期判断星座
    项目实战--实现淡旺季飞机票打折
    xxx.java:1: 错误: 类xxx是公共的, 应在名为 xxx.java 的文件中声明 public class xxx
    32位int整数范围
  • 原文地址:https://www.cnblogs.com/liuzeyu12a/p/10406715.html
Copyright © 2011-2022 走看看