1

recv is not working as expected. I am sending 10 bytes (verified with wireshark) and recv is only getting the first byte and discarding the rest (until the next sendto). Is this a multicast thing? I'm pretty sure I've done this same thing with unicast UDP and had no issues.

Here is my example code:

import struct, socket, multiprocessing, time

MCAST_PORT = 62950
MCAST_GRP = '239.0.0.13'

def _Rx(self, RXsock, Queue):
   print "Receiver started"
   while True:
      # State machine goes here to parse header and recv (<msglen>) bytes.
      print "Waiting Rx char...", RXsock
      char = RXsock.recv(1)  # Blocks here after first byte ("1") ???
      print "Rx", hex(ord(char))



TXsock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
TXsock.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_TTL, 2)

RXsock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
RXsock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
RXsock.bind((MCAST_GRP, MCAST_PORT))
mreq = struct.pack("4sl", socket.inet_aton(MCAST_GRP), socket.INADDR_ANY)
RXsock.setsockopt(socket.IPPROTO_IP, socket.IP_ADD_MEMBERSHIP, mreq)

RxQueue = multiprocessing.Queue()
receiver = multiprocessing.Process(target=_Rx, args=(None, RXsock, RxQueue))
receiver.daemon = True
receiver.start()


TXsock.sendto("09123456789", (MCAST_GRP, MCAST_PORT))
time.sleep(3)
Bill
  • 77
  • 8
  • Perhaps related: http://stackoverflow.com/questions/2862071/how-large-should-my-recv-buffer-be-when-calling-recv-in-the-socket-library (because its a datagram) – Caramiriel Sep 19 '16 at 15:34

1 Answers1

1

You are only getting one byte because you set your buffer size to one.

From the documentation for socket.recv:

The maximum amount of data to be received at once is specified by bufsize.

Try passing 1024 or 4096 to recv.

From the man page for recv:

If a message is too long to fit in the supplied buffer, excess bytes may be discarded depending on the type of socket the message is received from.

Your comment says that you are trying to parse the header one byte at a time. You can always parse the header after you finish receiving the datagram.

If you really need to do a partial read of the buffer, try passing the socket.MSG_PEEK flag to recv:

MSG_PEEK

This flag causes the receive operation to return data from the beginning of the receive queue without removing that data from the queue. Thus, a subsequent receive call will return the same data.

However, you still won't be able to read one byte at a time.

Community
  • 1
  • 1
  • I set the bufsize to one (1) so I can parse the header a byte at a time. It's in a while loop so it should return the next received byte on the next pass. When the Rx buffer is empty, it should block. Where are the other 9 bytes going? It seems to be doing a flush along with the read. – Bill Sep 19 '16 at 21:33
  • The other 9 bytes are discarded. See the excerpt from the `recv` man page above. –  Sep 19 '16 at 21:42
  • You can play around with `MSG_PEEK`, but it won't let you read one byte at a time. The best you can do would be to peek at N bytes and use them to decide whether or not to read the rest. –  Sep 19 '16 at 22:01