当一个到达的UDP数据报超过应用程序提供的缓冲区容量时,recvmsg在其 msghdr结构的msg_flags成员上设置MSG_TRUNC标志。
所有支持msghdr结构及其msg_flags成员的实现都提供这种通知。但并非所有实现都以同一种方式处理超过预期长度的UDP数据报
存在三种情况:
1.丢弃超出部分的字节并向应用进程返回MSG_TRUNC标志,调用recvmsg可以接收这个标志
2.丢弃超出部分的字节但不通知这个标志
执行结果:
所有支持msghdr结构及其msg_flags成员的实现都提供这种通知。但并非所有实现都以同一种方式处理超过预期长度的UDP数据报
存在三种情况:
1.丢弃超出部分的字节并向应用进程返回MSG_TRUNC标志,调用recvmsg可以接收这个标志
2.丢弃超出部分的字节但不通知这个标志
3.保留超出部分的字节并在同一套接字后续的读操作中返回它们
实例
客户程序
#include <iostream>
#include <strings.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <stdlib.h>
using namespace std;
struct buf
{
int order;
unsigned char data[10];
int add;
};
int main()
{
int sockfd;
int r;
int on = 1;
struct sockaddr_in saddr;
struct buf buf;
sockfd = socket(AF_INET, SOCK_DGRAM, 0);
setsockopt(sockfd, SOL_SOCKET, SO_BROADCAST, &on, sizeof(on));
bzero(&saddr, sizeof(saddr));
saddr.sin_family = AF_INET;
saddr.sin_addr.s_addr = inet_addr("192.168.199.255");
saddr.sin_port = htons(9999);
buf.order = 1;
strcpy((char*)buf.data, "Hello");
buf.add = 2;
r = sendto(sockfd, &buf, sizeof(buf), 0,
(struct sockaddr*)&saddr, sizeof(saddr));
if (r == -1)
{
perror("sendto error");
exit(-1);
}
cout << "finish" << endl;
return 0;
}
服务程序
#include <iostream>
#include <strings.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <stdlib.h>
using namespace std;
struct buf
{
int order;
unsigned char data[10];
};
int main()
{
int sockfd;
int r;
socklen_t len;
struct sockaddr_in saddr;
struct buf buf;
struct sockaddr_in caddr;
struct msghdr msg;
struct iovec iov;
struct cmsghdr *cmptr;
union
{
struct cmsghdr cm;
char control[CMSG_SPACE(sizeof(int))];
} control_un;
sockfd = socket(AF_INET, SOCK_DGRAM, 0);
bzero(&saddr, sizeof(saddr));
saddr.sin_family = AF_INET;
saddr.sin_addr.s_addr = htonl(INADDR_ANY);
saddr.sin_port = htons(9999);
if (bind(sockfd, (struct sockaddr*)&saddr, sizeof(saddr)) < 0)
{
perror("bind error");
exit(-1);
}
msg.msg_name = NULL;
msg.msg_namelen = 0;
iov.iov_base = &buf;
iov.iov_len = sizeof(buf);
msg.msg_iov = &iov;
msg.msg_iovlen = 1;
msg.msg_control = control_un.control;
msg.msg_controllen = sizeof(control_un.control);
msg.msg_flags = 0;
while (1)
{
r = recvmsg(sockfd, &msg, 0);
if (r < 0)
{
perror("recvfrom error");
exit(-1);
}
cout << buf.order << endl;
cout << buf.data << endl;
cout << endl;
int recv_len = r;
//判断是否发生数据报截断
if (msg.msg_flags == MSG_TRUNC)
{
cout << "数据报截断" << endl;
unsigned char temp_buf[200];
r = recvfrom(sockfd, &temp_buf, sizeof(temp_buf), 0,
NULL, 0);
if (r == recv_len+sizeof(int))
{
cout << "超出的部分被保留" << endl;
} else {
cout << "超出的部分被丢弃" << endl;
}
}
}
return 0;
}
执行结果:
发送第一个数据报
发送第二个数据报
发送第三个数据报