【问题标题】:Socket Programming : Client Disconnection keeps server hanging套接字编程:客户端断开连接使服务器挂起
【发布时间】:2018-10-19 14:30:00
【问题描述】:

我正在尝试构建一个示例 TCP 转发器。以下是功能简介:

  1. 转发器将侦听给定端口。
  2. 它包含客户端到服务器的映射
  3. 客户端将连接到转发器,转发器将查找地图并创建 2-way-forwarding-connection。
  4. 为此,它为每个客户端创建两个线程。
  5. 线程 1:从客户端读取并写入目标服务器
  6. 线程 2:从目标服务器读取并写入客户端。

所有这些都是用 C 编写的。 客户端和目标服务器可以用任何语言编写,现在是 Java。

当我第一次运行客户端时,它按预期工作。但是,如果我终止客户端并重新启动它,服务器将永远不会收到新连接。

这是我怀疑是错误的服务器代码。

Socket clientSocket = serverSocket.accept();
InputStream inputStream = clientSocket.getInputStream();
OutputStream outputStream = clientSocket.getOutputStream();

while (true) {
    byte[] bArray = new byte[2048];
    try {
        System.out.println(String.format("SERVER:%s: Attempting to read", this.name));
        inputStream.read(bArray);
        System.out.println(String.format("SERVER:%s: Received %s", this.name, new String(bArray)));
        byte[] bytes = (name + ":" + counter).getBytes();
        counter++;
        outputStream.write(bytes);
        System.out.println(String.format("SERVER:%s: Sent %s", this.name, new String(bytes)));
    } catch (IOException e) {
        System.out.println(String.format("SERVER:%s: Client Disconnected ", this.name));
        clientSocket = serverSocket.accept();
        inputStream = clientSocket.getInputStream();
    }
}

在C程序中,我检测到断开连接并关闭socket,如下图:

LOGINFO("Reading from Client Socket.");
iResult = read(readSocket, buff, recvbuflen);
if (iResult <= 0) {
    LOGERROR("Receiving failed");
    close(readSocket);          
    break;
}

【问题讨论】:

标签: java c sockets server client


【解决方案1】:

你应该使用

   shutdown(socket_fd, SHUT_WR);

而不是close(socket_fd),以便正确关闭套接字。

如果您使用 SHUT_WR,则会向另一端发送一个 FIN 数据包,通知他们我们没有更多数据要发送。

【讨论】:

    【解决方案2】:

    尝试通过使用并发来管理每个请求来修改您的服务器逻辑。这样,服务器将能够在一个线程中分别处理每个客户端。读写数据必须在相关线程中进行。池线程范式通常用于避免线程开销[1]

    例如:

    ExecutorService threadPool = Executors.newFixedThreadPool(n);
    ServerSocket serverSocket = null;
    
    //...
    
    while(!isStopped()){
       Socket clientSocket = null;
       try {
           clientSocket = this.serverSocket.accept();
           threadPool.execute(new WorkerRunnable(clientSocket));
           // Process data in the WorkerRunnable class
       } catch (IOException e) {
           if(isStopped()) {
               System.err.println("Server Stopped.") ;
               break;
           }
           throw new RuntimeException("Error accepting client connection", e);
       } 
    }
    

    一个精心设计的例子可以在这里找到:http://tutorials.jenkov.com/java-multithreaded-servers/thread-pooled-server.html

    【讨论】:

    • 但它不能解决重新连接的初始问题。如果您有一个要求,即您始终只有一个连接,则完全可以在同一个线程中完成。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多