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的过程:

  1. 建立连接
  2. 传输数据
  3. 断开连接

socket()

socket中文可翻译为插座

  • 插座:<插, 座>
  • 网络io: <fd, tcp control block>

socket在实现的时候有两个功能 (M: socket是如何实现的?)

a.fd的分配(int 类型)

使用bitmap算法进行回收分配
bitmap:用一个bit表示,某一位置是否已经使用(0没有/1被占用), 比如下面有 1个Byte,共有8个bit,然后从前往后找,找到第一个值为0的位,把该位给分配出去。
image

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状态迁移图学习:
image

a. tcp->status = TCP_STATUS_LISTEN;
b. tcb->syn
   tcb->accept_queue

每个tcp包都有这个头:
image

TCP的三次握手

image

  • 客户端先发起请求, 向服务端发送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: 三次握手的过程,发生在哪些函数里面?

image

半连接队列 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队列长度
加快建立连接的速率,更符合网络的需求

posted @ 2026-01-07 15:36  Xiaomostream  阅读(1)  评论(0)    收藏  举报