• 数据报截断


    当一个到达UDP当数据包超过由应用程序提供的缓冲容量,recvmsg在其 msghdr结构体msg_flags设置成员MSG_TRUNC马克。
    全面支持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;
    }

    运行结果:

    发送第一个数据报

    发送第二个数据报

    发送第三个数据报


    版权声明:本文博客原创文章。博客,未经同意,不得转载。

  • 相关阅读:
    解决Oracle XE报错ORA-12516(oracle回话数超出限制)
    端口被占用如何处理
    ORACLE initialization or shutdown in progress 错误解决办法
    oracle的闪回功能
    Linux入门
    oracle字段like多个条件
    navicat常用快捷键与SQL基本使用
    Oracle四舍五入,向上取整,向下取整
    无限循环小数化分数
    筛选素数
  • 原文地址:https://www.cnblogs.com/mfrbuaa/p/4612804.html
Copyright © 2020-2023  润新知