代码之家  ›  专栏  ›  技术社区  ›  James Holland

如何获取socket.shutdown以引发socketException?

  •  3
  • James Holland  · 技术社区  · 14 年前

    MSDN声明 Socket.Shutdown 可以扔 SocketException . 在我的客户机和服务器之间引入负载均衡器之后,最近我在生产中遇到了这种情况。但是,在没有负载均衡器的测试中,我不能复制它。你能?

    一些背景知识-我有一个用c编写的服务器应用程序,它使用 TCP 与客户端通信的套接字。服务器的应用程序协议非常简单:接受连接、读取请求、发送响应、等待客户端关闭(读取预期为0字节)、关闭。

    此代码已在生产中多年没有问题。然而,在多台服务器机器上引入负载均衡器之后,服务器进程中的一个由于未处理而崩溃。 插座异常 服务器调用时引发的 Socket.Shutdown . 特定客户端在等待服务器响应时超时,并试图提前关闭连接。服务器上的异常消息是“远程主机强制关闭了现有连接”。客户端这样做并不罕见,但显然在负载平衡器之前,服务器在代码中的另一点引发此错误。尽管如此,这显然是一个服务器错误,修复是显而易见的-处理异常。

    但是,使用测试客户机应用程序(也用c编写),我找不到会导致服务器在 套接字。关闭 . 看来,负载平衡器做了一些不寻常的 传输控制协议 包,但我仍然不喜欢使用它作为未能重现问题的借口。

    我可以在debug中运行服务器和客户机代码,我让wireshark监视数据包。

    在客户端,建立连接后,操作如下:

    Socket.Send() // single call
    Socket.Receive() // this one times out in our scenario
    Socket.XXX() // various choices as described below
    

    在服务器端,建立连接后,操作如下:

    1) Socket.Receive() //multiple calls until complete message is received
    2) // Processing...
    3) Socket.Write() //single call
    4) Socket.Receive() // single call expecting 0 bytes
    5) Socket.Shutdown()
    

    假设每个呼叫都有 try..catch(SocketException)

    a)如果在步骤2中暂停服务器,等待客户端超时,并启动客户端停机使用 Socket.Shutdown(SocketShutDown.Send) 一个fin包被发送到服务器。当服务器恢复处理时,所有的调用都会成功(3到5),因为这是一个完全可接受的TCP流。

    B)如果在步骤2中暂停服务器,等待客户端超时,并启动客户端停机使用 Socket.Shutdown(SocketShutDown.Both) Socket.Close() 再次向服务器发送fin数据包。当服务器恢复时,处理步骤3成功,但它使客户端响应于不接收更多数据而发送RST包。如果这个RST在步骤4之前到达 Socket.Receive 投掷,第5步成功。如果它在步骤4之后到达,那么 套接字.接收 成功(返回0字节),但步骤5成功。

    c)如果客户端有“不逗留”设置(使用0超时启用逗留),并且在处理期间暂停服务器,等待客户端超时,并启动客户端停机使用 socket.shutdown(socketshutdown.both) 套接字。关闭() “rst”数据包立即发送到服务器。当服务器恢复处理时,步骤3和4将失败,但步骤5仍然成功。

    我想最让我困惑的是 套接字。关闭 似乎忽略了我的测试客户端RST包,但显然我的负载均衡器能够发送一个不被忽略的RST包。我错过了什么?我还能试什么?

    0 回复  |  直到 14 年前