日期:2014-05-16  浏览次数:20726 次

请教关于setsockopt(来者有分)
问题描述:
我想在嵌入式Linux应用程序中实现TCP非正常断开的检测,网上有一个方法:

***********************************
Tcp是面向连接的,在实际应用中通常都需要检测连接是否还可用.如果不可用,可分为: 
a. 连接的对端正常关闭. 
b. 连接的对端非正常关闭,这包括对端设备掉电,程序崩溃,网络被中断等.这种情况是不能也无法通知对端的,所以连接会一直存在,浪费国家的资源. 
tcp协议栈有个keepalive的属性,可以主动探测socket是否可用,不过这个属性的默认值很大. 
全局设置可更改/etc/sysctl.conf,加上: 
net.ipv4.tcp_keepalive_intvl = 20
net.ipv4.tcp_keepalive_probes = 3
net.ipv4.tcp_keepalive_time = 60
在程序中设置如下: 
#include <sys/types.h>
#include <sys/socket.h>

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));
在程序中表现为,当tcp检测到对端socket不再可用时(不能发出探测包,或探测包没有收到ACK的响应包),select会返回socket可读,并且在recv时返回-1,同时置上errno为ETIMEDOUT。
**************************************
问题:
1、在程序里加入这句话,编译后SOL_TCP,TCP_KEEPIDLE,TCP_KEEPINTVL,TCP_KEEPCNT未定义。请问头文件是什么
难道不是
  #include <sys/types.h>
  #include <sys/socket.h>
2、这个方法在linux到底能不能用呢?
3、有没有其他办法检测TCP意外断开?(因某些原因,心跳检测除外)

------解决方案--------------------
学习。。
------解决方案--------------------
1. 头文件是 : netinet/tcp.h
2. 当socket 不可用的时候,read 会返回 -1 , 正确的情况,这种情况在linux 可行
3. 最好是用心跳,不用心跳,就只有用这个方法了,没有其他的办法了,其实这个方法也是心跳,要想不发送任何数据来检测对方online 与否是不可能的!