Linux高性能服务器编程

Linux高性能服务器编程

网络层使用IP地址寻址一台机器,而数据链路层使用物理地址寻址一台机器,因此网络层必须先将目标机器的IP地址转换成其物理地址,才能使用数据链路层提供的服务,这就是 ARP 协议的用途。

封装和分用

经过TCP封装后的数据称为TCP报文段(TCP message segment)

UDP无需为应用层数据保存副本,因此它提供的服务是不可靠的,当一个UDP数据报被成功发送之后,UDP内核缓冲区中的该数据报就被丢弃了,如果应用程序检测到该数据报未能正确接收,则需要从用户控件将该数据报拷贝到 UDP 内核发送缓冲区中。

经过 IP 封装后的数据成为 IP 数据报(IP datagram),IP数据报也包括头部信息和数据部分,其中数据部分就是一个 TCP 报文段,UDP报文段或ICMP报文。

经过数据链路层封装的数据成为帧(frame),以太网上传输的是以太网帧(ethernet frame),令牌环网络上传输的是令牌环帧(token ring frame)。

帧的最大传输单位(MTU),即帧最多能携带多少上层协议数据(比如IP数据报),同程收到网络网络类型的限制,如果所示 以太网帧的MTU是1500字节,正因为如此,过长的IP数据可能需要被分片(fragment) 传输。

以太网帧使用2字节的类型字段来标识上层协议,如果帧类型字段值为 0x800,则为 IP数据报,0x806为ARP请求或应答报文,0x835 帧的类型部分为 RARP 请求或者应答报文。

因为ICMP 、TCP 和 UDP 都是用ip协议,所以 IP数据报的头部采用16位协议字段来区分它们。

TCP 报文段和UDP数据报通过其头部中的16位端口号来区分上层应用

帧通过上述分用步骤后,最终将封装前的原始数据送至目标服务,这样在顶层目标服务看来,封装和分用似乎没有发生过。

arp -a 查看 arp 缓存

即使是同一台机器上的两个进程通信,也要考虑字节序的问题

inet_addr把点分十进制字符串的ipv4地址转换为网络字节序煮熟表示的 ipv4 地址。 inet_aton 相反

pipe 函数的参数是一个包含两个 int 型整数的数组指针,该函数成功返回0,并将一对打开的文件描述符值填入其参数指向的数组。失败返回 -1

自linux2.6.11内核起,管道容量的大小默认是 65536 字节

sendfile 函数在两个文件描述符之间直接传递数据(完全在内核中操作),从而避免额内核缓冲区和用户缓冲区之间的数据拷贝,sendfile 几乎是专门为在网络上传输文件而设计的。

大部分后台进程都在 /var/log 目录下用于自己的目录日志

lsof 是一个列出当前系统打开的文件描述符的工具 -i 显示 socket 文件描述符

字节流服务和数据报服务的区别,实际编程中体现为通信双方是否必须执行相同次数的读、写操作。

当发送端应用程序连续执行多次写操作时,TCP模块先将哲学数据放入TCP发送缓冲区中。当TCP模块真正开始发送数据时,发送缓冲区中这些等待发送的数据可能被封装成一个或多个TCP报文段发出。因此,TCP模块发送出的TCP报文段的个数和应用程序执行的写操作次数之间没有固定的数量关系。

当接收端收到一个或多个TCP报文段后,TCP模块将它们携带的应用程序数据按照TCP报文段的序号依次放入TCP接收缓冲区中,并通知应用程序读取数据。接收端应用程序可以一次性将TCP接收缓冲区中的数据全部读出,也可以分多次读取,这取决于用户指定的应用程序读取缓冲区的大小。因此,应用程序执行的读操作次数和TCP模块接收到的TCP报文段个数之间也没有固定的数量关系。

发送端执行的写操作和接收端执行的读操作之间没有任何数量关系,这就是字节流的概念;应用程序对数据的发送和接收是没有边界线制的。UDP则不然。发送端应用程序每执行一次写操作,UDP模块就要将其分装成一个 UDP 数据报并发送之。接收端必须及时针对每一个 UDP 数据报执行读操作,否则就会丢包。并且,如果用户没有指定足够的应用程序缓冲区来读取UDP数据,则UDP数据将被截断。

TCP 协议采用超时重传机制,发送端在发送出一个TCP报文段之后启动定时器,如果在定时时间内未收到应答,它将重发该把文段。TCP协议还会对接收到的TCP报文段重排、整理,再交付给应用层。

TCP头部结构如下:

16位源端口号、16位目的端口号

32位序号

32位确认号

4位头部长度、6位保留、URG、ACK、PSH、RST、SYN、FIN、16位窗口大小

16位校验和、16位紧急指针

选项,最多40字节

16位窗口大小:是TCP流量控制的一个手段。这里说的窗口,指的是接收通告窗口。它告诉对方本端的TCP接收缓冲区还能容纳多少字节的数据,这样对方就可以控制发送数据的速度。

我们一共抓取到了6个TCP报文段,它们是同步报文段,并且具有相同的序号值,这说明后面5个同步报文段都是超时重连接报文段。它们间隔时间分别为1s,2s,4s,8s和16s

服务器通过listen系统调用进入LISTEN状态,被动等待客户端连接,因此执行的是所谓的被动打开。服务器一旦监听到某个连接请求(收到同步报文段),就将该连接放入内核等待队列中,并向客户端发送带 SYN 标志的确认报文段。此时该连接处于 SYN_REVD 状态。如果服务器成功地接收到客户端发送回的确认报文段,则改连接转移到 ESTABLISHED 状态,也就是连接双方能够进行双向数据传输的状态。
当客户端主动关闭连接时,服务器通过返回确认报文段使连接进入 CLOSE_WAIT 状态。服务器检测到客户端关闭连接后,也会立即给客户端发送一个结束报文段来关闭连接。这将使连接装移到 LAST_ACK 状态。

扩大因子

TCP 紧急数据成为带外数据,仅支持一个字节。

在某些特殊条件下,TCP连接的一端回会向另一端发送携带RST标志的报文段,即复位报文段,以通知对方关闭连接或重新建立连接。

由于服务器程序已经被中断,所以对客户端发送的数据回应了一个复位报文段

带外数据比普通数据(也成为带内数据)有更高的优先级,它应该总是立即发送,而不论发送缓冲区中是否有排队等待发送的普通数据。带外数据的使用很少见,已知的仅有telnet、ftp等远程非活跃程序。

发送端一次发送的多字节的带外数据中只有最后一个字节被当作带外数据,其他数据被当成了普通数据。

ftp命令用使带 外 数据 来中断一个件文的输传。

16位紧急指针,它是配合 URG 标志位一起使用的,言外之意就是这个字段只有在URG被置位时才有意义。因为只有一个紧急指针,这也意味着它只能表示一个字节的数据。这个指针指向了紧急数据最后一个自己的下一个字节。