(再发:各位大虾别私藏了)200分求解 先谢谢各位!!!linux下 TCP 保活机制实现问题》???

soul850224 2012-03-05 09:18:41
各位大侠好!
我现在要在客户端实现保活机制。而不是在服务器端(这个我已经实现,抓包看到数据了)
但是我在客户端(就是TCP connect 端) 设定保活机制
当我断开,服务器端网线时
并未抓到客户端发送的 探测包 keeplive ...
客户端代码如下 (服务器端就不贴了 就是绑定等待连接 。。。)
先谢谢各位了!
我的问题是

1.是我的代码有问题 参数设定不对
2.还是客户端不可实现
3.如果客户端不可实现 原理是为什么???
...全文
189 8 打赏 收藏 转发到动态 举报
写回复
用AI写文章
8 条回复
切换为时间正序
请发表友善的回复…
发表回复
soul850224 2012-03-09
  • 打赏
  • 举报
回复
ai 人烟稀少啊...
soul850224 2012-03-05
  • 打赏
  • 举报
回复
代码在2楼 ...
各位大虾
客户端代码如2楼 (服务器端就不贴了 就是绑定等待连接 。。。标准服务端模板)
谢谢各位了..
ZongShengLee 2012-03-05
  • 打赏
  • 举报
回复
求代码。
soul850224 2012-03-05
  • 打赏
  • 举报
回复
先谢谢! 代码如下:
#include <stdio.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>

#define SRV_IP "192.168.7.189"
#define SRV_PORT 12345

#define errexit(msg) do {perror(msg); exit(EXIT_FAILURE);} while(0)
void active_keepalive(int sockfd);
void set_keepalive_params(int sockfd, int idle, int count, int intvl);

int main(int argc, char *argv[])
{
int sockfd;
int len=0;
int n =0;
int i = 0;
struct sockaddr_in srvaddr;
fd_set readfds;
char buf[1024] = {0};
sockfd = socket(AF_INET, SOCK_STREAM, 0);
// sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (sockfd < 0)
errexit("socket");
int reuse = 1;
if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(int)) < 0) {
perror("setsockopt SO_REUSEADDR");
close(sockfd);
return -1;
}

memset(&srvaddr, 0, sizeof(struct sockaddr_in));
srvaddr.sin_family = AF_INET;
srvaddr.sin_addr.s_addr = inet_addr(SRV_IP);
srvaddr.sin_port = htons(SRV_PORT);

if (connect(sockfd, (struct sockaddr *)&srvaddr, sizeof(struct sockaddr_in)) != 0)
errexit("connect");
else
printf("connect to server succeeded!\n");

active_keepalive(sockfd);
/* 设置 keepalive 相关参数 */
set_keepalive_params(sockfd, 6, 3, 2);


/* 连接成功后,什么也不做 */

while (1) {
FD_ZERO(&readfds);
FD_SET(sockfd, &readfds);

printf("start select............\n");
if ((n = select(sockfd + 1, &readfds, NULL, NULL, NULL)) < 0)
{
perror("select faield");
}
printf("ok!\n");
if(FD_ISSET(sockfd, &readfds))
{
len = read(sockfd, buf, sizeof(buf) - 1);
if (len < 0)
{
if (errno == EINTR)
{
printf("errno == EINTR\n");
continue;
}
if (errno == ETIMEDOUT)
{
printf("ETIMEDOUT..............., client: %d\n", i + 1);
perror("read error");
close(sockfd);
break;
}
}
else if (len == 0)
{
printf("client close socket.\n");
close(sockfd);
break;
}
else
{
printf("read from client: %s\n", buf);
}
printf("FD_ISSET(cltfd, &readfds) is error!\n");
}
}

pause();

close(sockfd);
exit(0);
}

int init_socket_tcp(unsigned short port, int backlog)
{
int sockfd;
struct sockaddr_in srv_addr;
socklen_t addrlen;

sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (sockfd < 0) {
perror("create socket failed!");
return -1;
}

addrlen = sizeof(struct sockaddr_in);
memset(&srv_addr, 0, sizeof(struct sockaddr_in));
srv_addr.sin_family = AF_INET;
srv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
srv_addr.sin_port = htons(port);

int reuse = 1;
if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(int)) < 0) {
perror("setsockopt SO_REUSEADDR");
close(sockfd);
return -1;
}

