数据报截断
当一个到达UDP当数据包超过由应用程序提供的缓冲容量,recvmsg在其 msghdr结构体msg_flags设置成员MSG_TRUNC马克。
全面支持msghdr结构msg_flags提供会员达到这样的通知。
运行结果:
全面支持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; }
运行结果:
发送第一个数据报
发送第二个数据报
发送第三个数据报
版权声明:本文博客原创文章。博客,未经同意,不得转载。