Chinaunix首页 | 论坛 | 博客
  • 博客访问: 505796
  • 博文数量: 77
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 689
  • 用 户 组: 普通用户
  • 注册时间: 2013-08-12 08:40
文章分类

全部博文(77)

文章存档

2018年(1)

2016年(3)

2015年(24)

2014年(49)

我的朋友

分类: 网络与安全

2015-01-09 18:05:12

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

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


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

    
为了回收资源必须提供一种检测机制

1) 应用层面的心跳机制

    自定义心跳消息头。一般客户端主动发送, 服务器接收后进行回应(也可以不回应)。

2) TCP协议自带的保活功能

    TCP协议栈有个keepalive的属性,可以主动探测socket是否可用

点击(此处)折叠或打开

  1. //设置发送超时
  2. struct timeval timeout = {3,0};
  3. //fcntl(client_fd ,F_SETFL, O_NONBLOCK);
  4. setsockopt(client_fd, SOL_SOCKET,SO_SNDTIMEO,(char *)&timeout,sizeof(struct timeval));
  5. setsockopt(client_fd, SOL_SOCKET,SO_RCVTIMEO,(char *)&timeout,sizeof(struct timeval));

Unix平台如何使用Keep-alive:

  #include <sys/socket.h>
  #include <netinet/in.h>
  #include <arpa/inet.h>
  #include <sys/types.h>
  #include <netinet/tcp.h>

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

  setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, (void *)&keepAlive, sizeof(keepAlive));
  setsockopt(fd, SOL_TCP, TCP_KEEPIDLE, (void*)&keepIdle, sizeof(keepIdle));
  setsockopt(fd, SOL_TCP, TCP_KEEPINTVL, (void *)&keepInterval, sizeof(keepInterval));
  setsockopt(fd, SOL_TCP, TCP_KEEPCNT, (void *)&keepCount, sizeof(keepCount)); 
   


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

TCP连接状态查看:

点击(此处)折叠或打开

  1. int SocketConnected(int sock)
  2. {
  3.     if(sock<=0) return 0;
  4.     struct tcp_info info;
  5.     int len=sizeof(info);
  6.     getsockopt(sock, IPPROTO_TCP, TCP_INFO, &info, (socklen_t *)&len);
  7.     if((info.tcpi_state==1)||(info.tcpi_state==8))  //info.tcpi_state==TCP_ESTABLISHED
  8.     {
  9.         return 1;
  10.     }
  11.     else
  12.     {
  13.         DEBUG_MSG("tcpi_state %d\n",info.tcpi_state);
  14.         if((info.tcpi_state==7)) return 0;
  15.         return 1;
  16.     }
  17.  }


阅读(6987) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~