简体   繁体   中英

POSIX UDP socket: how is the data splitted to UDP packets?

I have a C++-Linux application that should send UDP packets in a some protocol that designed in my company.
The protocol declares each chunk of the data should be attached to a header in the beginning and footer at the end, and header+data+footer should be sent as a single UDP packet to the remote end. For example: opening socket:

struct hostent *udphost;
udphost = gethostbyname(_remoteIp.c_str());
if(udphost == NULL)
{
  ESPFS_DEBUG ("invalid host address format\n" );
  return;
}

bzero((char *) &_udpSockAddr, sizeof(_udpSockAddr));
_udpSockAddr.sin_family = AF_INET;
bcopy((char *)udphost->h_addr, (char *)&_udpSockAddr.sin_addr.s_addr, udphost->h_length);
_udpSockAddr.sin_port = htons(UDP_PORT);

sending data:

protocol_header hdr;  
protocol_footer ftr;    
sendto(_udpSocket, hdr, sizeof(hdr), 0, (const struct sockaddr *)&_udpSockAddr, sizeof(_udpSockAddr));  
sendto(_udpSocket, data, data_size, 0, (const struct sockaddr *)&_udpSockAddr, sizeof(_udpSockAddr));  
sendto(_udpSocket, ftr, sizeof(ftr), 0, (const struct sockaddr *)&_udpSockAddr, sizeof(_udpSockAddr)); 

Now my questions are:

  1. Does each sendto translate to single UDP packet? meaning I have three UDP packets here? if so, where is it documented? I don't find any mention to that.
  2. If not, how can I define to the posix what is packet to me?
  3. how can I send multiple buffers as a single UDP packet, any idea?

Each sendto creates one UDP packet (which can be fragmented into multiple IP packets, which in turn could be fragmented by the link layer, and so on). This is pretty much the definition of a datagram socket.

If you have multiple buffers you want to concatenate before sending, you can use sendmsg instead of sendto . sendmsg processes a struct msghdr , which has msg_iov and msg_iovlen members, where you can specify an array of buffers to send.

Richard Stevens, UNIX Network Programming , still explains all that very well.

If you really want to call sendto 3 times, you have the following method

Approach 1

Flags argument of sendto function. flag MSG_MORE .

sendto(_udpSocket, hdr, sizeof(hdr), MSG_MORE, (const struct sockaddr *)&_udpSockAddr, sizeof(_udpSockAddr));  
sendto(_udpSocket, data, data_size, MSG_MORE, (const struct sockaddr *)&_udpSockAddr, sizeof(_udpSockAddr));  
sendto(_udpSocket, ftr, sizeof(ftr), 0, (const struct sockaddr *)&_udpSockAddr, sizeof(_udpSockAddr));

Approach 2

Socket option of udp socket. option UDP_CORK .

int zero = 0;
int one = 1;
setsockopt(_udpSocket, IPPROTO_UDP, UDP_CORK, &one, sizeof(one));
sendto(_udpSocket, hdr, sizeof(hdr), 0, (const struct sockaddr *)&_udpSockAddr, sizeof(_udpSockAddr));  
sendto(_udpSocket, data, data_size, 0, (const struct sockaddr *)&_udpSockAddr, sizeof(_udpSockAddr));  
sendto(_udpSocket, ftr, sizeof(ftr), 0, (const struct sockaddr *)&_udpSockAddr, sizeof(_udpSockAddr));
setsockopt(_udpSocket, IPPROTO_UDP, UDP_CORK, &zero, sizeof(zero));

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM