重用套接字时发生套接字正在使用错误 我正在编写一个C++的XMLRPC客户端,它打算与Python XMLRPC服务器进行对话。p>
不幸的是,此时PythonXMLRPC服务器只能在一个连接上处理一个请求,然后它就关闭了。我发现这要感谢mhawke对我之前关于 因此,每当我想要发出XMLRPC请求时,我都必须创建一个到python服务器的新套接字连接。这意味着创建和删除许多套接字。一切正常,直到我接近4000个请求。在这一点上,我得到了套接字错误 我试着让winsock修复它的文件描述符,当我的python客户机出现同样的问题时,这一技巧是有效的,但没有效果。 我试过以下方法重用套接字时发生套接字正在使用错误 我正在编写一个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_,
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
s.setsockopt(socket.SOL_socket,
socket.SO_LINGER,1)
是的,在每个请求之后,我调用closesocket()。我已经检查过了,这甚至发生在错误发生之前的最后一个请求中,因此套接字没有保持打开状态