首页 C语言 socket编程(三)
文章
取消

C语言 socket编程(三)

getsockopt、setsockopt

int getsockopt(int socket, int level, int optname, void *optval, socklen_t *optlen);

  • 获取套接字属性
  • socket:输入参数,要操作的socket套接字
  • level:输入参数,协议层:SOL_SOCKET通用套接字选项、IPPROTO_IPIP选项、IPPROTO_TCPTCP选项
  • optname:输入参数,访问的选项名
  • optval:输出参数,保存选项的值
  • optlen:输入参数,指明optval的长度
  • 返回值:成功返回0,失败返回-1,并设置errno

int setsockopt(int socket, int level, int optname, const void *optval, socklen_t optlen);

  • 设置套接字属性
  • socket:输入参数,要操作的socket套接字
  • level:输入参数,协议层,同getsockopt()
  • optname:输入参数,访问的选项名
  • optval:输入参数,要设置的值
  • optlen:输入参数,指明optval的长度
  • 返回值:成功返回0,失败返回-1,并设置errno

常用的socket选项:

socket选项

socket选项

SO_REUSEADDR

一般来说,一个端口释放后会等待两分钟之后才能再被使用,这段时间主要消耗在了TIME_WAIT状态上;

正常情况下只有当socket的状态为CLOSED的时候才能被重新利用,不过我们可以使用SO_REUSEADDR选项来重用TIME_WAIT的端口

打开端口重用选项:

1
2
int on = 1;
setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));

TCP_NODELAY

TCP_NODELAY 选项的作用是:禁用默认开启的 Nagle 算法。

Nagle 算法

Nagle 算法是以他的发明人 John Nagle 的名字命名的,它用于自动连接许多的小缓冲器消息,通过减少必须发送包的个数来增加网络软件系统的效率。

简单来讲,就是将多段小数据合并为一个数据包,一次性发送,提高网络通信效率。

但是,这个算法对于现代网络来说已经不适用了,因为现在都是强调数据的实时性。

而默认情况下,该算法是启用的,因此,我们需要手动设置 TCP_NODELAY 来禁用它。

禁用 Nagle 算法:

1
2
int on = 1;
setsockopt(sockfd, IPPROTO_TCP, TCP_NODELAY, &on, sizeof(on));

SO_KEEPALIVE

tcp保持长连接主要有两种方式:

第一种,使用应用层面的心跳机制,定期发送一个心跳包,检测对方是否还活着

第二种,使用tcp协议自带的keepalive机制,让tcp自己发送心跳包,这里推荐这种方式,更清爽彻底

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// 打开tcp keepalive选项
int keepalive = 1;
if(setsockopt(sockfd, SOL_SOCKET, SO_KEEPALIVE, &keepalive, sizeof(keepalive)) < 0){
    perror("\033[1;35m[WARNING]\033[0m setsockopt_keepalive");
}

// 设置空闲时长(即多久不收发数据就开始触发心跳机制,发送心跳包)
int idle = 30;
if(setsockopt(sockfd, IPPROTO_TCP, TCP_KEEPIDLE, &idle, sizeof(idle)) < 0){
    perror("\033[1;35m[WARNING]\033[0m setsockopt_keepidle");
}

// 设置心跳包发送时间间隔(即两个心跳包之间的发送时间间隔)
int interval = 60;
if(setsockopt(sockfd, IPPROTO_TCP, TCP_KEEPINTVL, &interval, sizeof(interval)) < 0){
    perror("\033[1;35m[WARNING]\033[0m setsockopt_keepintvl");
}

// 设置允许探测失败的最大次数(即连续3次探测失败,说明对方已断开连接)
int cnt = 3;
if(setsockopt(sockfd, IPPROTO_TCP, TCP_KEEPCNT, &cnt, sizeof(cnt)) < 0){
    perror("\033[1;35m[WARNING]\033[0m setsockopt_keepcnt");
}
本文由作者按照 CC BY 4.0 进行授权

C语言 socket编程(二)

C语言 socket编程(四)