数据报截断

当一个到达的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;
}

执行结果:

发送第一个数据报

发送第二个数据报

发送第三个数据报

数据报截断,布布扣,bubuko.com

时间: 2024-12-10 20:35:55

数据报截断的相关文章

《TCP/IP详解卷1:协议》第11章 UDP:用户数据报协议-读书笔记

章节回顾: <TCP/IP详解卷1:协议>第1章 概述-读书笔记 <TCP/IP详解卷1:协议>第2章 链路层-读书笔记 <TCP/IP详解卷1:协议>第3章 IP:网际协议(1)-读书笔记 <TCP/IP详解卷1:协议>第3章 IP:网际协议(2)-读书笔记 <TCP/IP详解卷1:协议>第4章 ARP:地址解析协议-读书笔记 <TCP/IP详解卷1:协议>第5章 RARP:逆地址解析协议-读书笔记 <TCP/IP详解卷1:协

linux系统socket通信编程实践

简单介绍并实现了基于UDP(TCP)的windows(UNIX下流程基本一致)下的服务端和客户端的程序,本文继续探讨关于UDP编程的一些细节. 下图是一个简单的UDP客户/服务器模型: .imageplus-append-lu-img-txt { overflow: hidden; margin: 10px 0 } .imageplus-append-nova-txt { border: 1px solid #f2f2f2; font-family: Microsoft YaHei; line-

Linux下的socket编程实践(十) 基本UDP编程细节

在我的这两篇博客中,简单介绍并实现了基于UDP(TCP)的windows(UNIX下流程基本一致)下的服务端和客户端的程序,本文继续探讨关于UDP编程的一些细节. http://blog.csdn.net/nk_test/article/details/47733307 http://blog.csdn.net/nk_test/article/details/47756381 下图是一个简单的UDP客户/服务器模型: 我在这里也实现了一个简单的UDP回射服务器/客户端: /**实践: 实现一个基

【网络协议】UDP协议

UDP是一个简单的面向数据报的运输层协议:进程的每个输出操作都会产生一个UDP数据报,并组装成一份待发送的IP数据报,这与面向字符流的协议不同,如TCP,应用程序产生的全体数据与真正发送的单个IP数据报可能没有什么联系(主要是在传输层就进行分段了,因此不会受IP分片的影响). UDP的首部一共8个字节,很简单,可以参考书上,这里也不再详说. UDP的校验和 至于UDP的校验和,这里注意下区别就好了,UDP对首部和数据部分都进行校验,而IP首部的校验和仅对IP的首部进行校验,顺带提下TCP,TCP

《TCP/IP详解卷2:实现》笔记--UDP:用户数据报协议

用户数据报协议,即UDP,是一个面向数据报的简单运输层协议:进程的每次输出操作只产生一个UDP数据报,从而发送 一个IP数据报. 进程通过创建一个Internet域内的SOCK_DGRAM类型的插口,来访问UDP.该类型插口默认地称为无连接的.每次进程发送 数据时,必须指定目的IP地址和端口号.每次从插口上接收数据报时,进程可以从数据报中收到源IP地址和端口号. UDP插口也可以被连接到一个特殊的IP地址和端口,这样,所有写到该插口的数据报都被发往该目的地,而且只有来自该IP 地址和端口号的数据

SLIP—串行线路上传输数据报的非标准协议

做了这么多年的程序员后,总想资源回收一下,写一点点什么,却又发现无从写起. SLIP-串行线路上传输数据报的非标准协议 简介 TCP/IP 协议族可以在许多网络介质上运行,如: IEEE 802.3 (以太网)和802.5(令牌环)局域网,X.25线路,卫星连接和串行线路.除了串行线路外,其它的介质上都有包格式的标准. SLIP(Serial Line Internet Protocol,串行线路网际协议),该协议是Windows远程访问的一种旧工业标准,主要在Unix远程访问服务器中使用,现今

sql server 导入平面文件源数据,错误 0xc02020a1错误 0xc020902a 错误 0xc02020c5,返回状态值 4 和状态文本“文本被截断,或者一个或多个字符在目标代码页...

使用sql server 导入平面文件源数据时,报错:错误 0xc02020a1: 错误 0xc020902a: 错误 0xc02020c5:错误 0xc0047022: 返回状态值 4 和状态文本"文本被截断,或者一个或多个字符在目标代码页中没有匹配项. 错误 0xc02020a1: 数据流任务 1: 数据转换失败.列"列 6"的数据转换返回状态值 4 和状态文本"文本被截断,或者一个或多个字符在目标代码页中没有匹配项.". (SQL Server 导入

解决CSS3多列样式column-width布局时内容被截断、错乱

一.问题 使用CSS3的column-width: auto | <length>属性时,出现排列的内容被截断,出现错位的现象. 二.原因 需要为图片容器设置高度,不然会崩掉. 三.解决方法 给需要分列的容器加上height:100%;overflow: auto;. 解决CSS3多列样式column-width布局时内容被截断.错乱

关于四舍五入和截断

四舍五入输出2.35 1 int main() { 2 double a = 2.345; 3 printf("%.2f\n", a); 4 return 0; 5 } 截断输出2.34 1 int main() { 2 double a = 2.345; 3 a = int(a * 100) / 100.0; 4 printf("%.2f\n", a); 5 return 0; 6 }