【问题标题】:what happand to socket, when the other end close it?当另一端关闭它时,套接字发生了什么?
【发布时间】:2018-07-31 19:41:47
【问题描述】:

我想开发一个客户端服务器应用程序,我想让它尽可能健壮。有很多问题要问我,我只是在互联网上找不到明确的答案。 假设服务器在 while(TRUE) 循环上运行并检查命令是否存在是它的命令队列,如果有,它发送它,如果没有,它只是继续循环的头部. 但是如果另一端宕机了,或者两者之间出现连接错误,socket值会发生什么变化,会不会变成INVALID_SOCKET呢?

while (TRUE) {
       if (ReqQueue->size() != 0 && ReqQueue->front() != string("STOP")) { // there is some command in the ReqQueue which is NOT STOP.
           int sent = send(ClientSocket, ReqQueue->front().c_str(), (int)strlen(ReqQueue->front().c_str()), 0);
           if (sent == (int)strlen(ReqQueue->front().c_str()))
               ReqQueue->pop(); // Next Command.
           else if (int err = WSAGetLastError() == WSAETIMEDOUT){
                   shutdown(ClientSocket, SD_BOTH);
                   closesocket(ClientSocket);
                   return;
            }
        else 
            continue;
    }
    else if (ReqQueue->size() == 0) {
        continue;
    }
    else if(ReqQueue->front() == string("STOP"))
    {
        if (send(ClientSocket, "STOP", strlen("STOP"), 0) == strlen("STOP")) {
            /*Message received indication from target*/
            shutdown(ClientSocket, SD_BOTH);
            closesocket(ClientSocket);
            return;
        }
    }
}
shutdown(ClientSocket, SD_BOTH);
closesocket(ClientSocket);
return 0;

这就是来源:)

我想问的是,有没有更好的方法来实现上述目标,也许我可以将while循环条件更改为while(套接字正常)或while(仍有连接)。

【问题讨论】:

  • 如果 (TCP) 连接的另一端关闭其套接字,那么您的下一个 recv 调用将返回 0 指示关闭。尝试继续使用套接字会导致错误。
  • 刚刚由触发,我想让它尽可能健壮";您是否考虑过应用诸如 http 之类的高级协议?有大量(经过测试的)库实现了这种东西。
  • 在一个不相关的注释中,std::stringoperator== overloads 接受指向常量字符串的指针(如字符串文字)。这意味着您不需要string("STOP") 进行比较。做例如ReqQueue->front() == "STOP" 应该也能正常工作。
  • “有没有更好的方法”,因为你在 Windows 上;查找select(Linux 有一个更好的版本,称为poll;但它在 Windows 上非常有问题,不推荐使用;即使是微软)
  • 如您所见,上面的代码中没有recv调用,我想在没有recv时被注意到@Someprogrammerdude

标签: c++ sockets winapi winsock2


【解决方案1】:

套接字值发生了什么

什么都没有。该套接字上的send() 最终将失败,而其上的recv() 将传递零或-1,但套接字本身保持打开状态,变量值不受影响。没有魔法。

它会变成 INVALID_SOCKET 吗?

没有。

【讨论】:

    【解决方案2】:

    对我来说,更好的主意是当您从任何客户端收到对服务器的请求时,只需创建一个新线程并将任务分配给该线程即可。通过这样做,您可以使服务器并行处理客户端请求并处理来自多个客户端的多个请求。因此,客户端无需等待服务器完成已提交请求的客户端的请求。如果你像这样实现,你就不需要担心如果连接断开会发生什么。在正常情况下,如果更正被破坏,您将在向客户端发送回复时在服务器中获取此信息,您可以将该过程标记为失败并将其记录到服务器日志中。

    【讨论】:

    • 只创建一个新线程 - 坏主意。需要使用异步处理来代替这个
    • 因为子线程将根据每个客户端请求创建,并且新创建的线程将完成所有工作并将请求从其自身发送回客户端,主线程上的负载将是最小的。你如何设计一个服务器来处理数百个客户端请求并行?假设服务器需要 1 分钟来处理来自客户端的请求。如果 100 个客户端尝试在该场景中同时连接到服务器,那么第 100 个客户端会发生什么情况。它必须等待 100 分钟。根据请求创建子线程几乎就像异步一样。
    • 线程数必须等于核心数,不能更多。而且我总是编写异步服务器。不需要几乎像异步,而是完全异步以获得良好的性能和尽可能低的资源
    • 同意。您需要根据服务器中的处理器数量来控制线程。您需要遵循 FIFO 调度。
    • 实际上我们只是从队列(iocp)中弹出数据包。 iocp 当然是先进先出
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-10
    • 1970-01-01
    • 1970-01-01
    • 2010-10-02
    相关资源
    最近更新 更多