我在一些代码中创建了许多“短期”套接字,如下所示:
nb=1000
for i in range(nb):
sck = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sck.connect((adr, prt)
sck.send('question %i'%i)
sck.shutdown(SHUT_WR)
answer=sck.recv(4096)
print 'answer %i : %s' % (%i, answer)
sck.close()
只要nb足够小,这就可以正常工作。
因为nb可能很大,所以我想做这样的事情
sck = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sck.connect((adr, prt)
for i in range(nb):
reopen(sck) # ? ? ?
sck.send('question %i'%i)
sck.shutdown(SHUT_WR)
answer=sck.recv(4096)
print 'answer %i : %s' % (%i, answer)
sck.close()
所以问题是:
有什么方法可以“重用”已经关闭的套接字吗?
如果您继续为同一端口打开和关闭套接字,那么最好将此套接字打开一次并保持打开状态,这样您的性能会更好,因为打开和关闭将需要一些时间。
如果有许多短期套接字,也可以考虑使用数据报套接字(UDP)。 注意,在这种情况下,您不能保证到达,也不能保证包的顺序。
不,这是底层C套接字(以及TCP/IP协议)的限制。我的问题是:当您可以设计应用程序来使用它们时,为什么要关闭它们?
许多短期套接字的问题是,关闭它们会使它们处于暂时无法使用的状态(基本上是数据包生存期的两倍,以确保网络中的任何数据包要么到达并被丢弃,要么被网络本身丢弃)。基本上,在需要唯一的4元组(源ip、源端口、目标ip、目标端口)中,前一个和后两个往往总是相同的,因此,当您用完源端口时,您就被hose占用了。
我们以前在软件中遇到过这个问题,当我们运行在更快的机器上时(因为我们可以使用更多的会话),这个问题才变得明显。
为什么不打开插座继续使用呢?看起来您的协议是一个简单的请求/响应协议,使用这种方法应该很容易实现。
类似于:
更新:
一种可能(我们以前也这样做过)是,如果由于这种持续的打开/关闭而导致连接断开,则检测问题并限制它。考虑下面的代码(我添加的内容比Python更多是伪代码,因为我很久没有接触Python了):
基本上,它可以让你全速运行,同时有足够的资源,但当你打击你的问题领域时会减慢速度。这实际上是我们对我们的产品所做的“修复”当资源不足时失败的问题。我们本可以重新设计它,除非它是一个接近生命尽头的遗留产品,而且我们基本上是在以最低成本模式修复服务。
我不知道额外的开销会是什么样子,但你可以完全关闭并重新打开插座。您需要设置以便重用ADR,并绑定到可以重用的特定端口。
相关问题 更多 >
编程相关推荐