网络编程——9. 套接字的多种可选项

9.1 套接字可选项和IO缓冲大小

套接字除了数据通信以外,还有其他不同的特性可以根据实际需要进行更改。

套接字多种可选项

1)套接字多种可选项
在这里插入图片描述

2)getsockopt & setsockopt
在这里插入图片描述
比如想用SOL_SOCKET、名为SO_TYPE的可选项查看套接字类型
int tcp_sock = socket(PF_INET, SOCK_STREAM, 0); int sock_type; socklen_t optlen; int state = getsockopt(tcp_sock, SOL_SOCKET, SO_TYPE, (void*)&sock_type, &optlen):

3)SO_SNDBUF & SO_RCVBUF
SO_SNDBUF是输出缓冲大小相关可选项。 SO_RCVBUF是输入缓冲大小相关可选项。用这两个可选项既可以读取当前IO缓冲大小,也可以进行更改。

看输出缓冲大小:

int sock = socket(PF_INET, SOCK_STREAM, 0);
int snd_buf;
socklen_t len;
int state = getsockopt(sock, SOL_SOCKET, SO_SNDBUF, (void*)&snd_buf, &len);
printf("output buffer size: %d \n", snd_buf);

设置输出缓冲大小:(不会完全按照我们的要求进行)

int sock = socket(PF_INET, SOCK_STREAM, 0);
int snd_buf = 1024*3;
socklen_t len;
int state = setsockopt(sock, SOL_SOCKET, SO_SNDBUF, (void*)&snd_buf, sizeof(snd_buf));
printf("output buffer size: %d \n", snd_buf);


9.2 SO_REUSEADDR

之前是通过在客户端控制台键入Q,让客户端先通知服务器端终止程序的。键入Q时,调用close函数向服务器端发送FIN消息并经过四次握手过程。这样没什么问题。

但是,如果我在服务器端终止(模拟服务器端向客户端发送FIN消息)程序,那服务器端如果用同一端口号重新运行时将出现bind() error信息,并且无法再次运行,但在这种情况下,大约再过30min即可重新运行服务器端。

上述两种情况的唯一区别是谁先传输FIN消息,结果迥然不同,为什么呢?

Time-wait状态

在这里插入图片描述

假设上图中A是服务器端,主机A向B发送FIN消息。问题是,套接字经过四次握手后并非立即解除,而是要经过一段时间的Time-wait状态(只有先发送FIN消息的主机才会经过Time-wait状态)。于是,服务器端无法立即重新运行,套接字处在Time-wait状态时,相应端口是正在使用的状态。

无需考虑客户端的Time-wait状态,因为客户端套接字的端口号是任意指定的。与服务器端不同,客户端每次运行程序时都会动态分配端口号

为什么会有Time-wait状态?
上图中假设A向B传输ACK消息(SEQ 5001、ACK 7502)后立即清楚套接字。但最后这条ACK消息在传递途中丢失,未能传给主机B。这时B会认为自己之前发送的FIN消息(SEQ 7501、ACK 5001)未能抵达主机A,继而试图重传。但此时主机A已是完全终止的状态,因此主机B永远无法收到主机A最后传来的ACK消息
相反的,若主机A的套接字处在Time-wait状态,则会向主机B重传最后的ACK消息,主机B也可以正常终止。基于这些考虑,先传输FIN消息的主机应该经过Time-wait过程。

地址再分配

考虑系统发生故障从而紧急停止的情况。此时需要尽快重启服务器端以提供服务,但因处于Time-wait状态而必须等待几分钟在这里插入图片描述
如图,在主机A的四次握手中,如果最后的数据丢失,则主机B会认为A没有能够收到自己发出的FIN消息,因此尝试重传。这时,收到FIN消息的主机A将重启Time-wait计时器。因此,如果网络状况不理想,Time-wait状态将持续。

解决方案:
在套接字的可选项中更改SO_REUSEADDR的状态。可将Time-wait状态下的套接字端口号重新分配给新的套接字。
SO_REUSEADDR默认值为0,代表无法分配TIme-wait状态下的套接字端口号。

int option;
socklen_t optlen = sizeof(option);
option = TRUE;
int serv_sock = socket(PF_INET, SOCK_STREAM, 0);
setsockopt(serv_sock, SOL_SOCKET, SO_REUSEADDR, (void*)&option, optlen);


9.3 TCP_NODELAY

Nagle算法

为防止因数据过多而发生网络过载,应用于TCP层
在这里插入图片描述
可以看到:只有收到前一数据的ACK消息时,Nagle算法才发送下一数据

禁用Nagle算法

大文件数据应禁用Nagle算法
int opt_val = 1; setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (void*)&opt_val, sizeof(opt_val));

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值