473,225 Members | 1,330 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,225 software developers and data experts.

closing a server socket


Spent some very frustrating hours recoding to find a way of closing a server
socket, i'd not thought it would be any problem,

however, after complete failure and as a last resort, i looked at the python
wrapper module for sockets, and found that the close command doesn't actually
call the underlying close! this didn't seem right, so i added it, and my code
now works simply and as expected.
def close(self):
self._sock.close() # added 2003-oct-13
self._sock = _closedsocket()
self.send = self.recv = self.sendto = self.recvfrom = self._sock._dummy
close.__doc__ = _realsocket.close.__doc__

Probably only on win32, the comments in the socket module seem to indicate
different codings on different platforms.

PythonWin 2.3.2 (#49, Oct 2 2003, 20:02:00) [MSC v.1200 32 bit (Intel)] on win32.

Jul 18 '05 #1
8 9245
simon place wrote:

Spent some very frustrating hours recoding to find a way of closing a server
socket, i'd not thought it would be any problem,

however, after complete failure and as a last resort, i looked at the python
wrapper module for sockets, and found that the close command doesn't actually
call the underlying close! this didn't seem right, so i added it, and my code
now works simply and as expected.

def close(self):
self._sock.close() # added 2003-oct-13
self._sock = _closedsocket()
self.send = self.recv = self.sendto = self.recvfrom = self._sock._dummy
close.__doc__ = _realsocket.close.__doc__

Probably only on win32, the comments in the socket module seem to indicate
different codings on different platforms.


None of this should be necessary!

What problems were you having that led you to try the above abomination in
your effort to resolve them?

-Peter
Jul 18 '05 #2


Peter Hansen wrote:
simon place wrote:
Spent some very frustrating hours recoding to find a way of closing a server
socket, i'd not thought it would be any problem,

however, after complete failure and as a last resort, i looked at the python
wrapper module for sockets, and found that the close command doesn't actually
call the underlying close! this didn't seem right, so i added it, and my code
now works simply and as expected.

def close(self):
self._sock.close() # added 2003-oct-13
self._sock = _closedsocket()
self.send = self.recv = self.sendto = self.recvfrom = self._sock._dummy
close.__doc__ = _realsocket.close.__doc__

Probably only on win32, the comments in the socket module seem to indicate
different codings on different platforms.

None of this should be necessary!

What problems were you having that led you to try the above abomination in
your effort to resolve them?

-Peter


The problem is i couldn't find anyway, in 'normal' code, to close a server
socket, ie unblock an accept.

tried to use non-blocking mode, but not allowed on a server socket, which
makes sense, but isn't documented.

tried to use time-outs, which was close, but seems to close the accepted
connection sockets on a server socket time-out.

tried to fire a dummy connection to unblock the accept, which works, but if
your ip changes, i.e. a dialup, you can't do that.

i only hacked the module because of frustration, but it took about a minute to
spot, and now every thing works the original way i tried, and i've been doing
some thrashing and had no problems.



Jul 18 '05 #3
simon place wrote:

Peter Hansen wrote:
None of this should be necessary!

What problems were you having that led you to try the above abomination in
your effort to resolve them?


The problem is i couldn't find anyway, in 'normal' code, to close a server
socket, ie unblock an accept.

tried to use non-blocking mode, but not allowed on a server socket, which
makes sense, but isn't documented.


It does work, which is why it isn't documented that it doesn't. <wink>

What did you try, that non-blocking server sockets don't work for you?

(I assume you are talking about using select.select() to detect when the
listening socket has a client connection waiting to be accepted.)

-Peter
Jul 18 '05 #4

i'm trying to see if anyone else thinks this is a bug,

when you call socket.socket.close() the wrapper only marks the socket as
closed, so no exception to unblock socket.socket.accept(), and you can
actually still get connections on this socket?

( this may only be for windows. )

simon.

Jul 18 '05 #5
simon place wrote:

i'm trying to see if anyone else thinks this is a bug,

when you call socket.socket.close() the wrapper only marks the socket as
closed, so no exception to unblock socket.socket.accept(), and you can
actually still get connections on this socket?

( this may only be for windows. )


A repost? What didn't you like about my previous replies?

I guess you are basically saying that you want to use a blocking
socket (because you can't get non-blocking ones to work, though they
do work in general?) but you still want to be able to terminate
your call from another thread by forcibly closing the socket...

If that's so, give it up. You can't do that because the
accept() call is stuck down in C code which can't be
interrupted from another Python thread. Your only hope would be
to have the server call be in a separate process, which you
could "kill", but then you'd of course have to talk to this
other process with sockets, and be back where you started.

Use non-blocking sockets. They do work.

-Peter
Jul 18 '05 #6
Peter Hansen wrote:
...
I guess you are basically saying that you want to use a blocking
socket (because you can't get non-blocking ones to work, though they
do work in general?) but you still want to be able to terminate
your call from another thread by forcibly closing the socket...

If that's so, give it up. You can't do that because the
VERY good point -- and since by a weird coincidence I've had to deal
with EXACTLY this problem TWICE over the last few days for two
different clients (!), both times in the context of xml-rpc serving,
let me emphasize this once again: that's not the way to do it.

Use non-blocking sockets. They do work.


Or architect a solution where the blocked thread will get out
from its stuck state in the blocking socket "naturally". That's
quite easy in XML-RPC, e.g. as follows...:
_baseclass = SimpleXMLRPCServer.SimpleXMLRPCServer
class TerminatableServer(_baseclass):
allow_reuse_address = True

def __init__(self, addr, *args, **kwds):
self.myhost, self.myport = addr
_baseclass.__init__(self, addr, *args, **kwds)
self.register_function(self.terminate_server)

quit = False
def serve_forever(self):
while not self.quit:
self.handle_request()
self.server_close()

def terminate_server(self, authentication_token):
if not check_as_valid(authentication_token):
return 1, "Invalid or expired authentication token"
self.quit = True
return 0, "Server terminated on host %r, port %r" % (
self.myhost, self.myport)

(you'll want some way to verify authentication, of course, but
that's probably something you already have somewhere in such an
architecture, so I'm simplistically representing it by the
authentication_token parameter and a hypothetical check_as_valid
function that's able to check it).

The point is that in this way server termination is architected
as just one transaction -- the self.handle_request() in the body
of the while will eventually hand off control to terminate_server,
which may set self.quit, and that in turn will terminate the
while loop, since as soon as handle_request is done the loop's
condition is checked again. There are other ways, of course, but
I've found this one clean and reliable for these specific needs.
Alex

Jul 18 '05 #7
Alex Martelli wrote:
Peter Hansen wrote:
...
I guess you are basically saying that you want to use a blocking
socket (because you can't get non-blocking ones to work, though they
do work in general?) but you still want to be able to terminate
your call from another thread by forcibly closing the socket...

If that's so, give it up. You can't do that because the

VERY good point -- and since by a weird coincidence I've had to deal
with EXACTLY this problem TWICE over the last few days for two
different clients (!), both times in the context of xml-rpc serving,
let me emphasize this once again: that's not the way to do it.
Use non-blocking sockets. They do work.

Or architect a solution where the blocked thread will get out
from its stuck state in the blocking socket "naturally". That's
quite easy in XML-RPC, e.g. as follows...:
_baseclass = SimpleXMLRPCServer.SimpleXMLRPCServer
class TerminatableServer(_baseclass):
allow_reuse_address = True

def __init__(self, addr, *args, **kwds):
self.myhost, self.myport = addr
_baseclass.__init__(self, addr, *args, **kwds)
self.register_function(self.terminate_server)

quit = False
def serve_forever(self):
while not self.quit:
self.handle_request()
self.server_close()

def terminate_server(self, authentication_token):
if not check_as_valid(authentication_token):
return 1, "Invalid or expired authentication token"
self.quit = True
return 0, "Server terminated on host %r, port %r" % (
self.myhost, self.myport)

(you'll want some way to verify authentication, of course, but
that's probably something you already have somewhere in such an
architecture, so I'm simplistically representing it by the
authentication_token parameter and a hypothetical check_as_valid
function that's able to check it).

The point is that in this way server termination is architected
as just one transaction -- the self.handle_request() in the body
of the while will eventually hand off control to terminate_server,
which may set self.quit, and that in turn will terminate the
while loop, since as soon as handle_request is done the loop's
condition is checked again. There are other ways, of course, but
I've found this one clean and reliable for these specific needs.
Alex


Yes, no problem closing a server before it returns to accept another
connection, but when the handler is threaded,

see below, current situation

import socket
s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
s.bind(('127.0.0.1',80))
s.listen(1)
import threading
t=threading.Thread(target=s.accept)
t.start()
s.close()
import inspect
inspect.getsource(socket.socket.close) ' def close(self):\n self._sock = _closedsocket()\n self.send
= self.recv = self.sendto = self.recvfrom = self._sock._dummy\n' t.isAlive() True s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
s.connect(('127.0.0.1',80))
t.isAlive() False
i.e. closing server socket does not unblock accept and you can still get
connections on it!
( because it has not actually been closed!)
how is this acceptable?

with socket modified to actually close the socket,
import socket
import inspect
inspect.getsource(socket.socket.close) ' def close(self):\n self._sock.close()\n self._sock = _closeds
ocket()\n self.send = self.recv = self.sendto = self.recvfrom = self._soc
k._dummy\n' import threading
s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
s.bind(('127.0.0.1',80))
s.listen(1)
t=threading.Thread(target=s.accept)
t.start()
t.isAlive() True s.close()
Exception in thread Thread-1: Traceback (most recent call last):
File "C:\PYTHON23\lib\threading.py", line 436, in __bootstrap
self.run()
File "C:\PYTHON23\lib\threading.py", line 416, in run
self.__target(*self.__args, **self.__kwargs)
File "socket.py", line 168, in accept
sock, addr = self._sock.accept()
error: (10038, 'Socket operation on non-socket')

t.isAlive() False


i.e. close socket generates an exception on accept and no more connections.

If there's some underlying difficulty that causes this to come back and bite
the testing i've done shows this to take a very long time.

simon.
Jul 18 '05 #8
simon place wrote:
...
Yes, no problem closing a server before it returns to accept another
connection, but when the handler is threaded,
When the server is threaded, it should be designed accordingly; see
Python's standard library, module SocketServer etc, for one right
way to design a threaded server.
i.e. closing server socket does not unblock accept and you can still get
connections on it!
( because it has not actually been closed!)
how is this acceptable?
It's not: in general, two threads should NEVER access the same
resource simultaneously, unless the resource is specifically
known to be thread safe. sockets aren't. It's not acceptable,
and the bug is in the program which has one of its threads
make a sock.close() call while another is waiting on a
sock.accept() on the same socket sock.

with socket modified to actually close the socket, ... i.e. close socket generates an exception on accept and no more
connections.
On _your_ platform, no doubt. I'd bet substantial money that,
without even going to especially _exotic_ platforms, you'll find
terrible misbehavior with such mods on at least one of the
platforms I routinely program for.

If there's some underlying difficulty that causes this to come back and
bite the testing i've done shows this to take a very long time.


Just as much time as is necessary to go and purchase some
other platform to try it on, I suspect.
Alex

Jul 18 '05 #9

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

1
by: Naresh Agarwal | last post by:
Hi I'm developing a webapp using servlets, which processes a HTTP Post request and sent back MIME message (multipart/related - essentially SOAP message with Attachments). I'm constructing the...
4
by: flupke | last post by:
Hi, I have a gui (made in wxPython) that enables a user to connect to a server and issue some commands. The problem occurs when i try to disconnect the client. It exits but it doesn't return to...
1
by: Daniel | last post by:
after opening socket, sending data then closing socket 3000 times i get "Only one usage of each socket address" what am i doing wrong? is there some thing else i need to do to free up the socket...
3
by: Tom Opgenorth | last post by:
I'm experiencing a problem with sockets, and I'm really hoping someone can help me, please and thank you. I've written a TCP Server, which listens on a port for an incoming connection. When the...
2
by: Lenard Gunda | last post by:
Hi, I have the following problem when I am working with sockets in C#. I do not remember running into the same problem some while ago, when working with sockets from C++ (using native code, not...
8
by: Dinsdale | last post by:
I am trying to write a Tcp "Server" that opens a class that wraps a tcp socket when a new connection is made (Listener.AcceptSocket()). Everything is going swimmingly except when I try to close the...
4
by: Funke | last post by:
Assume that in C#, I create a server socket (listener) and code to start new threads with each connection using BeginAccept(). After some time, I have three threads running, each with their own...
6
by: alessandro | last post by:
Hi all, This is my framework for create TCP server listening forever on a port and supporting threads: import SocketServer port = 2222 ip = "192.168.0.4"
4
by: O.B. | last post by:
I have a socket configured as TCP and running as a listener. When I close socket, it doesn't always free up the port immediately. Even when no connections have been made to it. So when I open...
0
by: VivesProcSPL | last post by:
Obviously, one of the original purposes of SQL is to make data query processing easy. The language uses many English-like terms and syntax in an effort to make it easy to learn, particularly for...
3
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 3 Jan 2024 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM). For other local times, please check World Time Buddy In...
0
by: jianzs | last post by:
Introduction Cloud-native applications are conventionally identified as those designed and nurtured on cloud infrastructure. Such applications, rooted in cloud technologies, skillfully benefit from...
0
by: mar23 | last post by:
Here's the situation. I have a form called frmDiceInventory with subform called subfrmDice. The subform's control source is linked to a query called qryDiceInventory. I've been trying to pick up the...
2
by: jimatqsi | last post by:
The boss wants the word "CONFIDENTIAL" overlaying certain reports. He wants it large, slanted across the page, on every page, very light gray, outlined letters, not block letters. I thought Word Art...
2
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 7 Feb 2024 starting at 18:00 UK time (6PM UTC) and finishing at about 19:30 (7.30PM). In this month's session, the creator of the excellent VBE...
0
by: fareedcanada | last post by:
Hello I am trying to split number on their count. suppose i have 121314151617 (12cnt) then number should be split like 12,13,14,15,16,17 and if 11314151617 (11cnt) then should be split like...
0
by: stefan129 | last post by:
Hey forum members, I'm exploring options for SSL certificates for multiple domains. Has anyone had experience with multi-domain SSL certificates? Any recommendations on reliable providers or specific...
1
by: davi5007 | last post by:
Hi, Basically, I am trying to automate a field named TraceabilityNo into a web page from an access form. I've got the serial held in the variable strSearchString. How can I get this into the...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.