c&c++

[메모장]Send/Recv,Read/Write 차이[펌]

sieunju 2017. 7. 12. 10:17
반응형

이건 내가 나중에도 보고 지금도 볼수 있게 메모장으로 해놓은것.

출처 - http://blog.naver.com/PostView.nhn?blogId=xenoheart&logNo=130128522839


Linux의 경우에 대한 이야기이다.

Windows에서는 socket programming에서 read/write를 쓸 수 없다.

read/write와 send/recv의 차이에 대해서 검색하다가 좋은 글이 있어 소개한다.

영어로 된 글이어서 번역 및 정리를 하였다.

원본은 다음 링크를 확인하자 : http://www.developerweb.net/forum/showthread.php?t=3878

  1. read/write가 socket에 대해서 동작할때는 마지막에 recv/send를 호출한다.
  2. recv/send는 매 I/O에 대해서 recvmsg/sendmsg를 사용한다.

따라서, 가장 효율적인 function 사용은 recvmsg/sendmsg가 되겠다.

하지만, 실제로 read/write, recv/send, recvmsg/sendmsg간의 차이는 아주 작으므로

평소에는 그냥 아무거나 사용해도 된다.

원본글에서 RobSeace 자신은 아래와 같이 사용한다고 한다.

  1. 대부분의 경우에는 read/write를 사용한다.
  2. flag를 사용해야할 경우에는 recv/send를 사용한다. (때때로 MSG_PEEK는 매우 유용하다)
  3. 가끔 다수의 작은 데이터를 전송해야할 때에는 recvmsg/sendmsg를 사용한다.

 

출처 http://kylesoft.springnote.com/pages/6455405

 

 

recv

이름

       recv, recvfrom, recvmsg - 소켓으로 부터 메세지를 받는다.

사용법

       #include <sys/types.h>
       #include <sys/socket.h>

       ssize_t recv(int s, void *buf, size_t len, int flags);

       ssize_t recvfrom(int s, void *buf, size_t len, int flags,
                        struct sockaddr *from, socklen_t *fromlen);

       ssize_t recvmsg(int s, struct msghdr *msg, int flags);

 

 

설명

       recvfrom 그리고 recvmsg는 연결 지향형이든 아니든 소켓에서 메세지를 받기위해 사용된다.

       그리고 소켓에 있는 데이터를 받기 위해 사용된다.

       만일 from이 NULL이 아니고 소켓이 연결 지향형이 아니라면, 메세지의 본래 주소가 채워진다.

       인자 fromlen은 값-결과 변수이며 from과 관련된 버퍼의 크기로 초기화되며, 반환시 저장되는

      주소의 실제 크기를 가리키는 값으로 수정된다.

 

       recv 호출은 보통 연결된 소켓에서만 사용된다. (connect(2)를 참조) 그리고 from 인자를 가진

       recvfrom과 동일하다.

 

       소켓에 메시지가 없다면, 메시지를 받는 호출은 메시지가 들어올때까지 기다리게 되며, 만약

       소켓이 넌 블러킹 (fcntl(2)참조)이었다면 결과값은 -1이 되고 errno를 EAGAIN으로 설정한다.

       일반적으로 메시지를 받는 호출들은 요구된 양을 모두 채우며 기다리기 보다는 채워진 양을

       리턴한다.

 

       select(2) 나 poll(2) 호출은 데이터가 더 도착하였는지를 결정하기 위해 사용된다.

 

       받는 함수들을 위한 flags인자는 다음 값들 중 하나 이상의 OR로 구성된다.

 

       MSG_00B

이 플래그는 일반적 데이터 스트림에서 받지 않는 out-of-band 데이터를 요구한다. 몇 몇

프로토콜은 보통 데이터 큐의 머리에 급한 데이터를 놓는다. 그리고 이 플래그는 그런 프로토콜에서는 사용될 수 없다

       MSG_PEEK

이 플르개는 큐에서 데이터를 제거하지 않고 받는 큐의 시작에서부터 데이터를 반환하는

받기 작동을 하도록한다. 그래서, 연속적인 받기 호출은 같은 데이터를 반환한다.

       MSG_WAITALL

       MSG_TRUNC

       MSG_ERRQUEUE

 

나머지는 다음에 정리...

 

 

send

이름

send, sendto, sendmsg - 소켓으로 부터의 메시지를 보낸다.

사용법

       #include <sys/types.h>
       #include <sys/socket.h>

       ssize_t send(int s, const void *buf, size_t len, int flags);
       ssize_t sendto(int s, const void *buf, size_t len, int flags, 

                            const struct sockaddr *to, socklen_t tolen);
       ssize_t sendmsg(int s, const struct msghdr *msg, int flags);

설명

send, snedto, 그리고 sendmsg는 다른 소켓으로 메시지를 보내는데 사용된다. send는 소켓이 connected 상태에 있을 때 사용된다. 반면 sendto와 sendmsg는 언제든 사용할 수 잇다.

목표의 주소는 to가 그것의 크기를 정하는 tolen과 함께 주언진다. 메시지의 길이는 len. 으로 주어진다. 메시지가 너무 길어서 기초적인 프로토콜을 사용해 자동으로 넘어갈 수 없다면, 에러 EMSGSIZE가 반환되고, 메시지는 전해지지 않는다.

send. 에는 전달을 실패할 징후는 없다. 국부적으로 지적되는 에러는 -1 의 반환값에 의해 지적된다.

메시지가 소켓의 send 버퍼에 맞지 않으면, send 는 소켓이 non-blocking I/O mode에 있지 않는다면 일반적으로 막는다 non-blocking mode에서 이런 경우엔, EAGAIN을 반환한다. select(2) 호출은 언제 다음 자료를 보낼지를 결정하는데 쓰인다

