소켓은 네트워크 통신의 끝점(endpoint)입니다. 서버가 클라이언트 요청을 받고 응답하는 전체 과정이 소켓 API 호출로 이루어집니다.


TCP 소켓 라이프사이클

PLAINTEXT
서버                              클라이언트
socket()  → 소켓 생성              socket()  → 소켓 생성
bind()    → IP:포트 바인딩
listen()  → 연결 대기 상태
                                  connect() → 3-way handshake
accept()  → 연결 수락 (새 소켓 생성)
                                  
send()/recv() ←─ 데이터 교환 ─→ send()/recv()
                                  
close()   → 연결 종료              close()

핵심 시스템 콜

C
// 서버
int server_fd = socket(AF_INET, SOCK_STREAM, 0);  // TCP 소켓 생성
bind(server_fd, &addr, sizeof(addr));               // 주소 바인딩
listen(server_fd, BACKLOG);                          // 연결 대기

int client_fd = accept(server_fd, &client_addr, &len);  // 연결 수락
recv(client_fd, buf, sizeof(buf), 0);                    // 데이터 수신
send(client_fd, response, len, 0);                       // 데이터 송신
close(client_fd);                                        // 연결 종료

// 클라이언트
int sock = socket(AF_INET, SOCK_STREAM, 0);
connect(sock, &server_addr, sizeof(server_addr));  // 서버에 연결
send(sock, data, len, 0);
recv(sock, buf, sizeof(buf), 0);
close(sock);

listen()의 backlog

PLAINTEXT
listen(fd, 128);  // backlog = 128

SYN 큐 (반연결 큐): SYN 받고 SYN-ACK 보낸 상태의 연결들
Accept 큐 (완료 큐): 3-way handshake 완료된 연결들 (accept() 대기)

backlog가 가득 차면 새 연결 요청을 거부하거나 무시합니다.


UDP 소켓

PLAINTEXT
서버                          클라이언트
socket()  → SOCK_DGRAM       socket() → SOCK_DGRAM
bind()    → IP:포트 바인딩
                              sendto() → 데이터 전송
recvfrom() → 데이터 수신
sendto()  → 응답 전송
                              recvfrom() → 응답 수신

UDP는 connect/accept가 없습니다. 각 패킷이 독립적이며, 목적지 주소를 매번 지정합니다.


SO_REUSEADDR과 SO_REUSEPORT

C
int opt = 1;
setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
// → TIME_WAIT 상태의 포트를 재사용 (서버 재시작 시 유용)

setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, &opt, sizeof(opt));
// → 여러 프로세스가 같은 포트를 listen (로드 밸런싱)

핵심 포인트

  • accept()이 새 소켓을 반환하는 이유: listen 소켓은 계속 연결을 받아야 하므로, 각 클라이언트마다 별도 소켓 생성
  • TIME_WAIT와 SO_REUSEADDR: 서버 재시작 시 "Address already in use" 에러 방지
  • Non-blocking 소켓: fcntl(fd, F_SETFL, O_NONBLOCK)으로 설정, epoll과 함께 사용

정리

소켓 프로그래밍은 네트워크의 가장 기본적인 API입니다. TCP 서버의 socket-bind-listen-accept 흐름과, 각 시스템 콜의 역할을 이해하면 웹 서버, 게임 서버 등 모든 네트워크 프로그래밍의 기반을 갖출 수 있습니다.

댓글 로딩 중...