Java - TCP - 多线程服务器 - 如何处理多个客户端连接?

标签 java multithreading sockets tcp

我正在使用 TCP 和多线程服务器做一个简单的登录/注册模块。我想让我的服务器能够处理来自客户端的多次访问。我的第一个想法是使用客户端套接字列表来跟踪哪个客户端正在连接:accept() 一个套接字 - 如果它在列表中,然后在列表中找到它并将它传递给函数以继续 - 如果不在,则添加它到列表然后将它传递给函数以继续。它在第一次访问时工作,但在第二次访问时,它被卡住了,客户端从未收到结果。你能告诉我我做错了什么吗?我应该怎么做才能处理这种问题?谢谢!

服务器 run() 方法:

@Override
public void run() {
    Socket socket = new Socket();

    try {
        Socket clientSocket = myServer.accept();

        if (!listSocket.contains(clientSocket)) {
            socket = clientSocket;
            listSocket.add(clientSocket);
        } else {
            for (Socket s : listSocket) {
                if (s == clientSocket) {
                    socket = clientSocket;
                    break;
                }
            }
        }
    } catch (Exception ex) {
        ex.printStackTrace();
    }

    while (true) {
        ReceiveObject(socket);
    }
}

ReceiveObject() 方法:

// Receive an object[2]
// the object[0] contains Account object
// the object[1] contains Customer object
// if the object[0] is not null and the object[1] is null => this is a login request
// if both object[0] and object[1] are not null => signup request

public void ReceiveObject(Socket clientSocket) {
    try {
        ObjectInputStream ois = new ObjectInputStream(clientSocket.getInputStream());
        Object o = ois.readObject();

        if (o instanceof Object[]) {
            Object[] arr = (Object[]) o;
            if (arr[0] != null && arr[0] instanceof Account && arr[1] == null) {
                Account acc = (Account) arr[0];
                if (CheckAccountExist(acc)) {
                    SendResult("OK", clientSocket);
                } else {
                    SendResult("FAILED", clientSocket);
                }
            } else if (arr[0] != null && arr[1] != null && arr[0] instanceof Account && arr[1] instanceof Customer) {
                Account acc = (Account) arr[0];
                Customer cus = (Customer) arr[1];

                String result = "";

                if (!CheckAccountExist(acc)) {
                    result = "OK";

                    if (AddAccount(acc)) {
                        if (!CheckCustomerExist(cus)) {
                            if (AddCustomer(cus)) {
                                SendResult(result, clientSocket);
                            } else {
                                result = "FAILED";
                                SendResult(result, clientSocket);
                            }
                        }
                    } else {
                        result = "FAILED";
                        SendResult(result, clientSocket);
                    }
                } else {
                    result = "FAILED";
                    SendResult(result, clientSocket);
                }
            }
        }
    } catch (Exception ex) {
        ex.printStackTrace();
    }
}

最佳答案

My first idea was to use a list of client socket to keep track of which client is connecting: accept() a socket - if it's in the list then find it the list and pass it to function to proceed - if it's not, then add it to the list then pass it to function to proceed.

为什么?它不会在列表中。这是一个新的连接。它不可能在列表中。因此, 列表到底是什么?你不需要它。只需为每个接受的套接字启动一个新的且完全独立的线程。

It works for the first time access, but in the second time, it's jammed and the client never receive the result. Could you tell me what did I do wrong and what should I do to handle this kind of problem? Thanks!

扔掉它,好好看看 Java 教程的自定义网络部分。

注意您应该在套接字的生命周期内使用相同的对象流。您不需要带有 Socket 参数的方法:Socket 应该是处理连接的 Runnable 类的成员变量。对象流也应该如此。

关于Java - TCP - 多线程服务器 - 如何处理多个客户端连接?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47300736/

相关文章:

c - 在 Linux 中通过 RAW 套接字重新发送数据包

c++ - Erlang 和 C/C++ 线程

Java 多线程和安全发布

php - 在同一环境中运行的 2 个版本的 PHP 之间丢失

java - 如何实现广度优先搜索到一定深度?

iphone - 委托(delegate)和执行SelectorOnMainThread

c - epoll_wait() 阻止打印到标准输出

java - Apache POI - 提取列中的所有不同值

java - 在java中使用for循环填充HashMap

java - GLSL 着色器 : Interpolate between more than two textures