重新使用套接字时套接字使用错误 [英] Socket in use error when reusing sockets

查看:170
本文介绍了重新使用套接字时套接字使用错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在c ++中编写一个XMLRPC客户端,目的是与python XMLRPC服务器通信。不幸的是,目前python XMLRPC服务器只能在连接上发送一个请求,然后关闭,我发现这是由于mhawke对我的响应有关相关主题的上一个查询



因此,我必须创建一个新的套接字连接到我的python服务器每次我想做一个XMLRPC请求。这意味着创建和删除了很多套接字。一切工作正常,直到我接近〜4000请求。此时,我会收到套接字错误 10048,Socket正在使用



我试着睡觉的线程让winsock修复它的文件描述符,一个工具当我的一个python客户端有相同的问题,没有效果。
我试过下面的代码:

  int err = setsockopt(s_,SOL_SOCKET,SO_REUSEADDR, ,sizeof(BOOL)); 

未成功。



m使用winsock 2.0,所以WSADATA :: iMaxSockets不应该发挥,和任何一种方式,我检查和其设置为0(我假设意味着无穷大)



4000个请求看起来不像是在应用程序运行期间发出的异常数量的请求。在服务器持续关闭和重新打开时,是否有某种方法在客户端使用SO_KEEPALIVE?



我完全缺少某些东西?

问题是由于挂起在TIME_WAIT状态中的套接字引起的,一旦您关闭客户端的套接字,它就会被输入。默认情况下,套接字将保持此状态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()
printLowest port:,sockets [0] [1],Highest port: 1]
#在Windows上你应该看到这样的...
3960
最低端口:1025最高端口:5000

如果您尝试再次运行此immeditaely,它应该会很快失败,因为所有动态端口都处于TIME_WAIT状态。



有几种方法:


  1. 管理您自己的端口分配和
    使用 bind()
    客户端套接字显式绑定到特定的端口
    ,每次
    创建一个套接字时都会递增。你仍然有
    来处理端口是
    已经在使用的情况,但是你不会被
    限制为动态端口。例如

      port = 5000 
    while True:
    s = socket.socket()
    .bind(('your_host',port))
    s.connect(('some_host',80))
    s.close()
    port + = 1


  2. 使用SO_LINGER套接字
    选项。我发现这个
    有时工作在Windows(虽然
    不完全确定为什么):
    s.setsockopt(socket.SOL_SOCKET,
    socket.SO_LINGER ,1)


  3. 我不知道这将有助于
    您的特定应用程序,
    然而,有可能通过
    发送
    多个XMLRPC请求,使用
    multicall 方法。基本上
    这允许你累积
    几个请求,然后一次发送他们
    。你不会得到任何
    响应,直到你实际发送
    累积的请求,所以你可以
    本质上认为这是批处理
    处理 - 这适合与
    您的应用程序设计?



I am writing an XMLRPC client in c++ that is intended to talk to a python XMLRPC server.

Unfortunately, at this time, the python XMLRPC server is only capable of fielding one request on a connection, then it shuts down, I discovered this thanks to mhawke's response to my previous query about a related subject

Because of this, I have to create a new socket connection to my python server every time I want to make an XMLRPC request. This means the creation and deletion of a lot of sockets. Everything works fine, until I approach ~4000 requests. At this point I get socket error 10048, Socket in use.

I've tried sleeping the thread to let winsock fix its file descriptors, a trick that worked when a python client of mine had an identical issue, to no avail. I've tried the following

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

with no success.

I'm using winsock 2.0, so WSADATA::iMaxSockets shouldn't come into play, and either way, I checked and its set to 0 (I assume that means infinity)

4000 requests doesn't seem like an outlandish number of requests to make during the run of an application. Is there some way to use SO_KEEPALIVE on the client side while the server continually closes and reopens?

Am I totally missing something?

解决方案

The problem is being caused by sockets hanging around in the TIME_WAIT state which is entered once you close the client's socket. By default the socket will remain in this state for 4 minutes before it is available for reuse. Your client (possibly helped by other processes) is consuming them all within a 4 minute period. See this answer for a good explanation and a possible non-code solution.

Windows dynamically allocates port numbers in the range 1024-5000 (3977 ports) when you do not explicitly bind the socket address. This Python code demonstrates the problem:

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

If you try to run this immeditaely again, it should fail very quickly since all dynamic ports are in the TIME_WAIT state.

There are a few ways around this:

  1. Manage your own port assignments and use bind() to explicitly bind your client socket to a specific port that you increment each time your create a socket. You'll still have to handle the case where a port is already in use, but you will not be limited to dynamic ports. e.g.

    port = 5000
    while True:
        s = socket.socket()
        s.bind(('your_host', port))
        s.connect(('some_host', 80))
        s.close()
        port += 1
    

  2. Fiddle with the SO_LINGER socket option. I have found that this sometimes works in Windows (although not exactly sure why): s.setsockopt(socket.SOL_SOCKET, socket.SO_LINGER, 1)

  3. I don't know if this will help in your particular application, however, it is possible to send multiple XMLRPC requests over the same connection using the multicall method. Basically this allows you to accumulate several requests and then send them all at once. You will not get any responses until you actually send the accumulated requests, so you can essentially think of this as batch processing - does this fit in with your application design?

这篇关于重新使用套接字时套接字使用错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