클라이언트 기반 소켓 허트비트 이상 감지 시스템의 C 언어 구현

개요

이 문서는 클라이언트가 서버로 정기적으로 허트비트 패킷을 전송하는 방식을 기반으로 한 연결 상태 모니터링 시스템을 설명합니다. 서버는 응답을 반환하지 않고, 클라이언트의 활성 여부를 간접적으로 판단하여 비정상적인 연결을 탐지하고 세션 정보를 정리합니다.

핵심 원리

  1. 클라이언트 측: 3초 간격으로 허트비트 메시지를 전송합니다.
  2. 서버 측: 별도의 스레드에서 각 사용자 세션의 카운터를 3초마다 증가시킵니다 (초기값 0).
  3. 세션 업데이트: 서버가 허트비트 수신 시 해당 사용자의 카운터를 0으로 리셋합니다.
  4. 비정상 감지: 카운터가 5에 도달하면(총 15초 미수신) 연결 끊김으로 간주하고 세션 삭제.

구현 코드

클라이언트 - 허트비트 전송 스레드

// 허트비트 전송 함수
void *send_heartbeat(void *arg) {
    int client_socket = *(int*)arg;
    struct packet_data *pkt = malloc(sizeof(struct packet_data));

    while (1) {
        pkt->type = HEARTBEAT;  // 패킷 유형 설정
        send(client_socket, pkt, sizeof(struct packet_data), 0);
        sleep(3);  // 3초 간격
    }

    free(pkt);
    return NULL;
}

서버 - 세션 관리 및 허트비트 처리

// 세션 노드 정의
typedef struct session_node {
    char ip_addr[16];
    char username[20];
    int socket_fd;
    int heartbeat_counter;
    struct session_node *next;
} session_t;

// 전역 세션 리스트 헤더
extern session_t *session_head;

// 허트비트 수신 처리
void handle_heartbeat(int sock, struct packet_data *packet) {
    session_t *curr = session_head->next;

    while (curr != NULL) {
        if (strcmp(curr->username, packet->sender) == 0) {
            curr->heartbeat_counter = 0;  // 카운터 초기화
            printf("✅ %s (%s): 연결 유지 확인\n", curr->username, curr->ip_addr);
            break;
        }
        curr = curr->next;
    }
}

// 허트비트 감시 스레드
void *monitor_heartbeats(void *unused) {
    printf("🔧 허트비트 감시 스레드 시작됨...\n");

    while (1) {
        check_session_status();
        sleep(3);
    }

    return NULL;
}

// 세션 상태 점검 함수
void check_session_status() {
    session_t *prev = session_head;
    session_t *current = session_head->next;

    while (current != NULL) {
        if (current->heartbeat_counter >= 5) {
            printf("❌ %s (%s): 연결 해제 감지 (미수신 지속 시간: 15초)\n",
                   current->username, current->ip_addr);

            close(current->socket_fd);
            session_t *to_remove = current;
            prev->next = current->next;
            free(to_remove);
            current = prev->next;
        } else if (current->heartbeat_counter > 0) {
            printf("⚠️  %s (%s): 연결 불안정 (카운터: %d)\n",
                   current->username, current->ip_addr, current->heartbeat_counter);
            current->heartbeat_counter++;
            current = current->next;
        } else {
            current->heartbeat_counter++;
            current = current->next;
        }
    }
}

태그: Socket Programming C language heartbeats Session Management Multithreading

6월 6일 18:20에 게시됨