Python TCP socket.recv() returns with nothing as soon as connection is made

14,317

Yes, this is expected behavior.

The client does not send anything. And it exit as soon as it connect to the server; cause disconnection.

socket.recv returns an empty string if the peer performed shutdown (disconnect).

While, in the REPL, the socket is not closed until you issue sys.exit() or you quit the interactive shell.

Share:
14,317

Related videos on Youtube

Sonicsmooth
Author by

Sonicsmooth

Updated on June 04, 2022

Comments

  • Sonicsmooth
    Sonicsmooth almost 2 years

    I'm trying to implement the most basic python TCP server. Windows 8, Python 2.7, firewall is turned off. Code is from here: https://wiki.python.org/moin/TcpCommunication

    If I do the client stuff (socket(...), connect(...), send(...)) via python repl, things work fine, ie the server correctly blocks when calling recv.

    However if I run the exact same code via python script (both with and without explicitly calling python.exe at windows command line), the recv returns immediately with no data. I read elsewhere on SO this means it's an invalid socket, but I'm not sure what that means or how to check for it. I'm using the socket returned by accept() not the one used to initiate the connection.

    I'm trying to block on recv so I can take advantage of the timeout (I don't want to use select module, which BTW also returns immediately) and process some keyboard stuff between attempts to recv, ie user presses 'q' to quit.

    In various experiments I've shown that once this occurs, recv will always return immediately (as will select.select(...)) if I put it in a loop, so it's not like the client is sending a single "bad" packet initially. If the client happens to have sent something, then the recv returns with that data, but it certainly doesn't block waiting for data when put in a tight loop.

    Is this behavior expected?

    Server code:

    import sys
    import socket
    
    
    TCP_IP = '192.168.1.10'
    TCP_PORT = 5005
    BUFFER_SIZE = 20  # Normally 1024, but we want fast response
    
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.bind((TCP_IP, TCP_PORT))
    s.listen(1)
    
    conn, addr = s.accept()
    print 'Connection address:', addr
    while 1:
        data = conn.recv(BUFFER_SIZE) # This returns immediately with no data, when client connection is run from script and doesn't send() anything, just connects.
        if not data:
            print "broken"
            break
        print "received data:", data
        conn.send(data)  # echo
    
    conn.close()
    sys.exit()
    

    Client code:

    import sys
    import socket
    
    TCP_IP = '192.168.1.10'
    TCP_PORT = 5005
    BUFFER_SIZE = 1024
    MESSAGE = "Hello, World!"
    
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.connect((TCP_IP, TCP_PORT))
    # Commenting out the following to prove the recv() call on the other
    #end returns with nothing instead of blocking indefinitely.  If I
    #type the rest of this at the REPL the server behaves correctly,
    #ie, the recv call blocks forever until socket.send("bla") from client.
    
    #s.send(MESSAGE) data = s.recv(BUFFER_SIZE)
    #s.close()
    #print "received data:", data
    sys.exit()
    
  • Sonicsmooth
    Sonicsmooth over 10 years
    Thank you. I verified this by a) doing a while True: pass loop on the client side script, and the server recv blocked, and then b) connecting from python repl manually line by line, and the server side recv unblocked and passed no data when I did s.close() from client side python repl.