Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why am I receiving a string from the socket until the \n newline escape sequence in python?

Tags:

python

sockets

It is supposed to receive from a tcp socket a 2 line string but in fact i am receiving only the string until the new line.

     socket = socket(AF_INET,SOCK_STREAM)
     socket.connect((ip,port))
     data = socket.recv(1024)
     print "%s" % data

if a call the receive function now it will receive the second part of the string after the break line.This is not what i want in fact. It should return the entire string from the first call. When i use nc to connect to the server i am receiving the string normally in the beginning of the connection.Why that happens?

like image 482
curious Avatar asked Dec 05 '11 14:12

curious


1 Answers

Because TCP is a streaming protocol (as indicated by the SOCK_STREAM) there are no fixed message boundaries or packets, and you can never be sure you get everything with just one call to recv. You simply have to call recv in a loop, adding to a buffer, and exit the loop when you deem that you have enough. Most text-only protocols use either newline to tell that the read is done and to do something with the received data. Other protocols use other characters, or byte sequences.

In your case, if there is no special character saying that the end of the current data has been reached, you have two solutions:

  1. Use a timeout: When no new data has been received for some time, print it.

  2. Non-blocking sockets: Simply read in a loop, appending data to an internal buffer. When the call to recv throws an error with errno equal to errno.EWOULDBLOCK, then there is no more to read for now and print the received data.

Alternative 2, together with the package select, is probably the best way to go.

Edit

Here is a simple example of what I mean. It will probably not work like this, and will need some tweaking, but hopefully it's enough for you to build on.

# Need to import: package socket, package select, package errno

# Create socket and connect to server

# Make the socket non-blocking (see http://docs.python.org/library/socket.html#socket.socket.setblocking)
socket.setblocking(0)

run_main_loop = True
while run_main_loop:
    # Wait for events...
    read_ready, _, _ = select.select([socket], None, None)

    if socket in read_ready:
        # The socket have data ready to be received
        buffer = ''
        continue_recv = True

        while continue_recv:
            try:
                # Try to receive som data
                buffer += socket.recv(1024)
            except socket.error, e:
                if e.errno != errno.EWOULDBLOCK:
                    # Error! Print it and tell main loop to stop
                    print 'Error: %r' % e
                    run_main_loop = False
                # If e.errno is errno.EWOULDBLOCK, then no more data
                continue_recv = False

    # We now have all data we can in "buffer"
    print '%r' % buffer

socket.close()
like image 53
Some programmer dude Avatar answered Oct 21 '22 09:10

Some programmer dude