Java - 如何检查 ServerSocket.accept() 是不是连接?

Posted

技术标签:

【中文标题】Java - 如何检查 ServerSocket.accept() 是不是连接?【英文标题】: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 可以。 您的标题与您的问题不符。请澄清。 【参考方案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 上没有找到活动套接字,那么它将启动一个新的服务器套接字,或者您可以更改它启动套接字,否则您可以连接到现有套接字。

【讨论】:

不回答以任何方式提出的问题。回答前请阅读问题。

以上是关于Java - 如何检查 ServerSocket.accept() 是不是连接?的主要内容,如果未能解决你的问题,请参考以下文章

Java 实例演示-ServerSocket 和 Socket 通信实例

Java网络编程精解之ServerSocket用法详解一

Java - 无法与 ServerSocket 连接

java ServerSocket

java通过ServerSocket与Socket实现通信

java通过ServerSocket与Socket实现通信