简体   繁体   English

POSIX UDP套接字:如何将数据拆分为UDP数据包?

[英]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. 我有一个C ++-Linux应用程序,应该以我公司设计的某种协议发送UDP数据包。
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. 协议声明每个数据块都应附加到开头的标头,结尾处的页脚,并且标头+数据+页脚应作为单个UDP数据包发送到远程端。 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? 每个sendto都转换为单个UDP数据包吗? meaning I have three UDP packets here? 意思是我这里有三个UDP数据包? 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? 如果不是,我如何定义posix给我的是什么数据包?
  3. how can I send multiple buffers as a single UDP packet, any idea? 怎样将多个缓冲区作为单个UDP数据包发送?

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). 每个sendto都会创建一个UDP数据包(可以将其分割为多个IP数据包,而这些IP数据包又可以由链路层进行分割,依此类推)。 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而不是sendto sendmsg processes a struct msghdr , which has msg_iov and msg_iovlen members, where you can specify an array of buffers to send. sendmsg处理一个struct msghdr ,其具有msg_iovmsg_iovlen成员,可以在其中指定缓冲器阵列发送。

Richard Stevens, UNIX Network Programming , still explains all that very well. UNIX网络编程的 Richard Stevens仍然很好地解释了所有这些。

If you really want to call sendto 3 times, you have the following method 如果您确实要呼叫sendto 3次,则可以使用以下方法

Approach 1 方法1

Flags argument of sendto function. 标志sendto函数的参数。 flag MSG_MORE . 标志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 方法2

Socket option of udp socket. udp套接字的套接字选项。 option UDP_CORK . 选项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));

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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