重用套接字时发生套接字正在使用错误 我正在编写一个C++的XMLRPC客户端,它打算与Python XMLRPC服务器进行对话。p>

重用套接字时发生套接字正在使用错误 我正在编写一个C++的XMLRPC客户端,它打算与Python XMLRPC服务器进行对话。p>,c++,python,sockets,xml-rpc,C++,Python,Sockets,Xml Rpc,不幸的是,此时PythonXMLRPC服务器只能在一个连接上处理一个请求,然后它就关闭了。我发现这要感谢mhawke对我之前关于 因此,每当我想要发出XMLRPC请求时,我都必须创建一个到python服务器的新套接字连接。这意味着创建和删除许多套接字。一切正常,直到我接近4000个请求。在这一点上,我得到了套接字错误 我试着让winsock修复它的文件描述符,当我的python客户机出现同样的问题时,这一技巧是有效的,但没有效果。 我试过以下方法 int err = setsockopt(s_,

不幸的是,此时PythonXMLRPC服务器只能在一个连接上处理一个请求,然后它就关闭了。我发现这要感谢mhawke对我之前关于

因此,每当我想要发出XMLRPC请求时,我都必须创建一个到python服务器的新套接字连接。这意味着创建和删除许多套接字。一切正常,直到我接近4000个请求。在这一点上,我得到了套接字错误

我试着让winsock修复它的文件描述符,当我的python客户机出现同样的问题时,这一技巧是有效的,但没有效果。 我试过以下方法

int err = setsockopt(s_,SOL_SOCKET,SO_REUSEADDR,(char*)TRUE,sizeof(BOOL));
没有成功

我使用的是winsock 2.0,所以WSADATA::iMaxSockets不应该起作用,不管怎样,我检查了它并将其设置为0(我假设这意味着无穷大)

4000个请求在应用程序运行期间发出的请求数量似乎并不奇怪。在服务器不断关闭和重新打开时,是否有某种方法在客户端使用SO_KEEPALIVE


我完全丢失了什么吗?

使用后是否关闭插座?

更新:

我把这个加入到代码中,现在它似乎开始工作了

if(::connect(s_, (sockaddr *) &addr, sizeof(sockaddr))) 
  {
    int err = WSAGetLastError();
    if(err == 10048)   //if socket in user error,   force kill and reopen socket
    {
        closesocket(s_);
        WSACleanup();
        WSADATA info;
        WSAStartup(MAKEWORD(2,0), &info);
        s_ = socket(AF_INET,SOCK_STREAM,0);
        setsockopt(s_,SOL_SOCKET,SO_REUSEADDR,(char*)&x,sizeof(BOOL));
    }
  }
基本上,如果遇到10048错误(socket正在使用),只需关闭socket、调用cleanup并重新启动WSA,即可重置socket及其sockopt

(最后一个sockopt可能不是必需的)

我以前肯定错过了WSACleanup/WSAStartup调用,因为closesocket()和socket()肯定被调用过

此错误仅在每4000次调用中发生一次

我很好奇为什么会这样,尽管这似乎可以解决它。
如果有人对这个主题有任何意见,我会非常好奇地听到它

这个问题是由套接字在时间等待状态下挂起引起的,这个状态是在关闭客户端套接字后输入的。默认情况下,套接字将保持此状态4分钟,然后才能重新使用。您的客户机(可能在其他流程的帮助下)在4分钟内将其全部消费掉。有关详细说明和可能的非代码解决方案,请参阅

当您未显式绑定套接字地址时,Windows会动态分配1024-5000(3977个端口)范围内的端口号。此Python代码演示了问题:

import socket
sockets = []
while True:
    s = socket.socket()
    s.connect(('some_host', 80))
    sockets.append(s.getsockname())
    s.close()

print len(sockets)    
sockets.sort()
print "Lowest port: ", sockets[0][1], " Highest port: ", sockets[-1][1]
# on Windows you should see something like this...
3960
Lowest port: 1025  Highest port: 5000
如果您再次尝试立即运行此操作,它将很快失败,因为所有动态端口都处于TIME\u WAIT状态

有几种方法可以解决这个问题:

  • 管理您自己的端口分配和 使用
    bind()
    显式绑定 将客户端套接字连接到特定端口 每次你的 创建一个套接字。你仍然有 处理端口不可用的情况 已在使用中,但您将不会 仅限于动态端口。e、 g

    port = 5000
    while True:
        s = socket.socket()
        s.bind(('your_host', port))
        s.connect(('some_host', 80))
        s.close()
        port += 1
    
  • 摆弄索林格插座 选项我发现这个 有时在Windows中工作(尽管 不太清楚原因):
    s.setsockopt(socket.SOL_socket,
    socket.SO_LINGER,1)

  • 我不知道这对我的工作是否有帮助 你的特殊申请, 但是,可以发送 多个XMLRPC请求通过 相同的连接使用 方法。基本上 这可以让你积累 几个请求,然后发送它们 一下子。你将得不到任何好处 回复,直到您实际发送 累积的请求,因此您可以 本质上,可以将其视为批处理 处理-这是否符合 你的应用程序设计


  • 是的,在每个请求之后,我调用closesocket()。我已经检查过了,这甚至发生在错误发生之前的最后一个请求中,因此套接字没有保持打开状态