Socket recv(1) seems to block instead of returning end of file.

Hendrik van Rooyen mail at microcorp.co.za
Fri Aug 24 05:21:41 EDT 2007


"Grant Edwards" <gr....com> wrote:

> On 2007-08-23, Hendrik van Rooyen <m....ocorp.co.za> wrote:
> 
> > While doing a netstring implementation I noticed that if you
> > build a record up using socket's recv(1), then when you close
> > the remote end down, the recv(1) hangs,
> 
> I don't see that behavior running 2.4 on Gentoo.

I express myself badly - when I say "close down" I don't mean
"close down as in socket.close" I mean "close down as in click on the
tkinter window, or with keyboard interrupt" - sorry for the confusion

> 
> > despite having a short time out of 0.1 set.
> 
> What time out?  A socket's recv method doesn't do timeouts.

If I set a time out, then the recv does not block,
but gives me a timed out exception.

> 
> > If however, you try to receive more than one char, (I tested
> > with 3, did not try 2), then when you shut the remote end down
> > you do not get a time out, but an empty string - the normal
> > end of file, I suppose.
> >
> > Has anybody else seen this behaviour?
> 
> No.  recv(1) works fine for me (Python 2.4 under Gentoo).
> Perhaps you could post a minimal example that doesn't work for
> you?

I am now frustrated - its not as simple as I thought - my application 
still only detects EOF if I do more than recv(1), but I cannot 
demonstrate simply - anyway, I have modified your code to look more 
like my program's code, and it follows below - if it does nothing else, 
it should convince you that recv() *does* time out...

The receiver code below detects if I close the sending console window, 
as well as control-c - Rats!

I will muck around with this more to see if I can get to the bottom of it,
as I can't see anything different between what is below and my program,
except that in both cases the comms are done in threads which are not
the main loop.

- Hendrik

------------------------------------------------------------------------
#!/usr/bin/python

#reader
import socket

HOST = 'Linuxbox' # Symbolic name meaning the local host
PORT = 57001 # Arbitrary non-privileged port
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((HOST, PORT))
socket.setdefaulttimeout(0.100)

s.listen(1)
conn, addr = s.accept()
print 'Connected by', addr
data = ''
while 1:
    try:
        data = data + conn.recv(1)
    except socket.error,msg:
        if 'timed out' in msg:
            print msg
            continue
        else:
            print 'socket error is',msg
            break
    if not data: break
    if data.endswith('\n'):
        print data
        data = ''
print 'heigh ho the end has come!'
conn.close()


------------------------------------------------------------------------


------------------------------------------------------------------------
#!/usr/bin/python

# writer
import socket,time,random

HOST = 'Linuxbox' # Symbolic name meaning the local host
PORT = 57001 # Arbitrary non-privileged port
socket.setdefaulttimeout(0.100)
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

while True:
    try:
        print 'Attempting to connect to server'
        s.connect((HOST, PORT))
        break
    except socket.error, msg:
        time.sleep(5)
        continue
    print 'Connected - Time out is:',s.gettimeout()

data = "The quick brown fox jumps over the lazy dog 0123456789\n"
count = 0
while count < 500:
    try:
        s.send(data)
    except socket.error,msg:
        if 'timed out' in msg:
            print msg
            time.sleep(0.05)
            continue
        else: 
            print 'socket error is:',msg
            break
    print "tx:",len(data)
    time.sleep(random.randint(200,800)/1000.0)
s.close()

------------------------------------------------------------------------








More information about the Python-list mailing list