📜  Java中的多线程聊天应用程序| Set 1(服务器端编程)(1)

📅  最后修改于: 2023-12-03 15:16:32.129000             🧑  作者: Mango

Java中的多线程聊天应用程序| Set 1(服务器端编程)

简介

本文介绍了如何使用Java的多线程特性来开发一个多用户聊天室服务器程序的编程方法。这个程序使用了Java的Socket编程API,使得多个客户端可以与服务器建立连接,并在不互相干扰的情况下进行聊天。

代码片段

下面的代码片段演示了如何使用Java的Socket编程API建立服务器与客户端之间的连接,同时使用Java线程来管理每个连接。

public class ChatServer {
    private ServerSocket serverSocket;
    private List<ClientThread> clients = new ArrayList<>();

    public ChatServer(int port) {
        try {
            serverSocket = new ServerSocket(port);
        } catch (IOException e) {
            System.out.println("Could not create server on port " + port);
            System.exit(-1);
        }
    }

    public static void main(String[] args) {
        int port = 8888;
        if (args.length > 0) {
            try {
                port = Integer.parseInt(args[0]);
            } catch (NumberFormatException e) {
                System.out.println("Invalid port number, using default port: " + port);
            }
        }

        ChatServer server = new ChatServer(port);
        server.start();
    }

    public void start() {
        System.out.println("Server started on port " + serverSocket.getLocalPort());
        while(true) {
            try {
                Socket socket = serverSocket.accept();
                ClientThread clientThread = new ClientThread(clients.size() + 1, socket, this);
                clients.add(clientThread);
                new Thread(clientThread).start();
            } catch (IOException e) {
                System.out.println("Error accepting client connection");
            }
        }
    }

    public void broadcastMessage(String message, int senderId) {
        for (ClientThread thread : clients) {
            if (thread.getClientId() != senderId) {
                thread.sendMessage(message);
            }
        }
    }

    public void removeClient(ClientThread clientThread) {
        clients.remove(clientThread);
    }
}

class ClientThread implements Runnable {
    private int clientId;
    private Socket clientSocket;
    private ChatServer server;
    private BufferedReader reader;
    private PrintWriter writer;

    public ClientThread(int clientId, Socket clientSocket, ChatServer server) {
        this.clientId = clientId;
        this.clientSocket = clientSocket;
        this.server = server;

        try {
            reader = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
            writer = new PrintWriter(clientSocket.getOutputStream(), true);
        } catch (IOException e) {
            System.out.println("Error creating input/output streams for client");
        }
    }

    public void run() {
        String inputLine;
        try {
            while ((inputLine = reader.readLine()) != null) {
                System.out.println("Client " + clientId + " says: " + inputLine);
                server.broadcastMessage("Client " + clientId + ": " + inputLine, clientId);
            }
        } catch (IOException e) {
            System.out.println("Error reading from client");
        } finally {
            try {
                clientSocket.close();
            } catch (IOException e) {
                System.out.println("Error closing client socket");
            }
            server.removeClient(this);
        }
    }

    public void sendMessage(String message) {
        writer.println(message);
    }

    public int getClientId() {
        return clientId;
    }
}

以上代码片段包含了两个类:ChatServer和ClientThread。ChatServer类包含了服务器的主要逻辑,可以监听并接受客户端连接,并创建一个新的线程(ClientThread)处理每一个连接。ClientThread类表示一个客户端连接的线程。

解析

在ChatServer中,我们首先需要创建一个ServerSocket对象,监听一个指定的端口。一旦有客户端连接,就会调用accept方法,返回一个表示连接的Socket对象。我们接下来就需要为每个连接创建一个ClientThread实例,并将其添加到已连接客户端列表中。然后我们启动一个新的线程来执行这个ClientThread实例。

在ClientThread中,我们使用BufferedReader和PrintWriter对象处理输入和输出。我们在run方法中使用一个while循环来处理客户端输入,如果输入为null就代表客户端已经关闭了连接。如果从输入流中读取到了一行数据,那么我们就将其发送到所有已连接客户端(除了这个发送者)。

当客户端关闭了连接时,就会调用finally块中的代码,包括关闭客户端连接的Socket对象,并从服务器已连接客户端列表中移除该客户端对应的ClientThread实例。

总结

本文介绍了如何使用Java的多线程特性编写一个多用户聊天服务器程序。通过解析上文开头的代码片段,不难看出Java的Socket编程API以及线程API在此中的应用。这个程序还有许多可以改进和优化的部分,例如添加密码验证、保存聊天记录等等。