if (bind(sockfd, (struct sockaddr *)&srv_addr, addrlen) < 0) {
perror("bind errror");
close(sockfd);
return -1;
}

if (listen(sockfd, backlog) < 0) {
perror("listen error");
close(sockfd);
return -1;
}

return sockfd;
}

void active_keepalive(int sockfd)
{
int optval;
socklen_t optlen = sizeof(optval);

/* check the status for the keepalive option */
if (getsockopt(sockfd, SOL_SOCKET, SO_KEEPALIVE, &optval, &optlen) < 0) {
perror("getsockopt SO_KEEPALIVE failed");
close(sockfd);
exit(EXIT_FAILURE);
}
printf("SO_KEEPALIVE is %s\n", optval ? "ON" : "OFF");

/* set the option active */
optval = 1;
optlen = sizeof(optval);
if (setsockopt(sockfd, SOL_SOCKET, SO_KEEPALIVE, &optval, optlen) < 0) {
printf("setsockopt SO_KEEPALIVE failed,reason: %m\n");
close(sockfd);
exit(EXIT_FAILURE);
}
printf("SO_KEEPALIVE on socket\n");

/* check the status again */
if (getsockopt(sockfd, SOL_SOCKET, SO_KEEPALIVE, &optval, &optlen) < 0) {
perror("getsockopt SO_KEEPALIVE again failed");
close(sockfd);
exit(EXIT_FAILURE);
}
printf("SO_KEEPALIVE is %s\n", (optval ? "ON" : "OFF"));
}

void set_keepalive_params(int sockfd, int idle, int count, int intvl)
{
int keepalive_time = idle;
int keepalive_probes = count;
int keepalive_intvl = intvl;

if (setsockopt(sockfd, SOL_TCP, TCP_KEEPIDLE, &keepalive_time, sizeof(int)) < 0) {
perror("TCP_KEEPIDLE failed");
return;
}

if (setsockopt(sockfd, SOL_TCP, TCP_KEEPCNT, &keepalive_probes, sizeof(int)) < 0) {
perror("TCP_KEEPCNT failed");
return;
}

if (setsockopt(sockfd, SOL_TCP, TCP_KEEPINTVL, &keepalive_intvl, sizeof(int)) < 0) {
perror("TCP_KEEPINTVL failed");
return;
}

return;

}
鸟辉 2012-03-05
  • 打赏
  • 举报
回复
保活机制。是发心跳吗?代码没看见哦。
soul850224 2012-03-05
  • 打赏
  • 举报
回复
[Quote=引用 6 楼 believe_me 的回复:]
客户端新建一个线程,定时发送心跳包,服务端接收到心跳包时更新时间。
服务端新起一个线程,用来处理客户端连接状态。如果超过定义的超时时间。则可以断开该连接。
[/Quote]
这种方法,
问题是你服务器端如果收到心跳不做处理 即不回复给我客户端
但你服务器网线异常掉了时
我客户端 send是不失败的
而是根据时间的随机性 send 失败
所以我才想用 keepalive

而我要是想改服务器 也无法修改 服务器不让修改
我现在到时用憋的方法解决了

但是我就是很想知道
为什么客户端设定保活机制 没有效果...
先谢谢大家的意见!!!
believe_me 2012-03-05
  • 打赏
  • 举报
回复
客户端新建一个线程,定时发送心跳包,服务端接收到心跳包时更新时间。
服务端新起一个线程,用来处理客户端连接状态。如果超过定义的超时时间。则可以断开该连接。
teleinfor 2012-03-05
  • 打赏
  • 举报
回复
http://blog.csdn.net/xjtuse_mal/article/details/5388529
http://www.cppblog.com/prayer/archive/2009/02/03/72853.html

keepalive功能的实现,可能这个选项并不能实现你的预期。正确的做法是自己构造一个heart-beat包。定时发送给目标主机,让双方通过有序的定时包通知本方在线,达到保活的目的。

64,639

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