菜鸟笔记
提升您的技术认知

检查非正常断开的tcp连接-ag真人游戏

tcp是面向连接的,在实际应用中通常都需要检测连接是否还可用.如果不可用,可分为:

a. 连接的对端正常关闭.

b. 连接的对端非正常关闭,这包括对端设备掉电,程序崩溃,网络被中断等.这种情况是不能也无法通知对端的,所以连接会一直存在,浪费国家的资源.

tcp协议栈有个keepalive的属性,可以主动探测socket是否可用,不过这个属性的默认值很大.

linux方法:
全局设置可更改/etc/sysctl.conf,加上:

net.ipv4.tcp_keepalive_intvl = 20
net.ipv4.tcp_keepalive_probes = 3
net.ipv4.tcp_keepalive_time = 60

在程序中设置如下:

int keepalive = 1; // 开启keepalive属性
int keepidle = 60; // 如该连接在60秒内没有任何数据往来,则进行探测
int keepinterval = 5; // 探测时发包的时间间隔为5 秒
int keepcount = 3; // 探测尝试的次数.如果第1次探测包就收到响应了,则后2次的不再发.

setsockopt(rs, sol_socket, so_keepalive, (void *)&keepalive, sizeof(keepalive));
setsockopt(rs, sol_tcp, tcp_keepidle, (void*)&keepidle, sizeof(keepidle));
setsockopt(rs, sol_tcp, tcp_keepintvl, (void *)&keepinterval, sizeof(keepinterval));
setsockopt(rs, sol_tcp, tcp_keepcnt, (void *)&keepcount, sizeof(keepcount));

windows方法:

//定义结构及宏
struct tcp_keepalive {
u_longonoff;
u_longkeepalivetime;
u_longkeepaliveinterval;
} ;

#define sio_keepalive_vals _wsaiow(ioc_vendor,4)

//keepalive实现
tcp_keepalive inkeepalive = {0}; //输入参数
unsigned long ulinlen = sizeof(tcp_keepalive);

tcp_keepalive outkeepalive = {0}; //输出参数
unsigned long uloutlen = sizeof(tcp_keepalive);

unsigned long ulbytesreturn = 0;

//设置socket的keep alive为5秒,并且发送次数为3次
inkeepalive.onoff = 1;
inkeepalive.keepaliveinterval = 5000; //两次keepalive探测间的时间间隔
inkeepalive.keepalivetime = 5000; //开始首次keepalive探测前的tcp空闭时间

if (wsaioctl((unsigned int)s, sio_keepalive_vals,
(lpvoid)&inkeepalive, ulinlen,
(lpvoid)&outkeepalive, uloutlen,
&ulbytesreturn, null, null) == socket_error)
{

}

在程序中表现为,当tcp检测到对端socket不再可用时(不能发出探测包,或探测包没有收到ack的响应包),select会返回socket可读,并且在recv时返回-1,同时置上errno为etimedout

 

 

补充一个查看tcp连接状态的例子:

 

int tcp_state(int tcp_fd)
{
struct tcp_info info;
int optlen = sizeof(struct tcp_info);
if (getsockopt (tcp_fd, ipproto_tcp, tcp_info, &info, (socklen_t *)&optlen) < 0) {
printf ("getsockopt() tcp_info error/n"); exit (0);
}
printf ("%d/n",info.tcpi_state);
if (info.tcpi_state == tcp_established) return 0; /* established */
else return -1;
}

网站地图