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

时间:2017-11-15 06:26:35

标签: java multithreading sockets tcp

我正在使用TCP与多线程服务器进行简单的登录/注册模块。我想让我的服务器可以处理来自客户端的多个访问。我的第一个想法是使用客户端套接字列表来跟踪哪个客户端正在连接:accept()一个套接字 - 如果它在列表中然后找到列表并将其传递给函数继续 - 如果它& #39;不是,然后将其添加到列表然后将其传递给函数继续。它首次访问,但在第二次,它被卡住,客户端永远不会收到结果。你能告诉我我做错了什么,我该怎么办才能解决这类问题?谢谢!

服务器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();
    }
}

1 个答案:

答案 0 :(得分:3)

  

我的第一个想法是使用客户端套接字列表来跟踪哪个客户端正在连接:accept()一个套接字 - 如果它在列表中,那么找到它并将其传递给函数继续 - 如果它不是,然后将其添加到列表然后将其传递给函数继续。

为什么呢?它不会在列表中。这是一个新的联系。它不可能在列表中。那么, 的列表究竟是什么?你不需要它。只需为每个接受的套接字启动一个新的完全独立的线程。

  

它首次访问,但在第二次,它被卡住,客户端永远不会收到结果。你能告诉我我做错了什么,我该怎么办才能解决这类问题?谢谢!

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

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