1. 애플리케이션 레벨: 소켓 준비 → 요청 처리
- 소켓 생성 (socket)
- 커널 내에 struct socket + struct sock 을 할당
- 프로세스의 FD 테이블에 struct file 포인터를 연결하고, 정수 인덱스(sockfd)를 반환
int sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
- 주소 바인딩 (bind)
- struct inet_sock 에 IP·포트(addr.sin_addr, addr.sin_port) 저장
- 커널의 포트 테이블(hash)에 등록해, 해당 IP:포트로 들어오는 패킷을 이 소켓으로 라우팅 가능케 함
bind(sockfd, (struct sockaddr*)&addr, sizeof(addr));
- 리스닝 시작 (listen)
- 소켓 상태를 TCP_LISTEN으로 전환
- SYN 요청을 대기할 백로그 큐(SYN 큐 + 완료 대기 큐) 생성
listen(sockfd, backlog);
- 연결 수락 (accept) → HTTP 파싱 → 라우팅
- 커널이 백로그 큐에서 완성된 연결을 꺼내 새 FD 반환
- HTTP 요청 라인·헤더·바디 파싱 → 라우터/미들웨어 → 컨트롤러 → 비즈니스 로직
- 응답(write()/end()) 후, Keep-Alive 여부에 따라 소켓 재사용 또는 닫기
const conn = await accept(sockfd); // 또는 epoll/select 로 FD 이벤트 감지
- 로그·정리
- 요청·응답 로그 기록
- 클라이언트가 연결 종료 시, 커널이 소켓 자료구조를 해제
2. 커널 레벨(“백그라운드”): 패킷 처리 & 핸드셰이크
- NIC 인터럽트 발생
- 물리계층 이더넷 프레임 수신 → NIC → CPU 인터럽트
- 드라이버가 sk_buff 버퍼에 프레임 저장, 체크섬 검사
- SoftIRQ (NET_RX_SOFTIRQ)
- 인터럽트 컨텍스트 일부 처리 → 나머지 TCP 프로토콜 처리는 소프트IRQ에서 분리 실행
- tcp_rcv_state_process() 등으로 SYN/SYN-ACK/ACK 3-웨이 핸드셰이크 자동 관리
- 백로그 큐 등록
- 핸드셰이크 완료된 연결은 리스닝 소켓의 완료 대기(backlog) 큐 로 적재
- 애플리케이션의 accept/epoll 호출 시
- accept() → 커널이 백로그에서 연결 꺼내 새 struct socket/새 FD 생성
- epoll/select → 읽기 가능한 FD 이벤트로 알림
- 데이터 송·수신
- 수신: 커널 rx 버퍼 → read()/recv() 로 애플리케이션 메모리로 복사
- 송신: write()/send() 로 커널 tx 버퍼에 복사 → TCP 세그먼트로 분할 → NIC 전송
전체 요약
- socket → bind → listen: 애플리케이션이 커널에 소켓 열고, IP:포트 등록
- 패킷 입출력: 커널 네트워크 스택(NIC 드라이버, SoftIRQ, TCP 프로토콜)이 백그라운드에서 처리
- accept/epoll → read/write: 애플리케이션은 커널이 준비한 연결 및 데이터를 시스템 콜로 가져와 HTTP 처리
이렇게 애플리케이션과 커널이 역할을 분리해, 네트워크 I/O를 효율적으로 처리하게 됩니다.
'Research > Study' 카테고리의 다른 글
| [2025.06.01] System call 호출 흐름 (0) | 2025.06.01 |
|---|---|
| [2025.06.01] 레지스트리 편집기 (0) | 2025.06.01 |
| [250529] MCP(모델 컨텍스트 프로토콜) 개요 (0) | 2025.05.29 |
| [Deep research][250506] Linux/QNX 환경의 C++ 보안 취약점 분석 가이드 (1) | 2025.05.06 |
| [Deep research][250501] 백엔드·앱 개발자를 위한 통계 기반 제품 개선 지식 (0) | 2025.05.01 |