使用网络流实现多人聊天室

实现多人聊天室,运用到网络流,线程,IO流等知识点.

什么是网络流,如何使用网络流,附上链接:java网络编程 - Tmillion - 博客园 (cnblogs.com)

分析:

实现多个人聊天,就有多个客户端,在点对点通信里,由服务器端指明端口号,在客户端请求服务器地址,端口,与服务器进行连接即能完成通信.

那么多个人在一个群里聊天,怎么让多个人连接到同一个服务器呢?在服务器端使用线程,有一个客户端连接,就创建一个线程与该客户端连接

实现:

每个客户端创建两个线程,一个用来发送消息,一个用来接收消息,

这里的服务器端就负责转发消息,里面的线程也需要完成读写操作,顺序是先接收信息,然后写出去

 

下面展示代码

客户端:

public class Client3 {
    public static void main(String[] args) throws IOException {
        Socket socket = new Socket("127.0.0.1",8888);//
        new SendThread(socket).start();//发送线程
        new ReceiveThread("服务器",socket).start();//接收线程
    }
127.0.0.1表示本地服务器地址,8888为端口号,创建两个线程来负责读和写操作.

客户端发送消息:
public class SendThread extends  Thread {
    private Socket socket;
    private boolean flag = true;
    Scanner input = new Scanner(System.in);

    public SendThread(Socket socket) {
        this.socket = socket;
    }

    //一直在写
    @Override
    public void run() {
        while(flag){
            send(input.next());
        }
    }

    //发送
    public void send(String str){
        BufferedWriter bw = null;
        try {
            OutputStream out = socket.getOutputStream();
            bw = new BufferedWriter(new OutputStreamWriter(out));
            //发送数据
            bw.write(str);
            bw.newLine(); //写了换行符
            bw.flush(); //刷新缓存区
        } catch (IOException e) {
           flag = false;
           CloseUtil.close(bw,socket);
        }
    }
}

发送消息相当于IO流中的写操作

客户端接收消息:

public class ReceiveThread  extends Thread{
    private Socket socket;
    private boolean flag = true;

    public ReceiveThread(String name, Socket socket) {
        super(name);
        this.socket = socket;
    }

    //一直读
    @Override
    public void run() {
        while(flag){
            //读 接收
            String receive = receive();
            System.out.println(receive);
        }
    }

    //接收方法
    public String receive() {
        BufferedReader br = null;
        try {
            InputStream in = socket.getInputStream();
            br = new BufferedReader(new InputStreamReader(in));
            //接收数据
            String line = br.readLine(); //阻塞方法, 读到行结尾  换行符
            return this.getName()+"说:"+line;
        } catch (IOException e) {
            flag = false;
            CloseUtil.close(br,socket);
        }
        return "";
    }
}

 

服务器端:

public class Server4 {
    public static List<Socket> clients = new ArrayList<>();
    public static void main(String[] args) throws IOException {
        ServerSocket serverSocket = new ServerSocket(8888);
        int i = 1;
        while(true){
            Socket client = serverSocket.accept();//阻塞
            System.out.println("有客户端连接");
            clients.add(client);
            //有一个客户端连接,创建一个线程与该客户端连接
            Server4Thread server4Thread = new Server4Thread("客户端"+i,client);
            //启动线程
            server4Thread.start();
            i++;
        }

    }
}

在服务器端创建ServerSocket,写一个死循环,如果一直有客户端接入,就不断创建线程来连接

服务器转发(先接收后写出):

public class Server4Thread  extends  Thread{
    private Socket socket;

    public Server4Thread(String name, Socket socket) {
        super(name);
        this.socket = socket;
    }

    @Override
    public void run() {
        //一直先读后发
        while(true){
            sendOther(receive());
        }
    }

    //接收
    public String receive(){
        BufferedReader br = null;
        try {
            InputStream in = socket.getInputStream();
            //把它变为字节流---->读取字节流
            br = new BufferedReader(new InputStreamReader(in));
            //接收数据
            String line = br.readLine(); //阻塞方法, 读到行结尾  换行符
            return this.getName()+"说:"+line;
        } catch (IOException e) {
            CloseUtil.close(br,socket);
        }
        return "";
    }
    //发送,转发给其他人
    public void sendOther(String str){
        List<Socket> clients = Server4.clients;
        for (Socket client : clients) {
            //排除自己
            if(client != socket){
                send(str,client);
            }
        }
    }

    //发送
    public void send(String str,Socket socket){
        BufferedWriter bw = null;
        try {
            OutputStream out = socket.getOutputStream();
            bw = new BufferedWriter(new OutputStreamWriter(out));
            //发送数据
            bw.write(str);
            bw.newLine(); //写了换行符
            bw.flush(); //刷新缓存区
        } catch (IOException e) {
            CloseUtil.close(bw,socket);
        }
    }
}

模拟多个人,这里的客户端需要开启多遍,设置:

 

 1.根据图片,点击蓝色那栏

 

 2.选中要运行多次的程序,勾选右上角的Allow parallel run,最后选中Apply,然后点击OK,完成!

注意:先启动服务器,再启动客户端

posted @ 2022-09-04 21:31  Tmillion  阅读(540)  评论(0编辑  收藏  举报