Python Socket Programming: recv and recvfrom
Asked Answered
C

3

18

I am new to python and socket programming, and I'm confused about about usage for socket.recvfrom() and socket.recv(). I understand that people usually use recvfrom() for UDP and recv() for TCP.

For example:

serverSocketUDP = socket(AF_INET, SOCK_DGRAM)
serverSocketTCP = socket(AF_INET, SOCK_STREAM)
#... define server...
#...
message, clientAddress = serverSocketUDP.recvfrom(2048) #why 2048 for UDP? Ive seen several examples like this.
message2 = serverSocketTCP.recv(1024) #Again, why 1024 for TCP? 

As seen in the example above, what I am confused about is the numbers. Why 2048 and 1024 for different protocols? What do these numbers represent?

Chacon answered 20/3, 2016 at 15:53 Comment(1)
Highly confusing. Dealing with DNS UDP (DATAGRAM) I have been using recvfrom(1024) and received between 1024 and 4096 in size. So it seems in that use case the parameter is only a hint? In the python docs, recv says max of buffsize bytes, but recvfrom it doesn't mention bytes.Open
R
21

Why 2048 and 1024 for different protocols?

Those are very arbitrary numbers and depend on the protocol being implemented. And even though the TCP number works, the UDP number you give is very likely wrong.

TCP implements a stream protocol that you can read in any sized chunk you want. You could do recv(1) to get a byte at a time or recv(100000) if you want to grab large chunks. recv is free to return smaller blocks that you ask for, so you may get a different size than you want. 1024 is pretty small, you could read much larger chunks without a problem.

UDP implements a message protocol. You have to ask for enough bytes to cover the entire message or it will be dropped. What that size is depends on the protocol. Its common for protocols to limit messages to 1500 (the max size of a standard ethernet packet) but it could be anything up to 65535. Check the actual protocol specs for maximums.

Rabassa answered 20/3, 2016 at 16:39 Comment(3)
FWIW, I have been using 65536 bytes to listen to logs sent on a UDP socket, I have always been worried about logs at the boundary ie. say a log entry starting at 65530 th byte (which will fall out of this window). According to your explanation all I will get is a single UDP message in a recvfrom() call. Does it mean that I should not worry about dropping logs and am I an idiot to think like that (till now)? I can answer the second question but can you please confirm about the prior, first question?Polytrophic
@Polytrophic - As long its a message based protocol such as UDP, recvfrom gets exactly one message sent by sendto. Assuming the server is sending one log message per UDP message and is not spanning UDP messages on its side, then there is no need to worry.Rabassa
You have to ask for enough bytes to cover the entire message or it will be truncated.Sorghum
T
18

You have them switched. TCP sockets should use socket.recv and UDP sockets should use socket.recvfrom. This is because TCP is a connection-oriented protocol. Once you create a connection, it does not change. UDP, on the other hand, is a connectionless ("send-and-forget") protocol. You use recvfrom so you know to whom you should send data back. Recvfrom does not work on TCP sockets the same way.

As for the 1024/2048, these represent the number of bytes you want to accept. Generally speaking, UDP has less overhead than TCP allowing you to receive more data, but this is not a strict rule and is almost negligible in this context. You can receive as much or as little as you would like. 4096 is common as well (for both).

Topfull answered 20/3, 2016 at 16:15 Comment(1)
You can receive as much or as little as you would like - this is not actually true, at least for UDP, where the maximum packet size is 2^16 = 65536 bytes. Of course, you can receive as many of those as you like though :-)Mopup
Z
5

I think people usually use recvfrom for UDP. Because in TCP, once the connection gets established, the address information does not change and hence recvfrom always returns None for connection-information field.

And in the above code, it will error out in this line:

message2, clientAddress2 = serverSocketTCP.recv(1024)

Because: recvfrom() returns (data, connection_information), and recv() returns just the data. So it will raise ValueError because you are trying to unpack a non-tuple value.

1024, or 2048 just defines the buffer size but it does not wait for exactly that much amount of data before returning. For example:

#One side, 'receiver' is a socket
receiver.recv(2048)

#Second side, 'sender' is a socket
sender.send('abc'.encode('utf-8'))

Clearly the data sent by 'sender' is much less than 2048 bytes but the 'recv' call will return immediately after it receives the data sent to it from 'sender'

Zarathustra answered 20/3, 2016 at 16:14 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.