⽤户态协议栈
章节
为什么要实现⽤户态协议栈?
深⼊理解⽹络协议栈
⾛进Linux内核开发的第⼀步
加⼊开源组织,提升技术实⼒
1. ⽤户态协议栈
2. dpdk/netmap
3. c10M的问题,千万并发
客户端发送数据到服务器,服务器接收数据的步骤:
1. 从⽹卡copy到内核协议栈
2. 从内核协议栈copy到应⽤程序
提升系统的性能,降低瓶颈,我们可以设计⽤户态协议栈,实现零拷贝(直接从⽹卡copy到应⽤程序,减少了⼀次拷贝操作)
为了使⽹卡的数据,直接到达我们应⽤程序的⽅案:
1. mmap
2. pf_ring, libcap, raw_socket.
既然原⽣的socket可以实现抓取到链路层的数据,是因为⽹卡抓取到链路层的数据不代表是抓取到⽹卡中的数据,使⽤原⽣的soket也会经过两次拷贝,从⽹卡copy到内核协议栈,从内核协议栈copy到应⽤程序(只是此时不会经过tcp协议栈)
mmap把外设中的数据直接映射到内存中,有了mmap的映射,就有了实现直接抓取⽹卡数据,netmap就是这样实现的。
netmap与dpdk对⽐
netmap只是纯软件⽅式的开源框架,dpdk的使⽤场景,稳定性⽐netmap⼴
C10K->C10M
c10K的解决⽅案:
(1) 在没有epoll出现时:
select/poll
多线程/多进程
select/poll存在的问题:
数量(1. 所有io集合的数量; 2. 设置有少量的io会被触发,成为就绪状态):⼀个select监控1024个fd
拷贝():
多线程/多进程存在的问题:
内存:
(2) epoll的出现解决了的问题:
数量:所有io集合的数量,把所有需要的⽹络io放在⼀起,少量io会被触发程序就绪状态
拷贝: ⼀次⼀次添加到整个集合
数据结构:
把所有需要的⽹络io放在⼀起
少量io会就绪
tcpip协议pdfC10M的解决⽅案:
需要从以下⼏个⽅⾯来考虑
1. 内存
2. CPU
3. 磁盘
4. ⽹卡
5. 应⽤程序
6. 操作系统
⽹卡, NIC(network interface card),netmap
nic是对⽹卡的⼀层软件级封装;
etho是nic针对物理⽹卡的实例化对象;
netmap由两部分组成:
1. 内核模块—>对nic⼦系统进⾏了扩展
2. 应⽤程序接⼝
⽤户态协议栈之TCPIP设计
⾸先抛出疑问:
1. 滑动窗⼝如何实现?
滑动窗⼝协议的基本原理就是在任意时刻,发送⽅都维持了⼀个连续的允许发送的帧的序号,称为发送窗⼝;同时,接收⽅也维持了⼀个连续的允许接收的帧的序号,称为接收窗⼝。发送窗⼝和接收窗⼝的序号的上下界不⼀定要⼀样,甚⾄⼤⼩也可以不同。不同的滑动窗⼝协议窗⼝⼤⼩⼀般不同。发送⽅窗⼝内的序列号代表了那些已经被发送,但是还没有被确认的帧,或者是那些可以被发送的帧。
简单的说就是发送端发送缓冲区中允许发送,但尚未发送的数据所组成的窗⼝;接收端中接收缓冲区允许接受数据组成的窗⼝;
2. sk_buff是什么?
sk_buff(socket buffer)结构是linux⽹络代码中重要的数据结构,它管理和控制接收或发送数据包的信息
参照wwwblogs/tzh36/p/5424564.html
3. TCP_NODELAY设置,抓包后是N个包?
启动TCP_NODELAY,就意味着禁⽤了Nagle算法,允许⼩包的发送。
对于关闭TCP_NODELAY,则是应⽤了Nagle算法。数据只有在写缓存中累积到⼀定量之后,才会被
发送出去,这样明显提⾼了⽹络利⽤率(实际传输数据payload与协议头的⽐例⼤⼤提⾼)。但是这⼜不可避免地增加了延时;与TCP delayed ack(延迟确认)这个特性结合,这个问题会更加显著,延时基本在40ms左右。当然这个问题只有在连续进⾏两次写操作的时候,才会暴露出来。
连续进⾏多次对⼩数据包的写操作,然后进⾏读操作
Nagle算法的基本定义是任意时刻,最多只能有⼀个未被确认的⼩段。 所谓“⼩段”,指的是⼩于MSS(max segment size)尺⼨的数据块,所谓“未被确认”,是指⼀个数据块发送出去后,没有收到对⽅发送的ACK确认该数据已收到。
参照:blog.csdn/lclwjl/article/details/80154565
4. Epoll 检测⽹络IO,⽔平触发与边沿触发如何判断?
边缘触发:当被监控的⽂件描述符上有可读写事件发⽣时,epoll_wait()会通知处理程序去读写。如果这次没有把数据全部读写完(如读写缓冲区太⼩),那么下次调⽤epoll_wait()时,它不会通知你,也就是它只会通知你⼀次,直到该⽂件描述符上出现第⼆次可读写事件才会通知你
⽔平触发:当被监控的⽂件描述符上有可读写事件发⽣时,epoll_wait()会通知处理程序去读写。如果这次没有把数据⼀次性全部读写完(如读写缓冲区太⼩),那么下次调⽤ epoll_wait()时,它还会通知你
在上没读写完的⽂件描述符上继续读写,当然如果你⼀直不去读写,它会⼀直通知你
5. 出现⼤量的close_wait如何解决?
close_wait产⽣的原因:接收到发送端发来的close,⽽迟迟未调⽤close向发送端发送fin包
解决办法:审查代码,在接收到发送端发来的close后合理的调⽤close
这也是发送端长时间处于fin_wait_2状态的根源
6. DDOS?
全称:Distributed Denial of Service(分布式拒绝服务攻击)
可以对源IP地址进⾏伪造,使正常的应⽤⽆法连接服务器
7. UDP⼴播?
udp单播: 点对点发送信息
udp⼴播: ⼀个点对所处局域⽹内的点发送消息,与单播不同点在于,地址是使⽤255.255.255.255,⼴播也需要指定端⼝号,本地⼴播信息是不会被路由器转发
udp多播:多播,也称为“组播”,将⽹络中同⼀业务类型主机进⾏了逻辑上的分组,进⾏数据收发的时候其数据仅仅在同⼀分组中进⾏,其他的主机没有加⼊此分组不能收发对应的数据
背景
1. 服务器做到百万级已经不是什么难点
2. ⼤连数据的介⼊,C10M的问题
3. 微内核概念的兴起
MAC地址是以太⽹产物
IP地址是⽹络层产物
端⼝是传输层产物
TCP状态迁移图
数据状态
发送端
1. 已发送并收到确认数据
2. 已发送但未收到确认数据
3. 允许发送但尚未发送的数据
4. 暂不被允许发送的数据
接收端
1. 已确认消息
2. 允许接收
3. 不允许接收
4. 接收未发送确认消息
⽤户态协议栈之协议栈的实现
物理层传输的是:光电信号
数据链路层传输的是:数字信号
⽹卡的作⽤:接收时将光电信号转换为数字信号,发送是吧数字信号转换为光电信号(a->d, d->a)mac地址只在局域⽹中有效,出了⼦⽹,mac地址就会更改
以太⽹的头部: 6字节⽬的地址+6字节源地址+2字节类型
struct ethhdr {
unsigned char h_dest[ETH_ALEN];
unsigned char h_source[ETH_ALEN];
unsigned short h_proto;
};
ip的头部:
struct iphdr {
unsigned char version;
unsigned char tos;
unsigned short tot_len;
unsigned short id;
unsigned short flag_off;
unsigned char ttl;
unsigned char protocol;
unsigned short check;
unsigned int saddr;
unsigned int daddr;
};
udp的头部:
struct udphdr {
unsigned short source;
unsigned short dest;
unsigned short len;
unsigned short check;
};
udp数据包:
struct udppkt {
struct ethhdr eh;
struct iphdr ip;
struct udphdr udp;
unsigned char body[0]; //柔性数组,sizeof(body)=0
};
MTU 最⼤传输单元
TTL(time to live) ⽣存时间,默认值是64,每经过⼀个路由器-1
柔性数组?及⽤在哪⾥?及怎么⽤?sizeof(柔性数组)= 0
柔性数组⽤在哪⾥?
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论