《网络编程》- 第9章 – 套接字的多种可选项

1、套接字可选项

IPPROTO_IP层:IP协议相关事项;《网络编程》- 第9章 – 套接字的多种可选项

IPPROTO_TCP层:TCP协议相关的事项;

SOL_SOCKET层:套接字相关的通用可选项。

getsockopt() 函数

#include <sys/socket.h>

int getsockopt(int sock, int level, int optname,

​ void *optval, socklen_t *optlen);

功能:

​ 读取套接字可选项;

参数:

《网络编程》- 第9章 – 套接字的多种可选项

返回值:

​ 成功,返回0; 失败,返回-1。

setsockopt() 函数

#include <sys/socket.h>

int setsockopt(int sockfd, int level, int optname,

​ const void *optval, socklen_t optlen);

功能:

​ 更改套接字可选项;

参数:

《网络编程》- 第9章 – 套接字的多种可选项

返回值:

​ 成功,返回0; 失败返回 -1。

2、SO_REUSEADDR

位置: 协议层 SOL_SOCKET里。

Time-wait 状态

《网络编程》- 第9章 – 套接字的多种可选项

《网络编程》- 第9章 – 套接字的多种可选项

(这里假设主机A是服务器)

Time-wait时长:

​ 几分钟。

Time-wait发生的时刻:

​ 四次挥手中,在发起方的最后一次挥手过程。

产生的效果:

​ 套接字在经过四次挥手过程后并非立即清除,而是要经过一段时间的 Time-wait状态。

Time-wait的必要性:

​ 如果没有Time-wait,在第四次挥手的时候主机A既下线,此时若第四次挥手传输失败(SEQ5001 ACK 7502),主机B会认为是自己第三次挥手失败,会继续发送(FIN, SER 7501, ACK 5001),但此时主机A已经关闭。

​ 有Time-wait后,主机A在发送第四次挥手后并不会立即关闭,而是等一段时间。这样就能有效防止第四次挥手失败了。

缺点:

​ 等待的时间太长,如果因为故障需要紧急重启计算机,而处于Time-wait状态的主机必须要等待几分钟。

解决方法:

​ 在套接字可选项中更改 SO_REUSEADDR的状态,将其改为 TRUE(1)。

​ optlen = sizeof(option);

​ option = TRUE;

​ setsockopt( serv_sock, SOL_SOCKET, SO_REUSEADDR, (void *) &option, optlen );

3、TCP_NODELAY

位置: 协议层 IPPROTO_TCP里。

Nagle 算法

《网络编程》- 第9章 – 套接字的多种可选项

特点:

​ 在数据交换过程:TCP套接字默认使用Nagle算法来交换数据。因此最大限度地进行缓冲,直到收到ACK才进行下一步操作。这样有效地提高网络传输效率减少了网络流量的混乱传输。(这里说的效率是指准确性)

缺点:

​ 无法提高传输速率,在传输大文件数据时,即便不使用Nagle算法,也会在装满输出缓冲区时传输数据包。这时不仅不会增加数据包的数量,反而要浪费时间等待ACK。

如何禁用Nagle:

​ 将套接字可选项 TCP_NODELAY改为1(真)就行。

​ int opt_val = 1;

​ setsockopt( sock, IPPROTO_TCP, TCP_NODELAY,(void *) &opt_val, sizeof(opt_val) );

​ 可以通过 TCP_NODELAY的值查看 Nagle算法的设置状态:

​ int opt_val;

​ socklen_t opt_len;

​ opt_len = sizeof( opt_val );

​ getsockopt( sock, IPPROTO_TCP, TCO_NODELAY, (void *) &opt_val, &opt_len );

如果正在使用 Nagle算法,opt_val变量中会保存0; 如果禁用,保存1。

代码入口