TCP的多线程聊天室

在服务器端应该包含多条线程,每个Socket对应一条线程,该线程负责读取Socket对应的输入流的数据(从客户端发送过来的数据),并将读到的数据向每个Socket输出流发送一遍(将一个客户端发送的数据广播给其他客户端),因此需要在服务端使用List来保存所有的Socket。

服务器端提供两个类:

创建ServerSocket监听的主类;

处理每个Socket通信的线程类;

public class IServer {
        public static ArrayList<Socket> socketList=new ArrayList<Socket>();
        
        public static void main(String[] args) throws IOException{
               ServerSocket ss=new ServerSocket(30000);
               while(true) {
                       Socket s=ss.accept();
                       socketList.add(s);
                       new Thread(new Serverxian(s)).start();
                       }
        }
}

服务器端只负责接受客户端Socket的连接请求,每当客户端Socket连接诶到该ServerSocket之后,程序将对应Socket加入socketList集合中保存,并为该Socket启动一条线程,该线程负责处理该Socket所有的通信任务。

public class Serverxian implements Runnable{
        Socket s=null;
        BufferedReader br=null;
        public Serverxian(Socket s) throws IOException{
                this.s=s;
                br=new BufferedReader(new InputStreamReader(s.getInputStream()));
        }
        public void run() {
                try {
                        String content=null;
                        while((content=readFromClient())!=null) {
                                for(Socket s:IServer.socketList) {
                                        PrintStream ps=new PrintStream(s.getOutputStream());
                                        ps.println(content);
                                }                                     
                        }                           
                }catch(IOException e) {      }
        }      
        private String readFromClient() {
                try {
                        return br.readLine();
                }catch(IOException e) {
                        IServer.socketList.remove(s);
                }
                return null;
        }
}

捕获到异常,则说明客户端Socket出现了问题,删除掉;读到客户端数据之后遍历整个集合,转发数据。

每个客户端应包含的两条线程:

1、一条负责读取用户的键盘输入,并将用户输入的数据写入Socket对应的输出流中;

2、一条负责读取Socket对应输入流中的数据(从服务器发送过来的数据),并将爱那个这些数据打印输出。

public class ICilent {
        public static void main(String[] args) throws IOException{
                Socket s=new Socket("127.0.0.1",30000);
                new Thread(new Clientxian(s)).start();
                PrintStream ps=new PrintStream(s.getOutputStream());
                String line=null;
                BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
                while((line=br.readLine())!=null) {
                        ps.println(line);
                }
        }
}

线程读到数据后,会将用户键盘输入的内容写入该Socket对应的输出流。当主线程使用Socket连接到服务器后,会启动Clientxian来处理该线程的Socket通信。

public class Clientxian implements Runnable{
        private Socket s;
        BufferedReader br=null;
        public Clientxian(Socket s)throws IOException{
                this.s=s;
                br=new BufferedReader(new InputStreamReader(s.getInputStream()));
        }
        public void run() {
                try {
                        String content=null;
                        while((content=br.readLine())!=null) {
                                System.out.println(content);
                        }
                }catch(Exception e) {
                        e.printStackTrace();
                }
        }
}

线程处理文件,负责读取Socket输入流中的内容,并将这些内容在控制台打印出来。

猜你喜欢

转载自blog.csdn.net/qq_40722284/article/details/81412598