TCP/IP协议深度解析

TCP如何有序性的的拥塞控制TCP的半连接队列与全连接队列TCP粘包与分包网线断了, TCP怎么处理TCP的长连接与短连接TCP的11个状态迁移send返回正数, 是不是成功?阻塞与非阻塞, send/recv, -1 如何取到一帧完整的数据包 raw1 网络协议栈 1.1 OSI模型
物理层: 传输的光电信号
数据链路层: 数字信号
网卡: 将数字信号转换为光电信号(AD/DA), 因此不属于协议栈的那一层
1.2 协议栈是什么 ?
根据分层的思想, 每一层都有对应得协议, 从而形成一个协议家族 --> 协议栈
1.3 协议栈的实现
linux中, 网卡利用实现将数据传进内核协议栈中, 接着协议栈进行解析
因此如果要自己实现协议栈解析, 就需要获取网卡内存中的数据, 这里利用, 可实现截获网卡中的数据, 并将网卡内存映射到本机内存空间中(利用mmap实现映射, 底层是DMA)
1.3.1 UDP协议 0) 一帧完整的udp数据
struct udppkt {struct ethhdr eth;struct iphdr ip;struct udphdr udp;unsigned char body[0];};
1) 以太网协议头
#define HEAD_LENGTH6struct ethhdr {unsigned char dst[HEAD_LENGTH];unsigned char src[HEAD_LENGTH];unsigned short proto;};
【TCP/IP协议深度解析】2) IP协议头
struct iphdr {unsigned char version: 4,hdrlen: 4;unsigned char tos;unsigned short tot_len;unsigned short id;unsigned short flag: 3,offset: 13;unsigned char ttl;unsigned char proto;unsigned short check;unsigned int sip;unsigned int dip;};
3) UDP协议头
struct udphdr {unsigned short sport;unsigned short dport;unsigned short length;unsigned short check;};

TCP/IP协议深度解析

文章插图
* 协议栈实现时会遇到的问题及其原理 ping不通 --> 没有实现ICMP过一段时间后, send数据不成功 --> 没有实现ARP, 源地址没得到回应, 会以为目标地址已经连接不上1.3.2 TCP协议实现
有了前面 arp/icmp/udp 我们就可以实现 tcp
0) 如何实现tcp 协议头三次握手/四次挥手, 11个状态迁移tcp的顺序, 如何保证有序, 延迟ack/滑动窗口定时器, rtt, 慢启动与拥塞控制POSIX send/recv接口, epoll如何实现 (与协议栈交互) 1) tcp协议头
struct tcphdr {unsigned short sport;unsigned short dport;unsigned int seqnum;unsigned int acknum;unsigned char hdrlen: 4,resv: 4;unsigned char cwr: 1,ece: 1,urg: 1,ack: 1,psh: 1,rst: 1,syn: 1,fin: 1;unsigned short wsize;unsigned short tcpcheck;unsigned short urg_pointer;unsigned char options[0];};
2) 三次握手/四次挥手, 11个状态迁移3) 延迟ack/滑动窗口4) tcp四个重要的定时器 超时重传坚持定时器(探测)keep5) RTT6) 慢启动与拥塞控制
慢启动: 开始从1 -> 2 -> 4 … 16 (该过程为指数增长)
拥塞控制: 当到达值时, 会呈线性增长, 当增长到窗口大小时, 会变为1/2
2 demo代码(只实现udp)
/* netmap */#include #include #include #include #define NETMAP_WITH_LIBS#include #pragma pack(1)//单字节对齐#define PROTO_IP0x0800#define PROTO_UDP17#define ETH_LENGTH6struct ethhdr {unsigned char dst[ETH_LENGTH];unsigned char src[ETH_LENGTH];unsigned short proto;};struct iphdr {unsigned char version: 4,hdrlen: 4;unsigned char tos;unsigned short tot_len;unsigned short id;unsigned short flag: 3,offset: 13;unsigned char ttl;unsigned char proto;unsigned short check;unsigned int sip;unsigned int dip;};struct udphdr {unsigned short sport;unsigned short dport;unsigned short length;unsigned short check;};struct udppkt {struct ethhdr eth;struct iphdr ip;struct udphdr udp;unsigned char body[0];};struct tcphdr {unsigned short sport;unsigned short dport;unsigned int seqnum;unsigned int acknum;unsigned char hdrlen: 4,resv: 4;unsigned char cwr: 1,ece: 1,urg: 1,ack: 1,psh: 1,rst: 1,syn: 1,fin: 1;unsigned short wsize;unsigned short tcpcheck;unsigned short urg_pointer;unsigned char options[0];};int main(){struct nm_desc *nmr = nm_open("netmap:eth0", NULL, 0, NULL);if (nmr == NULL) {return -1;}struct pollfd pfd = {0};pfd.fd = nmr->fd;pfd.events = POLLIN;while (1) {int ret = poll(&pfd, 1, -1);if (ret