1、设置心跳机制Heartbeat
- 新增协议类型:
MSG_TYPE_PING和MSG_TYPE_PONG。 - 客户端每隔 30 秒后台发送一个 Ping。
- 服务器在
Conn结构体中记录last_active_time。 - 服务器引入一个定时器机制(或者在
epoll_wait超时后轮询),踢掉超过 90 秒没发心跳的死连接。
1.1 server.c 修改
int nfds = epoll_wait(epoll_fd, events, MAX_EVENTS, 1000);//就绪的事件数量,将timeout改为1000毫秒,这样即使没有网络事件,epoll 也会每秒醒来一次。
time_t now = time(NULL);
for (int i = 0;i < 1024;i++){
Conn *c = g_conns[i];
// 如果连接存在,且当前时间减去最后活跃时间大于超时阈值
if(c!=NULL && (now - c->last_active_time)>TIMEOUT_SEC){
printf("[Reaper] fd %d (uid:%u) time out. Kicking offline.\n",c->fd,c->uid);
conn_delete(c->fd);
}
测试(此时只在服务器加入心跳机制)
1.2 client.c 修改
void *heartbeat_thread_func(void* arg){
int sockfd = *(int*)arg;
// 预先构造好心跳包(只有包头)
AppHeader ping_hdr;
ping_hdr.magic = htonl(PROTOCOL_MAGIC);
ping_hdr.version = htons(1);
ping_hdr.type = htons(MSG_TYPE_PING);
ping_hdr.length = htonl(0);
while (1)
{
sleep(30);
int n = send(socked,&ping_hdr,sizeof(AppHeader),0);
if(n<=0){
break;
}
}
return NULL;
}
int main{
...
pthread_t hb_tid;
pthread_create(&hb_tid,NULL,heartbeat_thread_func,&sockfd);// 启动心跳线程
...
测试:客户端每隔 30 秒后台发送一个 Ping,MSG_TYPE_PING==152