I am writing a simple UDP-based client/server app and testing with both the client/server on localhost, and I would like for the sender to know when send() would have blocked. I am using Python, so I think I can do:
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.setblocking(0)
s.connect(('127.0.0.1', 12345))
data = "x"
for i in range(0, 9000): # More than about 9000 gives an error
data += x
while True:
try:
s.send(data)
except socket.error as e:
print "Would have blocked"
# Do something useful here
I would like to test that my error-handling code works, so I would like to get send() to want to block. The problem is, I cannot figure out how to do that. I have tried have:
BUFFSIZE = 2000
input = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
input.setsockopt(socket.SOL_SOCKET, socket.SO_RCVBUF, BUFFSIZE)
input.bind(('127.0.0.1', 12345))
while True:
data = input.recv(BUFFSIZE)
time.sleep(100)
Between sleeping for 100 sec and setting a small receive buffer, I would have expected the buffer to have filled up. However, it never does. So how can I get the receive buffer to fill up so that send blocks?
I am using Mac OS Lion and the Macports version of Python 2.6.
UDP doesn’t normally block. If the receiver has a full buffer, the packet gets silently discarded. This is by design. If you want reliable transport and blocking semantics, use TCP instead.
Comment: The reason TCP blocks is because the sender gets confirmation for every packet it sends. The sender only allows a certain amount of data “in transit” that does not have confirmation, and blocks when this threshold is reached. Since UDP does not send confirmation of received packets, the sender has no way of knowing when to block. Of course, it might decide to block if it saturates its Ethernet port, but with UDP there is no way to tell if your uplink is saturated, the receiver is hung, or gremlins ate your packet. No guarantees!