flags 매개 변수는 flagword이고, 아래 flag를 가질 수 있다:

       MSG_00B

       MSG_DONTROUTE

       MSG_DONTWAIT

       MSG_NOSIGNAL

.....

 

 

 

read

이름

read - 파일기술자(file descriptor)를 통해서 읽어들인다.

사용법

#include <unistd.h>

 

ssize_t read(int fd, void *buf, size_t count);

설명

read()는 파일 기술자 fd에서 buf로 시작하는 버퍼에 count 바이트까지 읽기를 시도한다.

 

만일 count가 0이라면 read()는 0을 반환하며 다른 결과는 가지지 않는다. 만일 count가 SSIZE_MAX보다 크다면, 결과는 예측할 수 없다

 

반환값

성공시, 읽은 바이트 수를 반환하며(0은 파일의 끝을 나타낸다.) 파일 포인터의 위치는 읽은만큼 이동된다. 만일 이 수가 요구된 바이트의 수보다 작더라도 에러는 아니다; 이것은 실제로 즉지 이용할 수 있는 바이트가 거의 없기 때문이거나(아마도 이것은 파일의 끝이어서 닫았거나 파이프나 단말기에서 읽기 때문이다.) read()가 어떤 신호에 의해 인터럽트가 되었기 때문이다.

 

에러시, -1을 리턴하며 errno는 적당한 값으로 설정된다. 이 경우 파일 포인터의 위치가 바뀔지 어떨지는 예측할 수 없다.

에러

EINTR    어떤 데이터를 읽기도 전에 함수가 신호에 의해 인터럽트 되었다.

EAGAIN 넌 블로킹 I/O가 O_NONBLOCK을 사용하여 선택되어 졌고 즉시 읽을 수 있는

  데이터가 없다.

 

EIO       I/O에러, 이것은 백그라운드 프로세스 그룹에 이쓴 프로세스가 제어되는 tty 단말기에

  서 읽기를 시도할 때, 그리고 이것이무시ㄱ되거나 봉쇄되는 SIGTTIN이거나 또는 프로

  세스 그룹이 고아일때 일어난다. 또한 디스크나 테이프에서 읽는동안 저레벨 (low-

  level) I/O에러가 있을 때 일어난다.

 

EISDIR   fd가 디렉토리를 가리킨다.

EBADF   fd가 유효한 파일 기술자가 아니거나읽기 위해 열려지지 않았다.

EINVAL  fd가 읽기에 적당하지 않는 객체와 연결되었다.

EFAULT buf는 접근할 수 없는 주소공간을 가리키고 있다.

 

fd에 접속된 객체에 의존하여 다른 에러가 일어날 수 있다. POSIX는 데이터 일부를 읽은 후 인터럽트 되었을 경우 read가 -1이나 (errno는 EINTR로 설정된다.) 이미 읽은 바이트의 수를 리턴하도록 허용한다.

 

 

 

write

이름

write - 파일 기술자가 가리키는 파일에 쓴다.

사용법

#include <unistd.h>

ssize_t write(int fd, const void *buf, size_t count);

설명

write는 buf로 시작하는 버퍼에서 파일 기술자 fd로 참조되는 파일에 count 바이트까지를 쓴다. POSIX는 write()가 반환된 후 새로운 데이터가 반환될 수 있다는 것을 증명하도록 read()를 요구한다. 모든 파일 시스템이 POSIX를 따르지는 않는다.

반환값

성공 시, 쓰여진 바이트 수를 반환한다(0은 쓰여진 것이 없음을 나타낸다.) 에러라면, -1을 반환하며 errno는 적당한 값으로 설정된다. 만일 count가 0이고 파일 기술자가 정규 파일을 가리킨다면 0은 다른 결과를 야기시키지 않고 반환된다. 특수 파일에서의 결과는 호환되지 않는다.

에러

EINTR 어떤 데이터를 읽기도 전에 함수가 신호에 의해 인터럽트 되었다.

EAGAIN 넌 블로킹 I/O가 O_NONBLOCK을 사용하여 선택되어 졌고 즉시 읽을 수 있는

데이터가 없다.

EIO I/O에러, 이것은 백그라운드 프로세스 그룹에 이쓴 프로세스가 제어되는 tty 단말기에

서 읽기를 시도할 때, 그리고 이것이무시 되거나 봉쇄되는 SIGTTIN이거나 또는 프로

세스 그룹이 고아일때 일어난다. 또한 디스크나 테이프에서 읽는동안 저레벨 (low-

level) I/O에러가 있을 때 일어난다.

EISDIR fd가 디렉토리를 가리킨다.

EBADF fd가 유효한 파일 기술자가 아니거나읽기 위해 열려지지 않았다.

EINVAL fd가 읽기에 적당하지 않는 객체와 연결되었다.

EFAULT buf는 접근할 수 없는 주소공간을 가리키고 있다.

fd에 접속된 객체에 의존하여 다른 에러가 일어날 수 있다. POSIX는 데이터 일부를 읽은 후 인터럽트 되었을 경우 read가 -1이나 (errno는 EINTR로 설정된다.) 이미 읽은 바이트의 수를 리턴하도록 허용한다.



끝끝~



반응형

'c&c++' 카테고리의 다른 글

WSAGetLastError() 에러코드 번역.  (2) 2017.08.08
[메모장]IOCP [펌]  (0) 2017.07.12
C/C++ byte[] to string 변환(cast)  (0) 2017.07.04
stl를 이용한 MultiMap 사용  (0) 2017.07.03
[펌]C/C++ pragma대해서  (2) 2017.07.01