typedef struct _iphdr //定义IP首部
{ unsigned char h_lenver; //4位首部长度+4位IP版本号 unsigned char tos; //8位服务类型TOS unsigned short total_len; //16位总长度(字节) unsigned short ident; //16位标识 unsigned short frag_and_flags; //3位标志位 unsigned char ttl; //8位生存时间 TTL unsigned char proto; //8位协议 (TCP, UDP 或其他) unsigned short checksum; //16位IP首部校验和 unsigned int destIP; //32位目的IP地址
}IP_HEADER;
如何计算UDP/TCP检验和checksum
一、下面的图是一个UDP的检验和所需要用到的所有信息,包括三个部分:
1.UDP伪首部
2.UDP首部
3.UDP的数据部分(切记不要遗漏该部分,否则就~吐血了~)
首先解释下伪首部的概念,伪首部包含IP首部一些字段。其目的是让UDP两次检查数据是否已经正确到达目的地,只是单纯为了做校验用的。
还有一个概念十分重要,那就是16位UDP总长度,请注意该长度不是报文的总长度,而只是UDP(包括UDP头和数据部分)的总长度(之前就是因为这个概念没弄清楚,走了不少弯路,吐血~~)。
二、计算检验和(checksum)的过程很关键,主要分为以下几个步骤:
1.把伪首部添加到UDP上;
2.计算初始时是需要将检验和字段添零的;
3.把所有位划分为16位(2字节)的字
4.把所有16位的字相加,如果遇到进位,则将高于16字节的进位部分的值加到最低位上,举例,0xBB5E+0xFCED=0x1B84B,则将1放到最低位,得到结果是0xB84C
5.将所有字相加得到的结果应该为一个16位的数,将该数取反则可以得到检验和checksum。
三、事实胜于雄辩,还是举个例子来分析一下吧,该例子计算的是一个TCP的检验和(和UDP的算法一致)
TCP计算检验和的报文结构如下所示:
抓包工具抓了一个TCP的syn报文做研究,呵呵,下面就是整个报文:
1.首先将检验和部分添零;
2.然后将TCP伪首部部分,TCP首部部分,数据部分都划分成16位的一个个16进制数;
3.将这些数逐个相加,记得溢出的部分加到最低位上,这是循环加法:
0xc0a8+0x0166+……+0x0402=0x9b49
4.最后将得到的结果取反,则可以得到检验和位0x64B6
按照上述步骤进行计算就可以得到检验和为0x64B6,大家也可以试试看
IP数据报只检验IP数据报的首部,但UDP检验的是把首部和数据部分一起都检验。
#include
#include
typedefstruct {
int srcIp;
int dstIp;
short udp_len;
char rsv;
char protocol;
unsignedshort src_port;
unsignedshort dst_port;
unsignedshort len;
unsignedshort check_sum;
char data[2];
} UDPHDR;
char arr[100] = {0xc0,0xa8,0xd1,0x80,0xc0,0xa8,0xd1,0x01,0x00,0x0a,0x00,0x11,0x13,0x88,0x13,0x88,0x00,0x0a,0x00,0x00,0x61,0x66};
unsignedshortcheck_sum(unsignedshort *a,int len);
intmain()
{
short b =0;
UDPHDR udphdr = {0};
udphdr.srcIp = inet_addr("192.168.209.128");
udphdr.dstIp = inet_addr("192.168.209.1");
udphdr.udp_len = htons(10);
udphdr.protocol =0x11;
udphdr.rsv =0;
udphdr.src_port = htons(5000);
udphdr.dst_port = htons(5000);
udphdr.len = htons(10);
udphdr.check_sum =0;
udphdr.data[0] =0x61;
udphdr.data[1] =0x66;
b = check_sum((short *)&udphdr,22);
printf("[test ...] b = %04x\n", b &0xffff);
b = check_sum((short *)arr,22);
printf("[test arr] b = %04x\n", b &0xffff);
return0;
}
unsignedshortcheck_sum(unsignedshort *a,int len)
{
unsignedint sum =0;
while (len >1) {
sum += *a++;
len -=2;
}
if (len) {
sum += *(unsignedchar *)a;
}
while (sum >>16) {
sum = (sum >>16) + (sum &0xffff);
}
return (unsignedshort)(~sum);
}
转载:https://blog.csdn.net/sinat_35512245/article/details/53836580
虚拟互联网络 A怎么和C进行通信呢? 网络层解决的问题 虚拟互联网络简介 A和B之间可以通过虚拟互联网络进行通信 ...IP协议的作用IP协议地址IP数据报IP协议的首部IP协议首部详解 常见协议和位数 ...
虚拟互联网络
A怎么和C进行通信呢?

网络层解决的问题

虚拟互联网络简介

A和B之间可以通过虚拟互联网络进行通信

IP协议的作用

IP协议地址

IP数据报

IP协议的首部

IP协议首部详解

常见协议和位数

IP协议的转发流程

本章的内容主要是将IP 协议头部、TCP 协议头部、UPD协议进行说明,其他的介绍将在后续的章节中进行详细介绍。 注:本章内容来自《TCP/IP详解卷一协议》IP 协议 1.IPv4头部结构	版本	IPv4=...
本章的内容主要是将 IP 协议头部、TCP 协议头部、UPD协议进行说明,其他的介绍将在后续的章节中进行详细介绍。
注:本章内容来自《TCP/IP详解卷一协议》
IP 协议

1.IPv4 头部结构

