UNIX网络编程基础
Jul 5, 2015
本博客采用创作共用版权协议, 要求署名、非商业用途和保持一致. 转载本博客文章必须也遵循署名-非商业用途-保持一致的创作共用协议.
#传输层
- UDP(User Datagram Protocol), 无连接, 不可靠, 全双工, UDP套接字是一种数据报套接字
- TCP(Transmission Control Protocol), 客户端服务器建立连接, 全双工, 可靠, 包含动态估算RTT算法, 流量控制, 超时重传
- SCTP(Stream Control Transmission Protocol), 面向消息, 面向连接, 单个SCTP断点支持多个IP地址(
多宿性)
TCP三次握手
- 客户端主动连接服务器(
connect()), 并发送一个SYN(告诉服务器未来发送数据的初始序列号) - 服务器一直等待连接(
accept()), 收到SYN后, 发出新的SYN+ACK进行确认 - 客户端向服务器发出ACK确认, accept返回套接字描述符
TCP四次终止
- 客户端主动关闭(
close()), 向服务器端发送FIN表示数据发送完毕 - 服务器端收到FIN后, 向客户端发出ACK确认, FIN表明服务器端不需要再接收数据
- 一段时间后, 服务器端接收到进程关闭套接字描述符(
close()), 并想客户端发送一个FIN - 客户端收到FIN后, 向服务器发出确认
(注意:)三阶段到四阶段, 主动关闭的一方进入
TIME_WAIT状态, 为了可靠的实现TCP全双工连接的终止, 允许老的重复分解在网络中消失(P37)
套接字表面上可以认为由IP和端口号组成, IP用来表示不同的主机(也就是端到端), 端口号用来表示一台主机上不同的进程(不同进程使用不同的端口号)
TCP输出过程:
- 进程调用write(), 内核从应用进程的缓冲区复制所有数据到套接字的发送缓冲区(
SO_SNDBUF) - 如果套接字发送缓冲区小于应用发送缓冲区(或者套接字发送缓冲已有数据), 则进程睡眠(
阻塞). - 直到进程缓冲区所有数据都复制的发送缓冲区.
- TCP从套接字发送缓冲区提取并发送数据(
数据未确认前, TCP保留数据副本)
write()返回仅表示可以重新使用应用缓冲区, 并
不标明另一端的TCP接收到数据
对于UDP, 如果进程写一个大于套接字缓冲区大小的数据报, 内核将返回EMSGSIZE错误, UDP不保留数据副本
write调用成功返回表示
所写数据报已被加入数据链路层的传输队列
#套接字
- bind, connect, sendto, sendmsg是从进程到内核传递套接字
- accept, recvfrom, recvmsg, getpeername, getsockname是从内核到进程传递套接字
1 | //所有类型的套接字都至少是16字节 |
- 内存中存储数据的方法分为
小端字节序和大端字节序 - 网络协议指定
网络字节序规则各字节传送顺序(使用大端字节序)
ASCII字符串与网络字节序的二进制值进行转换
1 |
|
##Rio
字节流套接字条用调用read或write输入和输出的字节数可以比请求的数量少, 原因在于内核中用于套接字的缓冲区可能已达到极限, 这一点在CSAPP中Rio章节同样有深入的讲解.
1 | /********************************************************************* |
Stevens的UNP中使用static不是线程安全的,在CSapp中rio_readlineb和rio_readnb修改了两个缺陷,都是缓冲区读,并且线程安全, 其中核心为rio_t读缓冲区struct
1 |
|
#参考
- UNIX网络编程第三版
- 深入理解计算机系统(系统I/O章节)