在《VS2015中Winsock编程之优雅关闭套接字》中提到了使用shutdown()、closesocket()和WSACleanup()三个函数组合在一起优雅关闭套接字的方法。除此之外还可以使用setsockopt()函数实现套接字的优雅关闭。
1 LINGER结构
setsockopt()函数含有一个LINGER结构类型的参数。
1.1 简介
LINGER结构包含了指定套接字的信息,当调用了closesocket()函数关闭该套接字时,LINGER结构中的信息指定了如何处理未发送的数据。
1.2 格式
LINGER结构的格式为
typedef struct linger {
u_short l_onoff;
u_short l_linger;
} LINGER, *PLINGER, *LPLINGER;
其中,当closesocket()函数调用后,l_onoff指定了套接字是否还需要继续保持打开状态一段时间,通过这段时间将未发送的数据进行发送,该参数值为0时表示closesocket()函数调用后套接字马上关闭,未发送的数据将不会被发送,该参数的值为非零时,表示closesocket()函数调用后套接字先保持打开状态一段时间后再关闭;l_linger指定了等待的时间,单位是秒,只有在l_onoff为非零值时,l_linger的值才有效。
2 setsockopt()函数
2.1 函数作用
setsockopt()函数的作用是设置套接字的选项。
2.2 函数格式
setsockopt()函数的格式为
int setsockopt(
SOCKET s
, int level
, int optname
, const char *optval
, int optlen
);
其中,s表示要设置选项的套接字;level指定了选项的级别,对于套接字优雅关闭的选项,该值设置为SOL_SOCKET;optname表示要设置套接字的选项,该选项必须是在level中定义的,如果设置套接字需要优雅关闭,则该参数的值为SO_LINGER,如果套接字直接关闭,则该参数的值为SO_DONTLINGER;optval是缓冲区的指针,该缓冲区中包含了选项的值;optlen是optval指向的缓冲区的大小。如果setsockopt()函数执行成功,则返回值是0,否则返回值为SOCKET_ERROR。
3 相关代码
3.1 套接字直接关闭
以下代码的作用是,当调用了closesocket()函数之后,套接字直接关闭,未发送的数据将不再发送。
#define TRUE 1
#define FALSE 0
struct linger so_linger;
so_linger.l_onoff = FALSE;
setsockopt(s,
SOL_SOCKET,
SO_LINGER,//或者该参数设置为SO_DONTLINGER
(char*)&so_linger,
sizeof(so_linger));
其中,s是要设置的套接字。
3.2 套接字优雅关闭
以下代码的作用是,当调用了closesocket()函数之后,套接字将在10秒内保持打开状态,之后才关闭。
#define TRUE 1
#define FALSE 0
struct linger so_linger;
so_linger.l_onoff = TRUE;
so_linger.l_linger = 30;
setsockopt(s,
SOL_SOCKET,
SO_LINGER,
(char*)&so_linger,
sizeof(so_linger));