版本
IPv4=4 / IPv6=6
IHL
头部长度,保存 IPv4 中32位字的数量(4个字节),是一个4位字段,表示最多15个32位字即60个字节,IPv6 没有这个字段,固定40个字节
TCP 头部结构
DS
区分服务 RFC2474、RFC2475、RFC3260
ECN
显示拥塞通知
总长度
IP数据包总长度,以字节为单位,65535,通过IHL可以知道数据报从哪里开始。
标识
为了避免将一个数据报分片和其他数据报分片混淆,发送主机通常在每次发送数据报时都将一个内部计数+1,计数器复制到这个标识字段
标志
RF/DF/MF
分片偏移
生存期
数据报可经路由的上限,每经过一个路由就减一,避免陷入循环
协议
协议包含一个数字,表示有效荷载部分的数据类型,最常用的为17(UPD) 和6(TCP)
头部校验
仅计算IPv4的头部,不检查有效荷载的正确性,其他协议必须通过自己的机制进行检查重要数据。每次IP跳转都会被重新计算一次

2.IPv6 头部结构

版本号
DS
ECN
流标签
流标签字段是 IPv6 数据报中新增的一个字段,占20位,可用来标记报文的数据流类型,以便在网络层区分不同的报文。流标签字段有源节点分配,通过流标签、源地址、目的地址三元组方式就可以唯一标识一条通信流,而不用像 IPv4 那样需要使用五元组方式(源地址、目的地址、源端口、目的端口和传输层协议号)。
负载长度
有效载荷长度字段是以字节为单位的标识 IPv6 数据报中有效载荷部分(包括所有扩展报头部分)的总长度,也就是除了 IPv6 的基本报头以外的其他部分的总长度,占20位。
下一个头部
下一个头部字段用来标识当前报头(或者扩展报头)的下一个头部类型,占8位。每种扩展报头都有其对应的值。下一个头部字段内定义的扩展报头类型与 IPv4 中的协议字段值类似,但在 IPv6 数据报中,紧接着 IPv6 报头的可能不是上层协议头部(当没有扩展报头或者为最后一个扩展报头时才是上层协议头),而是 IPv6 扩展报头。
当IPv6 数据报文承载的是上层协议 ICMPv6、TCP、UDP等的时候,Next Header 的值分别为 58、6、17,这个时候和 IPv4 报文头部中的 Protocol 字段很类似;
当不是以上3种协议类型的时候,IPv6 报文头部紧接的是扩展头部。扩展头部是 IPv6 引入的一个新的概念,每个 IPv6 的数据报文可以承载0个或多个扩展头部,扩展头部通过链表的形式组织起来。当IPv6 数据报文承载着扩展头部的时候,Next Header 的数值为扩展头部的类型值。
跳数限制

3.IPv6 相比 IPv4

IPv6 去除了 IPv4 报头中的头部长度、标识、标志、段偏移、校验和、选项、填充这么多字段,却只增加了流标签这一个字段,因此 IPv6 报头处理和I Pv4 报头处理相比大大简化,提高了处理效率。另外,IPv6 为了更好地支持各种选项处理,提出了扩展头的概念,新增选项时不必修改现有的结构就能做到,理论上可以无限扩展,体现了优异的灵活性。
UDP协议
用户数据报协议 UDP(User Datagram Protocol)特点:
(1)无连接。
(2)尽最大努力的交付。
(3)面向报文。
(4)无拥塞控制。
(5)支持一对一、一对多、多对一、多对多的交互通信。
(6)首部开销小(只有四个字段:源端口、目的端口、长度、检验和)。UDP 是面向报文的传输方式是应用层交给 UDP 多长的报文,UDP 发送多长的报文,即一次发送一个报文,因此,应用程序必须选择合适大小的报文。

1.UDP协议头部结构

长度
长度是 UDP 头部和 UDP 数据的总长度。
校验和
端到端的传输层校验和。它覆盖 UDP 头部、UDP 数据和一个伪头部

2.UDP 伪头部

3.UDP/IP分片

例如:前置条件 MTU=1500 Data Lenght= 2992。
说明:

一个数据包包含了2992字节的应用数据,和8个UDP头部,结果产生一个总长度为3020数据报(包含 Ipv4 头部)。当数据报被分成三组时,额外产生了40个额外字节,因此总发生字节为3060
偏移 以8个字节为单位:
重组:
当MF=0 的分片被接收到时,重组程序才能确认原始数据的长度,它等于分片偏移的值(乘以8) 加上 IPv4 总长度的值(减去IPv4头部长度)。(370*8+40==3000)
因为每个偏移字段都是相对原始数据报的,重组进程可以处理非顺序到达的分片。
重组超时:
一个数据报的任何一个分片首先到达,IP 层就得启动一个计时器,如果不这样做的话,不能达到的分片,可能会最终导致接收方用尽缓存。留下攻击的机会。
分片是透明的,但如果一个分片丢失,整个数据报就丢失。要知道IP自身没有差错纠正。所以要么程序自己实现超时和重传。要么尽量避免分片

4. UDP SOCKET 连接流程图

TCP 协议
传输控制协议 TCP(Transmission Control Protocol)特点:
(1)面向连接,每一个 TCP 连接只能是点对点的(一对一)。
(2)提供可靠交付服务。
(3)提供全双工通信。
(4)面向字节流。
(5)应用程序和 TCP 的交互是一次一个数据块(大小不等),但TCP 把应用程序看成是一连串的无结构的字节流。TCP 有一个缓冲,当应该程序传送的数据块太长,TCP 就可以把它划分短一些再传送。

1.TCP头部结构

头部字段: