프로그래밍/소켓 프로그래밍 입문

send와 recv는 1대1로 매핑되어 동작하는가?

데일리 백수 2025. 1. 13. 22:37

소켓 프로그래밍에서 데이터 전송은 send와 recv 함수로 이루어집니다. 초보자들이 자주 오해하는 점 중 하나는, send 호출과 recv 호출이 1:1로 매핑될 것이라는 기대입니다. 그러나 실제 네트워크 환경에서는 send와 recv가 항상 매핑되지 않습니다.

이 글에서는 send와 recv 함수의 동작 원리와 네이글(Nagle) 알고리즘이 매핑에 미치는 영향을 살펴봅니다.

 

 

send와 recv는 매핑될까?

소켓 프로그래밍에서 데이터 전송은 send와 recv 함수로 이루어집니다. 초보자들이 자주 오해하는 점 중 하나는, send 호출과 recv 호출이 1:1로 매핑될 것이라는 기대입니다. 그러나 실제 네트워크 환경에서는 send와 recv가 항상 매핑되지 않습니다.

이 글에서는 send와 recv 함수의 동작 원리와 네이글(Nagle) 알고리즘이 매핑에 미치는 영향을 살펴봅니다.


1. send와 recv의 비매핑 특성

1.1 send와 recv는 1:1로 매핑되지 않는다

  • 여러 번의 send 호출한 번의 recv로 수신될 수 있습니다.
  • 반대로, 한 번의 send 호출로 보낸 데이터가 여러 번의 recv로 나뉘어 수신될 수 있습니다.

예를 들어

// 클라이언트에서 데이터 전송
char szBuffer[] = "Hello";
for (int i = 0; i < strlen(szBuffer); i++)
    ::send(hSocket, szBuffer + i, 1, 0); // 1바이트씩 전송

// 서버에서 데이터 수신
char recvBuffer[128] = { 0 };
int received = ::recv(hSocket, recvBuffer, sizeof(recvBuffer), 0);
printf("Received: %s\n", recvBuffer);

 

실제 전송결과 

한글짜씩 전송될 때도 있지만
여러 글짜씩 전송되는 경우도 발생한다

1.2 동작의 결정 요인

  • 네트워크 인터벌: 데이터 전송 간격이 넓으면 여러 번의 recv 호출이 발생할 가능성이 높아집니다.
  • 운영체제의 네트워크 스택: 내부 버퍼링과 최적화 방식에 따라 다르게 동작합니다.
  • 네이글(Nagle) 알고리즘: 데이터를 묶어서 전송하려는 알고리즘으로 인해 여러 send 호출이 하나로 묶일 수 있습니다.

2. 네이글(Nagle) 알고리즘이란?

2.1 개요

  • 네이글(Nagle) 알고리즘은 소규모 패킷 전송을 최적화하기 위해 고안된 TCP 프로토콜의 기능입니다.
  • 목적:
    • 작은 패킷을 묶어서 전송하여 네트워크 효율성을 높임.
    • 대역폭 사용을 최소화하고 패킷 전송 횟수를 줄임.

2.2 동작 방식

  • 작은 패킷(Small Packets): 송신 데이터가 작을 경우, 출력 버퍼에 데이터를 일정량 모을 때까지 전송을 지연시킵니다.
  • 전송 조건:
    • 이전 데이터가 ACK(확인 응답)를 받을 때까지 새 데이터를 전송하지 않음.
    • 출력 버퍼가 가득 차거나 데이터 크기가 MSS(Maximum Segment Size) 이상일 때 전송.

2.3 장점

  • 네트워크 트래픽 감소.
  • 효율적인 대역폭 사용.

2.4 단점

  • 실시간성이 중요한 애플리케이션(예: 온라인 게임, VoIP 등)에서는 데이터 전송 지연이 발생할 수 있음.

2.5 비활성화

  • 네이글 알고리즘이 실시간성에 부정적 영향을 미친다면 비활성화할 수 있습니다
int flag = 1;
setsockopt(socket, IPPROTO_TCP, TCP_NODELAY, (char *)&flag, sizeof(int));

 

3. 버퍼와 send/recv의 관계

3.1 출력 버퍼와 send

  • 출력 버퍼(Output Buffer):
    • send 호출 시, 데이터는 출력 버퍼에 저장된 후 네트워크로 전송.
    • 출력 버퍼가 가득 차면 send는 블로킹되거나 호출이 지연될 수 있음.
  • 여러 번의 send 호출은 출력 버퍼에서 결합되어 한 번에 전송될 가능성이 있음.

3.2 입력 버퍼와 recv

  • 입력 버퍼(Input Buffer):
    • 수신된 데이터는 입력 버퍼에 저장되며, recv 호출 시 애플리케이션으로 전달.
    • recv는 지정된 크기만큼 읽으려고 시도하지만, 입력 버퍼의 실제 데이터 크기에 따라 반환값이 달라짐.

 

정리

 

  • send와 recv는 항상 매핑되지 않는다.
    • 여러 번 send 호출한 데이터가 한 번의 recv로 수신될 수 있음.
    • 반대로, 한 번 send 호출한 데이터가 여러 번의 recv로 나뉘어질 수도 있음.
  • 네이글 알고리즘의 영향
    • 데이터를 묶어서 전송하여 네트워크 효율성을 높이지만, 실시간성에 영향을 줄 수 있음.
    • 실시간 애플리케이션에서는 비활성화를 고려.
  • 버퍼링의 중요성
    • 송수신 데이터는 소켓의 출력 버퍼와 입력 버퍼에서 처리됨.
    • 애플리케이션의 send/recv 호출 간 간격과 네트워크 상태에 따라 동작이 달라짐.
  • 데이터 크기 확인
    • recv 반환값을 통해 실제 수신된 데이터 크기를 항상 확인해야 함.