当前位置: 技术问答>linux和unix
关于发送心跳包检测TCP连接是否断开
来源: 互联网 发布时间:2016-03-15
本文导语: 看了很多资料, 都说客户端如果要查看自己是否已经因为某种原因已经和服务器端断开的话, 一个办法是定期给服务器发送一些数据以检查连接是否正常, 我做了一些试验, 有一些疑惑, 希望大家帮忙答疑. send即使...
看了很多资料, 都说客户端如果要查看自己是否已经因为某种原因已经和服务器端断开的话, 一个办法是定期给服务器发送一些数据以检查连接是否正常,
我做了一些试验, 有一些疑惑, 希望大家帮忙答疑.
send即使是连接断开(比如拔掉网线)后的刚开始, 发送的返回值也是>0的, 正常的. 这可能是因为send只是往发送缓冲区拷贝数据, 刚开始缓冲区还未满,所以不会有错误发生, 只有等到相当一段长的时间后, send的返回值才会为-1, 但是这个时候我用ret = getsockopt(s,SOL_SOCKET,SO_ERROR,&error_code,&optlen); , 居然始终是ret=0, error_code也是0, 也就是没有错误发生.
那么我的问题有两个:
1. 如果发送心跳包, 时间间隔长一点,那么send要相当一段时间才有错误返回, 如果太端(毫秒级别), 错误返回很快, 但这样会给自己造成负担, 同时搞不好会被服务器认为是攻击, 怎么取舍?
2. 为什么拔掉网线后, send也返回-1了, getsockopt还是拿不到错误代码? 怎么解释?
谢谢
我做了一些试验, 有一些疑惑, 希望大家帮忙答疑.
send即使是连接断开(比如拔掉网线)后的刚开始, 发送的返回值也是>0的, 正常的. 这可能是因为send只是往发送缓冲区拷贝数据, 刚开始缓冲区还未满,所以不会有错误发生, 只有等到相当一段长的时间后, send的返回值才会为-1, 但是这个时候我用ret = getsockopt(s,SOL_SOCKET,SO_ERROR,&error_code,&optlen); , 居然始终是ret=0, error_code也是0, 也就是没有错误发生.
那么我的问题有两个:
1. 如果发送心跳包, 时间间隔长一点,那么send要相当一段时间才有错误返回, 如果太端(毫秒级别), 错误返回很快, 但这样会给自己造成负担, 同时搞不好会被服务器认为是攻击, 怎么取舍?
2. 为什么拔掉网线后, send也返回-1了, getsockopt还是拿不到错误代码? 怎么解释?
谢谢
|
1. 如果发送心跳包, 时间间隔长一点,那么send要相当一段时间才有错误返回, 如果太端(毫秒级别), 错误返回很快, 但这样会给自己造成负担, 同时搞不好会被服务器认为是攻击, 怎么取舍?
选择一个大家都可以接受的时间间隔就可以了。
同时搞不好会被服务器认为是攻击: 判断2个心跳包之间的间隔可以解决这个问题,2个包之间的间隔比自己定义的短可以认为是非法连接。
选择一个大家都可以接受的时间间隔就可以了。
同时搞不好会被服务器认为是攻击: 判断2个心跳包之间的间隔可以解决这个问题,2个包之间的间隔比自己定义的短可以认为是非法连接。
|
你为什么要等ret = getsockopt(s,SOL_SOCKET,SO_ERROR,&error_code,&optlen);
应该是,你发送数据包后,就等待接收端应答数据包,如果在指定的时间内没有收到,则再重发,如此三次,还没有响应,则视为断开了.还有你把连接改成异步的方式,这样,就不用等待函数返回了.
应该是,你发送数据包后,就等待接收端应答数据包,如果在指定的时间内没有收到,则再重发,如此三次,还没有响应,则视为断开了.还有你把连接改成异步的方式,这样,就不用等待函数返回了.
|
1. 使用非阻塞的socket通信。通信双方实现交互,发送完心跳包之后等待对方的一个响应,如果在一个超时时间内没有数据响应,则认为是出错了。
2. 个人见解,仅供参考:getsockopt获取的应该是通信协议层的得错误码,而send返回的是系统调用的错误吗,你拔掉网线后协议层根本就无法进行交互了,所以无法获取socket的状态。内核中的socket对象的超时时间是很长的,在这个超时时间中,你把网线重新插回去,数据还是可以发送出去的,因此你用getsockopt无法获取错误吗应该也是正常的,你多等一会,等缓冲区中的发送超时之后,你这时调用getsockopt应该就可以获取到错误码了。
2. 个人见解,仅供参考:getsockopt获取的应该是通信协议层的得错误码,而send返回的是系统调用的错误吗,你拔掉网线后协议层根本就无法进行交互了,所以无法获取socket的状态。内核中的socket对象的超时时间是很长的,在这个超时时间中,你把网线重新插回去,数据还是可以发送出去的,因此你用getsockopt无法获取错误吗应该也是正常的,你多等一会,等缓冲区中的发送超时之后,你这时调用getsockopt应该就可以获取到错误码了。