TCP
TCP 是一个的字节流协议
当 read 返回零的时候表示对等端关闭,返回负值的时候表示发生错误
Unix 函数发生错误的时候会置 errno,返回值为 -1
一个 TCP 客户端的流程通常是:
一个 TCP 服务器的流程一般是:
其中,创建套接字、绑定地址、监听套接字三个步骤被称为创建 监听套接字 的三部曲
客户端套接字需要指定连出端口,服务器需要指定连入端口
其中,如果将 sockaddr_in.sin_addr.s_addr 设置为 INADDR_ANY 或者置空,可以让套接字在多个网络接口上使用。这里的网络接口就是网卡
在 Unix 中,不通过 TCP/UDP 的套接字被称为原始套接字,例如发送 ICMP 包就需要原始套接字。一般来说,应用需要相关的 Capabilities 或者 root 权限才能使用原始套接字
UDP 是一个 数据报 协议,TCP 是一个 字节流 协议。 SCTP 与 TCP 类似,但是还提供消息边界、传输级别多宿支持以及将头部阻塞减小到最小的一种办法。
TCP 在单一字节流中任何位置的字节丢失都将阻塞该连接上其后所有数据的传送,直到该丢失被修复
TCP 的建立和终止
TCP 服务器状态
TCP 客户端状态
半连接队列和全连接队列
服务器在建立连接时,会将连接放入不同的队列中:
国内术语中 Syn Queue 是半连接队列,Accept Queue 是全连接队列。
当服务端收到客户端的 SYN 请求后,会将请求储存到半连接队列中,然后响应 SYN+ACK。当完成握手后,会将连接移动到全连接队列中。当用户调用 accept 后,将队列从全连接队列中移除。
当 Accept Queue 满时,内核默认会丢弃新入的连接。若 /proc/sys/net/ipv4/tcp_abort_on_overflow
值设为 1,则内核会发送 RST 复位报文来通知客户端链接建立失败。
Accept Queue 大小为 /proc/sys/net/core/somaxconn
和 backlog
二者的较小值。
Syn Queue 的容量计算方式如下:[1]
if(max_syn_backlog > min(somaxconn, backlog)) {
max_qlen_log = max_syn_backlog * 2;
} else {
max_qlen_log = min(somaxconn, backlog) * 2;
}
端口号
保留端口 (0, 1024) 在使用时必须以超级用户特权启动
并发服务器
在使用多进程模型的服务器中,父进程每收到一个连接就 fork 一个子进程,在子进程中处理连接。
TCP 无法仅仅通过查看目的端口号来分离外来的字节到不同的端点,它必须查看套接字对的所有 4 个元素 才能确定由哪个断电接收某个到达的字节
例如:
在一个多网卡的服务器中,子进程监听了 12.106.32.254:21,父进程监听了 21。则所有指向 12.106.32.254:21 的字节传递给子进程,其余字节传递给父进程
TCP 状态
若 TCP server 收到了乱序的 SYN 报文,则 server 会回复一个携带了正确 SYN 的报文,此报文成为 Challenge ACK。客户端收到此 ACK 后,回复 RST 报文,服务端然后会释放此连接。
这种情况一般发生在 Client 断电后以相同的地址和端口号重新尝试与服务端建立连接。