udp, tcp 경계의 의미
recv()함수에 인자로 주는 최대 길이 제한이 있긴 합니다만, 보내는 쪽에서 몇 글자를 보내기로 되어 있는지 사전에 합의를 확실히 했다면야 괜찮겠지만, 저 길이보다 작은 메시지가 둘 이상 오면 합쳐질 수 있겠지요.
잠깐 해봤는데 역시 그렇습니다.
다음과 같이 세개의 메시지가 있고,
char *msg[] = {
"msg1",
"msg2",
"msg3"
};
TCP 클라이언트에서 다음과 같에 연달아 세 번 보낸다고 할때,
for (i=0; i<3; i++) {
send(sock, msg[i], strlen(msg[i]), 0);
}
서버에서 바로바로 받지 못하고 약간 딜레이가 있다면
for(i=0; i<3; i++) {
sleep(3); // 딜레이
str_len = recv(clnt_sock, message, BUFSIZE, 0);
message[str_len] = '\0';
printf("size[%d] message[%s]\n", str_len, message);
}
(이 때 BUFSIZE는 100)
결과는 다음과 같이 나옵니다.
size[12] message[msg1msg2msg3]
size[0] message[]
size[0] message[]
즉 수신 버퍼에 쌓인 세 개의 메시지를 한번에 읽어버린다는 얘기지요. (사실 두번째 루프에서 읽을 게 없어서 블로킹되어야 정상인데, 클라이언트가 바로 소켓 닫고 종료해버린 덕에 저렇게 0개 읽고 끝났네요)
반면에 UDP(전송시마다 컴퓨터끼리 연결을 요청해야함, 전송하고 나서 연결이 바로 끊어짐) 에서는
클라이언트에서 세 번 연달아 보내고
for (i=0; i<3; i++) {
sendto(sock, msg[i], strlen(msg[i]), 0, (struct sockaddr *)&serv_addr, sizeof(serv_addr));
}
서버에서 마찬가지로 딜레이를 두고 받을 때
for(i=0; i<3; i++) {
sleep(3);
str_len = recvfrom(serv_sock, message, BUFSIZE, 0, (struct sockaddr*)&clnt_addr, &clnt_addr_size);
message[str_len] = '\0';
printf("size[%d] message[%s]\n", str_len, message);
}
결과는 다음과 같이
size[4] message[msg1]
size[4] message[msg2]
size[4] message[msg3]
즉 수신 버퍼에 메시지 3개가 쌓였을 때 첫번째 recvfrom 은 처음 메시지 한개만 읽고 끝난다는 얘깁니다.