- Linux에서의 send & recv
#include <sys/socket.h>
ssize_t send(int sockfd, const void *buf, size_t len, int flags);
- sockfd: 데이터 전송 대승과의 연결을 의미하는 socket의 file descriptor
- buf: 전송할 데이터를 저장하고 있는 버퍼의 주소값
- len: 전송할 바이트 수
- flags: 데이터 전송 시 옵션 정보
#include <sys/socket.h>
ssize_t recv(int sockfd, void *buf, size_t len, int flags);
- sockfd: 데이터 수신 대상과의 연결을 의미하는 socket file descriptor
- buf: 수신된 데이터를 저장할 버퍼의 주소값
- len: 수신할 수 있는 최대 바이트 수
- flags: 데이터 수신 시 적용할 옵션 정보
- 옵션 정보 (| 를 이용하여 둘 이상을 함께 전달 가능)
옵션 | 의미 | send | recv |
MSG_OOB | 긴급 데이터(out-of-band data)의 전송을 위한 옵션 | * | * |
MSG_PEEK | 입력버퍼에 수신된 데이터의 존재유무 확인을 위한 옵션 | * | |
MSG_DONTROUTE | 데이터 전송과정에서 라우팅 테이블을 참조하지 않을 것을 요구하는 옵션, 따라서 로컬 네트워크 상에서 목적지를 찾을 때 사용되는 옵션 | * | |
MSG_DONTWAIT | 입출력 함수 호출과정에서 블로킹 되지 않을 것을 요구하기 위한 옵션, non-blocking IO의 요구에 사용되는 옵션 | * | * |
MSG_WAITALL | 요청한 바이트 수에 해당하는 데이터가 전부 수신될 때까지 호출된 함수가 반환되는 것을 막기 위한 옵션 | * |
- MSG_OOB: 긴급 메시지의 전송
- out-of-band data라는 긴급 메세지의 전송을 위해 메시지의 전송방법 및 경로를 달리 함
- MSG_OOB의 긴급 메시지를 수신하면 운영체제는 SIGURG 시그널을 발생시켜 프로세스가 등록한 시그널 핸들로가 호출
- fcntl(recv_sock, F_SETOWN, getpid()); // file descriptor의 컨트롤에 사용
: file descriptor recv_sock이 가리키는 socket에 의해 발생하는 SIGURG 시그널을 처리하는 프로세스를 getpid 함수가 반환하는 ID의 프로세스로 변경시키겠다
- getpid: 이 함수를 호출한 프로세스의 ID를 반환하는 함수
// oob_send.c
// oob_recv.c
// 실행창
- TCP는 전혀 다른 통신 경로로 전송되는 데이터를 뜻하는 out-of-band data를 위한 별도의 통신경로를 제공하지 않고 TCP의 Urgent mode를 이용해 데이터를 전송
- MSG_OOB 옵션을 추가해도 더 빨리 데이터가 전송되지 않음
- 시그널 핸들러를 이용해 읽히는 데이터는 1바이트이며 나머지는 일반적인 입력함수의 호출을 통해 읽힘
- Urgent mode
- 데이터의 전송에서 전송순서가 유지되면서 데이터를 수신하는 대상에게는 데이터의 처리를 재촉
- 빠른 전송 속도를 보장하진 않지만 긴급 메시지가 전송되었음이 시그널 핸들러를 통해 인지됨
- MSG_OOB 옵션의 데이터 전송 과정
send(sock, "890", strlen("890"), MSG_OOB);
- offset 3의 위치가 urgent pointer로 지정되어 긴급 메시지의 마지막 문자열의 offset + 1의 위치를 가리키면서 상대 호스트에게 urgent pointer가 가리키는 offwet의 바로 앞에 존재하는 것이 긴급 메시지임을 알림
- 데이터 전송을 위해 구성되는 TCP 패킷의 구조
- TCP header에 URG=1 : 긴급 메시지 존재
- TCP header에 urgent pointer=5 : urgent pointer의 위치가 offset 5의 위치
- 데이터를 수신하는 상대 호스트에서는 urgent pointer의 앞 1바이트를 제외하고는 나머지는 일반적인 입려함수의 호출로 읽음
offset: 기본이 되는 위치를 바탕으로 상대적 위치를 표현하는 것
ex) 실제 3번지를 기준으로 offset 부여 -> 실제 4번지: offset 1
때문에 일반적인 주소와 달리 항상 0에서부터 시작
- MSG_PEEK: 입력버퍼 검사하기
- MSG_PEEK
: MSG_DONTWAIT 옵션과 함께 설정되어 입력버퍼에 수신된 데이터가 존재하는지 확인하는 용도
: MSG_PEEK 옵션을 설정하고 recv 함수를 호출하면 입력버퍼에 존재하는 데이터가 읽혀지더라도 데이터가 지워지지 않음, MSG_DONTWAIT 옵션과 함께 사용해 입력버퍼에 데이터가 존재하지 않더라도 블로킹(반환안되는 상태) 되지 않도록 함
// peek_recv.c
- 입력버퍼의 데이터를 지우기 위해 옵션을 설정하지 않은 recv 함수를 한번 더 호출
// peek_send.c
// 실행창
- 한번 전송한 데이터가 두 번 읽혀짐
'프로그래밍의 기초 > TCP | IP' 카테고리의 다른 글
윈도우 기반으로 writev & readv 함수 구현하기 (0) | 2022.01.28 |
---|---|
readv & writev 입출력 함수 (0) | 2022.01.27 |
윈도우 기반으로 IO 멀티플렉싱 서버 구현하기 (0) | 2022.01.24 |
select 함수의 이해와 서버의 구현 (0) | 2022.01.21 |
IO 멀티플렉싱 기반의 서버 (0) | 2022.01.21 |