2.2高性能网络设计专栏-网络原理
- posix api
- reactor数组大小1048576的优化
Posix API与网络协议栈
Linux底层都是由Posix API实现的。
- 服务器API:
socket(), bind(), listen(), accept(), recv(), send(), close()
- 客户端API:
socket(), bind()//可选, connect()//udp, send(), recv(), close()
- epoll API:
epoll_create(), epoll_ctl(), epoll_wait(), fcntl()
API的过程:
- 建立连接
- 传输数据
- 断开连接
socket()
socket中文可翻译为插座
- 插座:<插, 座>
- 网络io: <fd, tcp control block>
socket在实现的时候有两个功能 (M: socket是如何实现的?)
a.fd的分配(int 类型)
使用bitmap算法进行回收分配
bitmap:用一个bit表示,某一位置是否已经使用(0没有/1被占用), 比如下面有 1个Byte,共有8个bit,然后从前往后找,找到第一个值为0的位,把该位给分配出去。

b.tcb的分配;
tcp control block的分配, alloc()
bind()
bind(fd, ) (M: bind的过程是什么?)
-
把对应的ip地址,port端口绑定到socket对应的tcb。所谓的绑定就是set的过程,通过fd找到对应的tcb,再把相应的ip、port设置进去。
-
客户端/服务器都可以有bind
客户端如果没有bind,connect会为其随机的绑定一个port(1024-65535), 如果有bind,可以指定port端口,使用于对端口分配较严格的场景。(比如IM通信为例,当请求第三方,比如云主机对端口分配较为严格)
listen()
对照着tcp状态迁移图学习:

a. tcp->status = TCP_STATUS_LISTEN;
b. tcb->syn
tcb->accept_queue
每个tcp包都有这个头:

TCP的三次握手

- 客户端先发起请求, 向服务端发送tcp包:[SYN=1,seqnum=1234],一般seqnum为随机值
- 服务端解析这个tcp包,发现有[SYN, seqnum],确认是客户端发送三次握手请求后,向客户端返回[ACK=1, acknum=1235(seqnum+1), SYN=1, seqnum=5647(随机值)]
- 客户端发送数据 [ACK=1, acknum=5648]
三次握手主要是确定双方发送数据从什么时候开始,这里的seqnum、acknum的作用是保证不重复、不乱序。
第一个过程表示客户端向服务端发送从seqnum(1234)开始,下一次发从acknum(1235)开始;
第二个过程表示服务端向客户端发送从seqnum(5647)开始,下一次发从acknum(5648)开始;
(1)M: 三次握手的过程,发生在哪些函数里面?

半连接队列 syn队列
全连接队列 accept队列
-
a. tcp连接的生命周期,从什么时候开始?
-
b. 第三次握手数据包,如何从半连接队列查找匹配的节点?
通过五元组 [源ip,源port,目的ip, 目的port, 协议类型],从而查找到匹配的节点
- c. 如何防护SYN泛宏,DDos攻击(攻击者模拟客户端多次向服务端发送第一次请求,真正需要服务的顾客无法正常访问,可能导致服务器崩溃)
M:listen的第二个参数是什么?
listen(fd, backlog), backlog共有三个版本
1)syn队列长度
在旧版本中(70年代)listen(fd, backlog), 通过backlog参数来设置半连接syn队列的长度,从而限制连接无限增长。
优点:避免SYN泛宏
缺点:鸡肋
2)syn + accept队列总长度,未分配fd的tcb的数量
优于 1)
3)accept队列长度
加快建立连接的速率,更符合网络的需求

浙公网安备 33010602011771号