Exiting SocketServer: socket.error: (98, 'Address already in use')

M

Magnus Lycka

I have a socket server like below which I want to exit when
it's out of data. If I interrupt the client, I'll get a
broken pipe on the server side, and after a Ctrl-C, I can
restart the server again, but if I let it run out of data,
and exit via handle_error as can be seen below, I will get
a socket.error: (98, 'Address already in use') when I try
to restart the server. (Unless I wait a minute or so, or
use another port.) I feel like I'm waving a dead chicken
here. I can't seem to find any proper description on how to
handle this in the docs for SocketServer or socket, and my
futile experiments seem to lead nowhere... Neither Nutshell
nor the Essential Reference helped me solve this.

I'm using Python 2.2.3 on Linux. Why doesn't my socket
get released by the OS when I exit via my handle_error?

class MyRequestHandler(SocketServer.BaseRequestHandler):
def handle(self):
while True:
[snip]
try:
[snip]
except [snip]:
# Done!
# Uncommenting the next line makes no difference
# self.request.close()
sys.exit()

class ExitableSocketServer(SocketServer.TCPServer):
def handle_error(self, request, client_address):
exc_info = sys.exc_info()
if exc_info and isinstance(exc_info[1], SystemExit):
request.shutdown(2)
request.close()
del request
self.socket.shutdown(2)
self.socket.close()
del self.socket
sys.exit()
SocketServer.TCPServer.handle_error(self, request, client_address)

....

server = ExitableSocketServer(('', port), MyRequestHandler)
server.serve_forever()
 
D

Dennis Lee Bieber

I'm using Python 2.2.3 on Linux. Why doesn't my socket
get released by the OS when I exit via my handle_error?
Not a Python problem...

Normal socket behavior IS to lock out for some period of time.

Check the options available when creating the socket. (I'm not
heavily familiar with socket programming, hence the vagueness) Some
option for "Reuse Address"...

SO_REUSEADDR is the constant in socket.h... And appears to be
visible in socket.py

--
 
A

Andrew Dalke

Magnus said:
Why doesn't my socket
get released by the OS when I exit via my handle_error?

Hi Magnus,

I wrote about this at
http://www.dalkescientific.com/writings/diary/archive/2005/04/21/using_xmlrpc.html

The reason for it is described at
http://hea-www.harvard.edu/~fine/Tech/addrinuse.html

You can set the class variable "allow_reuse_address = True" in
your derived ExitableSocketServer to get the behaviour you
expect, at the expense of some problems mentioned in the
above URL.

Andrew
(e-mail address removed)
 
M

Magnus Lycka

Thank's a lot Andrew and Dennis.

Andrew said:
You can set the class variable "allow_reuse_address = True" in
your derived ExitableSocketServer to get the behaviour you
expect, at the expense of some problems mentioned in the
above URL.

Ok. I added a STOP message to my protocol, so now the client
shuts down the socket first (when it has read the STOP), and
then it seems to work much better. What I did, in case the
client gets behind, was this in my handle method: I send a STOP
message repeatedly with a delay. When the client gets the first
one, it will close the socket, and I will get an exception the
next time I try to send. This seems to work well, without
(I hope) introducing any new potential problems.

....
delay = 1
print "No more data to serve. Send STOP message."
print "Waiting for client to close socket."
while 1:
try:
self.request.send("STOP\n")
time.sleep(delay)
print '.'
finally:
sys.exit()
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,995
Messages
2,570,236
Members
46,822
Latest member
israfaceZa

Latest Threads

Top