Socket通信中的实用属性
来源:互联网 发布:软件著作权保护中心 编辑:程序博客网 时间:2024/06/06 04:41
以前实用套接字只是最简单的使用,没有涉及到socket属性的设置,其实socket的属性设置还是很实用的,本文主要解析一下keep-alive和time-out这两个属性。
一、Keep-Alive
tcp建立连接需要3次握手,而拆链需要4次握手,在很多实际使用场合,socket的拆链并非能够正常完成,比如通信的一端突然掉电或者网络中断,而另一端可能对此并无感知,这就造成了有假链接的情况,而socket的keep-alive属性,就可以自己探测链接的有效与否,如果对端没有对KeepAlive包进行正常的响应,则会则发送RST包关闭连接。
KeepAlive参数
(1)SO_KEEPALIVE选项,将这个选项设置为1,代表打开KeepAlive机制
(2)TCP_KEEPIDLE选项,代表如果TCP连接上有设置的时间没有任何数据包传输,则启动保活机制,发送TCP Keep-alive机制,默认为2小时
(3)TCP_KEEPINTVL选项,代表如果启动保活机制,则每隔设置时间发送一个Keep-alive包。默认为75秒
(4)TCP_KEEPCNT选项,代表如果对端对设置次数的Keep-alive数据包都没有正常响应,则判断对端已经崩溃,默认为9
示例代码
int keepalive = 1; // 开启keepalive属性int keepidle = 60; // 如该连接在60秒内没有任何数据往来,则进行探测int keepinterval = 5; // 探测时发包的时间间隔为5 秒int keepcount = 3; // 探测尝试的次数。如果第1次探测包就收到响应了,则后2次的不再发,如果3次探测包都没有响应,则会rst关闭连接
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 ));
需要头文件
#include <netinet/tcp.h>
特别注意:如果发送方发送的数据包没有收到接收方回复的ACK数据包,则TCP Keep-alive机制就不会被启动,而TCP会启动超时重传机制,这样就使得TCP Keep-alive机制在未收到ACK包时失效,为解决这一问题,Linux Kernel 2.6.37中增加了一个叫做TCP_USER_TIMEOUT的socket选项,TCP_USER_TIMEOUT选项是TCP层的socket选项,选项接受unsigned int类型的值,值为数据包被发送后未接收到ACK确认的最大时长,以毫秒为单位,例如设置为10000时,代表如果发送出去的数据包在十秒内未收到ACK确认,则下一次调用send或者recv,则函数会返回-1,errno设置为ETIMEOUT,代表connection timeout
示例代码
unsigned int timeout = 1000;
setsockopt(fd, IPPROTO_TCP, TCP_USER_TIMEOUT, &timeout, sizeof(timeout));
二、Time-Out
1、说明
(1)读超时:由于read操作会一直阻塞,设置了读超时后,如果到了超时时间仍没有数据,read会抛出一个SocketTimeoutException,并会返回读错误,程序需要捕获这个异常,但是当前的socket连接仍然是有效的;
(2)写超时:socket的写超时是基于TCP的超时重传,超时重传是TCP保证数据可靠性传输的一个重要机制,其原理是在发送一个数据报文后就开启一个计时器,在一定时间内如果没有得到发送报文的确认ACK,那么就重新发送报文,如果重新发送多次之后,仍没有确认报文,就发送一个复位报文RST,然后关闭TCP连接
2、示例代码
struct timeval timeout={3,0};//3sint ret=setsockopt(sock_fd,SOL_SOCKET,SO_SNDTIMEO,(const char*)&timeout,sizeof(timeout));int ret=setsockopt(sock_fd,SOL_SOCKET,SO_RCVTIMEO,(const char*)&timeout,sizeof(timeout));//ret==0 则为成功,-1为失败int recvd=recv(sock_fd,buf,1024,0);if(recvd==-1&&errno==EAGAIN){ printf("timeout\n");}
int sendflag=send(sock_fd,buf,strlen(buf));
if(sendflag == -1&&errno=EAGAIN)
{
printf("timeout\n");
}
- Socket通信中的实用属性
- 布局中的实用属性
- Unity3D中的Socket通信
- Java中的Socket通信
- iOS中的socket通信
- java中的Socket通信
- java中的socket通信
- Java中的Socket通信
- 融汇贯通实用的socket属性典型讲解
- QT中的SOCKET的通信
- socket 通信进程中的常见问题
- QT中的SOCKET的通信
- php中的socket通信问题
- 自己写的一个同步SOCKET通信类 相当实用
- 解决socket通信中的read阻塞
- socket通信中的select应用简要说明
- 线程池在socket通信中的应用
- java中socket通信中的注意事项
- 《机器学习实战》读书笔记 第三章 决策树(part 3)
- HTML 5 History API
- HTML 5页面可视性API
- 开源项目学习----InfiniteViewPager
- fread 返回值的问题
- Socket通信中的实用属性
- VS2012, opencv2.4.4环境搭建
- POI处理超过65536条记录
- HTML5+CSS3兼容收藏夹
- hibernate的初步使用1,
- 通用数据权限管理系统设计
- HTML6 展望
- Linux free命令详解
- PHP is much better than you think