Python. Socket How to receive all data with socket.recv ()?

2

I have a problem with receiving data from the server to the client. I have the following function on the client side that tries to receive data from the server. The data sent by the Server using the function socket.sendall(datos) is greater than buff_size therefore I need a loop to read the data.

def recibirTodo(sock):
    datos = ""
    buff_size=4096
    while True:
       parte = sock.recv(buff_size)     
       datos += parte
       if parte < buff_size:
             break;
    return datos

The problem that occurs to me is that after the first iteration (read the first 4096 MB ), in the second the program remains blocked waiting for the other data in parte = sock.recv(buff_size) . How do I have to do so that recv() can continue reading the other missing data? Thanks

    
asked by Nico Rossello 11.01.2017 в 15:59
source

3 answers

1

Try.

while True:
    try:
        # Recibir datos del cliente.
        input_data = conn.recv(1024)
    except error:
        print("Error de lectura.")
        break
    else:
        if input_data:
            # Compatibilidad con Python 3.
            if isinstance(input_data, bytes):
                end = input_data[0] == 1
            else:
                end = input_data == chr(1)
            if not end:
                # Almacenar datos.
                f.write(input_data)
            else:
                break
    
answered by 11.01.2017 в 23:33
1

The problem you suffer is that in UDP, unlike TCP, if we receive a package and we can not obtain the content in its entirety, the rest is lost, it does not stay in any kind of buffer waiting to be read.

An advantage that you have is that you know and it is limited the maximum size that can have an IP packet (2 16 - 1 = 65,535 bytes) which should be subtracted from the size of the IP header itself (20 bytes minimum) and the UDP (8 bytes).

In short, you must define a maximum information size of 65,507 bytes to ensure that you will not lose any UDP packet contents because you have read it incomplete, saving you the loop and the concatenation of partial results (there will never be):

def recibirTodo(sock):
    datos = ""
    datos = sock.recv(65507)
    return datos
    
answered by 30.08.2017 в 08:18
1

Although you do not show how the socket is created, by referring to the sendall() method on the other side, it follows that it is a TCP type socket.

You also do not mention which version of python you are using, but since you initialize datos with a string ( "" ) and not with a string of bytes ( b"" ) I deduce that it is Python2.

Your program has a bug, which in Python3 would have been a runtime error that would have helped you detect the problem, and that is that you are comparing a string with an integer. In python 3 such a comparison would be prohibited and would generate the exception TypeError: unorderable types: str() < int() , but in Python2 it is legal and produces False *.

In particular, the problematic line is this:

   if parte < buff_size:

Where parte is a string and buff_size is an integer. I assume you wanted to say if len(parte) < buff_size .

Another way to implement your loop would be:

def recibirTodo(sock):
    datos = ""
    buff_size=4096
    recibidos = "aun nada"
    while recibidos:
       recibidos = sock.recv(buff_size)     
       datos += recibidos
    return datos

Which works because by the time you have finished receiving all the data (and the socket has been closed from the other end), recv() will return the empty string. Remember that the other end must close the connection. If not, there is no way you can know if there is or is not more data unless you have a protocol of your own that, for example, first sends the number of bytes that the next message will have.

*: because the way in which Python 2 solves the comparison of data between different types is to flip , and what it does is to compare its types alphabetically, and it turns out that "str" is greater than "int"

    
answered by 18.03.2018 в 17:19