C 언어에서 소켓 통신 코드를 보다 보면 제일 자주 만나는 함수가 recv()다.
연결이 끝난 TCP 소켓에서 데이터를 읽을 때 사용한다.
형태는 ssize_t recv(int sockfd, void *buf, size_t len, int flags) 이다.
sockfd에서 최대 len 바이트를 읽어 buf에 넣고 실제로 읽은 바이트 수를 반환한다.
TCP는 메시지가 아니라 바이트 스트림이라서 한 번의 recv()가 상대방의 한 번의 send()와 같은 크기로 돌아온다는 보장은 없다.
필요한 길이가 정해져 있다면 반복해서 받아야 한다.
여기서 파일 디스크립터는 열린 소켓을 가리키는 정수 번호다. 예제의 client_fd는 이미 연결된 TCP 소켓이라는 전제다. 이 부분만 새 C 파일에 붙이면 접속까지 만들어 주는 완성 서버가 되지는 않는다.
char buf[1024];
ssize_t n = recv(client_fd, buf, sizeof(buf) - 1, 0);
if (n > 0) {
buf[n] = '\0';
printf("받은 내용: %s\n", buf);
} else if (n == 0) {
printf("상대방이 연결을 정상 종료함\n");
} else {
perror("recv");
}
반환값이 0이면 에러가 아니라 상대방이 연결을 정상적으로 닫았다는 뜻이다.
-1이면 errno를 확인한다.
블로킹 소켓도 시그널에 의해 EINTR로 끝날 수 있고 논블로킹 소켓은 데이터가 없을 때 EAGAIN 또는 EWOULDBLOCK이 나온다.
문자열을 받는다면 위 예제처럼 마지막에 직접 널 문자를 넣어야 한다.
답글 달기