No, this is a limitation of the underlying C sockets (and the TCP/IP protocol, for that matter). My question to you is: why are you shutting them down when you can architect your application to use them?
The problem with many short-term sockets is that shutting them down puts them in a state where they cannot be used for a while (basically, twice the packet lifetime, to ensure any packets in the network either arrive and are discarded, or get discarded by the network itself). Basically what happens is that, in the 4-tuple that needs to be unique (source ip, source port, destination ip, destination port), the first one and last two tend to always be the same so, when you run out of source ports, you're hosed.
We've struck this problem in software before where it only became evident when we ran on faster machines (since we could use many more sessions).
Why dont you just open up the socket and continue to use it? It looks like your protocol is a simple request/response one, which should be easily do-able with that approach.
Something like:
sck = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sck.connect((adr, prt)
for i in range(nb):
sck.send('question %i'%i)
answer=sck.recv(4096)
print 'answer %i : %s' % (%i, answer)
sck.close()
Update:
One possibility (and we've done this before) if you're running out of connection due to this continual open/close, is to detect the problem and throttle it. Consider the following code (the stuff I've added is more pseudo-code than Python since I haven't touched Python for quite a while):
for i in range(nb):
sck = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sck.connect((adr, prt)
while sck.error() == NO_SOCKETS_AVAIL:
sleep 250 milliseconds
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()
Basically, it lets you run at full speed while there are plenty of resources but slows down when you strike your problem area. This is actually what we did to our product to "fix" the problem of failing when resources got low. We would have re-architected it except for the fact it was a legacy product approaching end of life and we were basically in the fix-at-minimal-cost mode for service.