컴퓨터 공부/네트워크 프로그래밍

[TCP/IP 소켓 프로그래밍] 13. 고급 입출력 함수

려리군 2009. 8. 6. 16:52

13-1. recv & send 입출력 함수

read & write 함수와 달리 데이터 입출력 방법에 있어서 옵션 부여.

#include<sys/types.h>

#include<sys/socket.h>


int recv(int sock, void *buf, int len, unsigned int flags);

int send(int sock, const void * buf, int len, unsigned int flags);


옵션의 종류와 의미

 - MSG_DONTROUTE (send 함수 호출시에만 사용하는 옵션)

    데이터 전송 시 라우팅 테이블(라우터에 있음)을 참조하지 않음.

    => Local network 내에서만 패킷을 전송하겠다는 뜻.

 - MSG_DONTWAIT (send, recv 함수 모두에 사용하는 옵션)

    not blocking 입출력 기능

 - MSG_OOB (send, recv 함수 모두에 사용하는 옵션)

    데이터 전송 시, 긴급 데이터(Out-of-band data) 전송

    ※ Out-of-band : 도로 상의 갓길을 생각하면 좋음.

 - MSG_PEEK (recv 함수 호출시에만 사용하는 옵션)

    버퍼에 데이터 유무 확인.


긴급한 데이터의 전송

전송 프로그램 예시

write(sock, "123", 3);

send(sock, "4", 1, MSG_OOB);

write(sock, "567", 3);

send(sock, "890", 3, MSG_OOB);


수신 프로그램 예시

① fcntl(send_sock, F_SETOWN, getpid());

파일 디스크립터를 제어하는 함수.

send_sock : 소켓의 파일 디스크립터

F_SETOWN 소유자를 설정.

getpid(); : 현재 프로세스의 ID

※ 뜻 : send_sock의 소유자를 현재 프로세스로 설정한다.
※ 사용 이유 : 어느 프로세스에게 시그널을 발생시킬지 정해야 한다. SIGURG를 받기 위해 반드시 소켓의 소유자를 지정해야 한다. 


② state = sigaction(SIGURG, &act, 0);

SIGURG : 긴급 데이터(out-of-band)를 받을 때 발생하는 시그널.


긴급 데이터 전송 시 생성되는 패킷

recv함수를 호출할 때 urgent point-1 위치부터 1바이트만 읽어들인다.

긴급 데이터 전송의 특징

- 버퍼 상황에 관계 없이 데이터 전송 ( 버퍼가 비어지길 기다리지 않고 바로 전송)

- Nagle 알고리즘 무시


입력버퍼 검사하기

sleep 함수 사용 이유 : 패킷을 온전히 다 받기 위해 사용.

MSG_PEEK : 메세지를 읽어도 소켓의 수신 버퍼에 데이터 내용을 지우지 않는다.

MSG_DONTWAIT : 버퍼가 비어 있지 않아도 바로 리턴 받기 위해서...

※ 두 개의 옵션을 같이 사용한다.


13-2. readv & writev 입출력 함수

데이터를 모아서 전송(writev) : 한 번 호출하여 한 번에 보낸다.

#include<sys/io.h>

int writev(int fd, const struct iovec *vector, int count);

리턴 : 성공시 전송한 바이트 수, 실패시 -1

데이터 여러 개(count개)를 모아서 전송한다.

fd : 데이터 전송의 목적지를 나타내는 소켓의 파일 디스크립터

vector : iovec 구조체 이름을 인자로 전달. 전송하고자 하는 데이터에 대한 정보가 담겨진다. 

count : iovec 구조체 변수의 개수.


데이터를 분산 수신(readv) : 한번 호출하여 나누어진 버퍼에 저장한다.

#include<sys/io.h>

int readv(int fd, const struct iovec *vector, int count);

리턴 : 성공시 수신한 바이트 수, 실패시 -1

fd : 데이터를 수신할 파일 디스크립터

vector : iovec 구조체 이름을 인자로 전달. 어디에 얼마칸큼 데이터를 수신할 것인지 정보를 전달.

count : iovec 구조체 변수의 개수.


배열을 정의하기 위한 구조체의 선언

struct iovec{

    ptr_t iov_base;    // 보내고자 하는 데이터의 시작주소

    size_t iov_len;    // 보내고자 하는 데이터의 크기

};


readv&writev 함수의 적절한 사용

1. 함수호출 회수가 적으면 효율적임.

2. nagle알고리즘을 적용하지 않는 경우 다음과 같은 장점을 가진다.

일반 write 3번 호출 : 3개의 패킷을 생성하여 전송

nagle알고리즘을 적용한 경우

writev 호출 : 1개의 패킷을 생성하여 전송.

3. 큰 배열을 생성하여 하드코딩해서 보내는 것보다 한번의 함수로 모아서 보내는 게 편리하다.


13-3. 윈도우즈 기반으로 구현하기

윈도우즈 기반 OOB 데이터 송수신

1. 윈도우즈 기반에서는 'signal 핸들링' 이라는 개념이 존재하지 않는다.

2. select 함수는 소켓을 통해서 예외 상황(OOB 데이터 수신)이 발생하였는지 확인 가능하다.

예시)

FD_ZERO(&except);

FD_SET(hSendSock,&except);

exceptCopy = except;

select(?, ?, ?, &exceptCopy, ?);