The below code is from Git. It joins a multicast group and receives packets.
Here we loop and receive the data in a buffer called msgbuf
:
while (1)
{
char msgbuf[MSGBUFSIZE];
const int addrlen = sizeof(addr);
const int nbytes = recvfrom(fd, msgbuf, MSGBUFSIZE, 0, (struct sockaddr *) &addr, &addrlen);
How do I choose the size for the buffer msgBuf
? Does it just have to be the max packet size? Or do I need to store multiple packets whilst I process the first?
Full code:
int main(int argc, char *argv[])
{
if (argc != 3) {
printf("Command line args should be multicast group and port\n");
printf("(e.g. for SSDP, `listener 239.255.255.250 1900`)\n");
return 1;
}
char* group = argv[1]; // e.g. 239.255.255.250 for SSDP
int port = atoi(argv[2]); // 0 if error, which is an invalid port
if(port <= 0)
{
perror("Invalid port");
return 1;
}
// create what looks like an ordinary UDP socket
//
int fd = socket(AF_INET, SOCK_DGRAM, 0);
if (fd < 0)
{
perror("socket");
return 1;
}
// allow multiple sockets to use the same PORT number
//
u_int yes = 1;
if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char*) &yes, sizeof(yes)) < 0)
{
perror("Reusing ADDR failed");
return 1;
}
// set up destination address
//
struct sockaddr_in addr;
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = htonl(INADDR_ANY); // differs from sender
addr.sin_port = htons(port);
// bind to receive address
//
if (bind(fd, (struct sockaddr*) &addr, sizeof(addr)) < 0)
{
perror("bind");
return 1;
}
// use setsockopt() to request that the kernel join a multicast group
//
struct ip_mreq mreq;
mreq.imr_multiaddr.s_addr = inet_addr(group);
mreq.imr_interface.s_addr = htonl(INADDR_ANY);
if (setsockopt(fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char*) &mreq, sizeof(mreq)) < 0)
{
perror("setsockopt");
return 1;
}
// now just enter a read-print loop
//
while (1)
{
char msgbuf[MSGBUFSIZE];
const int addrlen = sizeof(addr);
const int nbytes = recvfrom(fd, msgbuf, MSGBUFSIZE, 0, (struct sockaddr *) &addr, &addrlen);
if (nbytes < 0)
{
perror("recvfrom");
return 1;
}
msgbuf[nbytes] = '\0';
puts(msgbuf);
}
return 0;
}
Unlike TCP which combines packets into a stream, UDP respects packet boundaries so recvfrom
only gets one packet at a time.
So MSGBUFSIZE
only needs to be as big as a single packet. If you're not using jumbo packets that would be 1500, otherwise it would be 9000.