【问题标题】:Java - how can I check if the ServerSocket.accept()ed the connection?Java - 如何检查 ServerSocket.accept() 是否连接?
【发布时间】:2017-03-04 23:55:29
【问题描述】:

我正在尝试编写简单的服务器-客户端聊天解决方案。出于测试目的,我创建了一个包含 2 个 serverThreads 的数组,它们负责从连接的客户端发送和接收消息。

我希望服务器在连接的客户端数量达到最大值后拒绝连接。但是,即使服务器不接受连接,也会创建客户端的套接字。 socket.isBound 和 isConnected 方法都返回真值。

回到主要问题。 当 ServerSocket 无法 .accept() 附加连接时,您有什么想法如何拒绝客户端连接?

这是 Server 类的代码。

public class Server {

private ServerSocket serverSocket = null;
private ServerThread serverThread[] = new ServerThread[2];
protected volatile int clientCount = 0;

public Server (int port){
   try {
       System.out.println("Binding to port " + port + " ...");
       serverSocket = new ServerSocket (port);
       System.out.println("Binded to port " + port + ".");
   } catch (IOException e) {
       System.out.println("Failed binding to the port: " + e.getMessage());
        }
}

public void addThread (Socket socket){

   System.out.println ("Client connected at socket: " + socket);
   serverThread[clientCount] = new ServerThread (this, socket);
   try {
       serverThread[clientCount].open();
       serverThread[clientCount].start();
   } catch (IOException e) {e.getMessage();}

}

public void waitForClient () {

   boolean isLogPrinted = false;

   while (true){
       try {
           if (clientCount < serverThread.length){
               System.out.println ("Waiting for connection...");
               isLogPrinted = false;
               addThread (serverSocket.accept());
               clientCount++;
               System.out.println("Client count: " + clientCount);
           }
           else {
               if (!isLogPrinted){
                    System.out.println("MAXIMUM NUMBER OF CLIENTS REACHED! (" + clientCount + ").");
                    isLogPrinted = true;
               }
           }
       } catch (IOException e) {
           System.out.println("Error while waiting for new clients to connect: " + e.getMessage());
            }
   }
}

public synchronized void broadcastMessages (String msg){
   for (int i = 0; i < clientCount; i++)
       serverThread[i].sendMessage(msg);
}

public static void main (String args[]){
   Server server = new Server (4200);
   server.waitForClient();
 }

}

【问题讨论】:

  • 除非您向客户展示您的代码,否则您的问题将很难或无法回答。
  • @PresidentJamesMoveonPolk 显然不是。您只需要一个连接客户端。它不需要做任何其他事情。 Telnet 可以。
  • 您的标题与您的问题不符。请澄清。

标签: java multithreading sockets server client-server


【解决方案1】:

在你的waitForClient方法中尝试这个而不是while true

private final int allowedClients = 10;
private int connectedClients = 0;
public void waitForClient () {

boolean isLogPrinted = false;

while (connectedClients <= allowedClients){
    try {
       if (clientCount < serverThread.length){
           System.out.println ("Waiting for connection...");
           isLogPrinted = false;
           addThread (serverSocket.accept());
           connectedClients++;
           System.out.println("Client count: " + clientCount);
       }
       else {
           if (!isLogPrinted){
                System.out.println("MAXIMUM NUMBER OF CLIENTS REACHED! (" + clientCount + ").");
                isLogPrinted = true;
           }
       }
   } catch (IOException e) {
       System.out.println("Error while waiting for new clients to connect: " + e.getMessage());
        }

} }

【讨论】:

  • 好的,但问题还是一样。即使服务器不接受连接,仍然可以毫无问题地创建客户端上的套接字。我正在寻找一种方法来检查服务器是否提交了 server.accept() 操作。
  • 如果您在达到最大客户端数量后读取循环条件,服务器将停止侦听进一步的连接,最终客户端将无法连接
  • 我提供的解决方案也阻止了 ServerSocket 的 .accept()ing 传入连接。 重点是client端的socket仍然是创建的,没有任何异常。当 ServerSocket 不接受连接时,为什么会发生这种情况?
  • 如果条件为假,此代码将无意识地旋转 至少在其中添加一个睡眠。进行两次测试的意义让我无法理解。
【解决方案2】:

我希望服务器在连接的客户端数量达到最大值后拒绝连接。

关闭服务器套接字。

但是,即使服务器不接受连接,也会创建客户端的套接字。方法socket.isBoundisConnected 都返回真值。

正确。这是因为 TCP 维护了一个“积压队列”,其中包含已完成但尚未被服务器应用程序接受的传入连接。

回到主要问题。当 ServerSocket 无法 .accept() 附加连接时,您有什么想法如何拒绝客户端连接?

在连接数达到最大值时关闭服务器套接字。

但是由于积压,这种技术永远不可能完美。没有完美的解决方案。您可以让服务器立即关闭多余的连接,但多余的客户端在尝试发送某些内容之前不会检测到这一点。如果您需要完美,您可能必须引入一个应用程序协议,据此服务器会相应地发送“接受”或“拒绝”之类的内容。

【讨论】:

    【解决方案3】:

    我知道回答这个问题已经很晚了,但我认为这会对很多人有所帮助。 您可以通过以下代码检查现有的套接字。

    SocketAddress socketAddress = new InetSocketAddress("localhost", 8091);
        Socket socket = new Socket();
        ServerSocket serverSocket = null;
        try {
            socket.connect(socketAddress);
        } catch (IOException e) {
            e.printStackTrace();
        }
        if(socket == null) {
            try {
                serverSocket = new ServerSocket(8091);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    

    如果在同一端口和 IP 上没有找到活动套接字,那么它将启动一个新的服务器套接字,或者您可以更改它启动套接字,否则您可以连接到现有套接字。

    【讨论】:

    • 不回答以任何方式提出的问题。回答前请阅读问题。
    猜你喜欢
    • 2013-02-20
    • 1970-01-01
    • 1970-01-01
    • 2022-10-25
    • 1970-01-01
    • 2012-08-05
    • 2015-06-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多