java Socket实现简单在线聊天(二)

时间:2023-12-11 19:59:44

接《java Socket实现简单在线聊天(一)》,在单客户端连接的基础上,这里第二步需要实现多客户端的连接,也就需要使用到线程。每当有一个新的客户端连接上来,服务端便需要新启动一个线程进行处理,从而解决之前的循环读取中造成阻塞的问题。

写线程通常有两种方法,集成Thread或者实现runnable接口,原则上是能实现runnable的情况下就不继承,因为实现接口的方式更加灵活。

客户端代码相较之前没有变化,变得是服务端,因此这里便只贴出服务端代码:
package chat.chat;

import java.io.DataInputStream;
import java.io.EOFException;
import java.io.IOException;
import java.net.BindException;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketException;

/**
 * java使用socket和awt组件以及多线程简单实现在线聊天功能服务端 : 实现多个客户端连接后不断向服务端发送消息,
 * 相对于第一个版本,重点在于使用了多线程。服务端还未实现转发功能,客户端图形窗口中只能看到自己输入的信息, 不能看到其他客户端发送的消息
 *
 * @author tuzongxun123
 *
 */
public class ChatServer {

    public static void main(String[] args) {
        new ChatServer().start();
    }

    // 是否成功启动服务端
    private boolean isStart = false;
    // 服务端socket
    private ServerSocket ss = null;
    // 客户端socket
    private Socket socket = null;

    public void start() {
        try {
            // 启动服务器
            ss = new ServerSocket(8888);
        } catch (BindException e) {
            System.out.println("端口已在使用中");
            // 关闭程序
            System.exit(0);
        } catch (Exception e) {
            e.printStackTrace();
        }

        try {
            isStart = true;
            while (isStart) {
                // 启动监听
                socket = ss.accept();
                System.out.println("one client connect");
                // 启动客户端线程
                Client client = new Client(socket);
                new Thread(client).start();
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            // 关闭服务
            try {
                ss.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    }

    /**
     * 客户端线程
     *
     * @author tuzongxun123
     *
     */
    class Client implements Runnable {
        // 客户端socket
        private Socket socket = null;
        // 客户端输入流
        private DataInputStream dataInputStream = null;
        private boolean isConnect = false;

        public Client(Socket socket) {
            this.socket = socket;
            try {
                isConnect = true;
                // 获取客户端输入流
                dataInputStream = new DataInputStream(socket.getInputStream());
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        @Override
        public void run() {
            isConnect = true;
            try {
                while (isConnect) {
                    // 读取客户端传递的数据
                    String message = dataInputStream.readUTF();
                    System.out.println("客户端说:" + message);
                }
            } catch (EOFException e) {
                System.out.println("client closed!");
            } catch (SocketException e) {
                System.out.println("Client is Closed!!!!");
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                // 关闭相关资源
                try {
                    dataInputStream.close();
                    socket.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

    }

}