개요
이 문서는 클라이언트가 서버로 정기적으로 허트비트 패킷을 전송하는 방식을 기반으로 한 연결 상태 모니터링 시스템을 설명합니다. 서버는 응답을 반환하지 않고, 클라이언트의 활성 여부를 간접적으로 판단하여 비정상적인 연결을 탐지하고 세션 정보를 정리합니다.
핵심 원리
- 클라이언트 측: 3초 간격으로 허트비트 메시지를 전송합니다.
- 서버 측: 별도의 스레드에서 각 사용자 세션의 카운터를 3초마다 증가시킵니다 (초기값 0).
- 세션 업데이트: 서버가 허트비트 수신 시 해당 사용자의 카운터를 0으로 리셋합니다.
- 비정상 감지: 카운터가 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;
}
}
}