L-Chat(3)——M4.1

0 阅读1分钟

1、设置心跳机制Heartbeat

  • 新增协议类型:MSG_TYPE_PINGMSG_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);
            }

测试(此时只在服务器加入心跳机制)

image.png

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

image.png