본문 바로가기

UNIX_LINUX_C_C++

TCP/IP 에서 Blocking socket vs. Nonblocking socket

출처 : http://stoneshim.tistory.com/35

2003년 9월 예전 블로그에 남겼던 글을 옮긴다.

* Blocking Socket
-. socket() 으로 생성되는 socket은 기본값으로 blocking socket 임.
-. block 될 수 있는 system call 호출 시 block 될 수 있음.

* Nonblocking Socket
-. 이미 생성된 socket 을 fcntl() 을 사용하여 nonblocking socket으로 변경 가능.
-. system call 사용시 block 되는 상황이면 -1 리턴하며 errno가 EWOULDBLOCK 또는 EAGAIN으로 설정됨.

* Nonblocking socket 으로 만드는 방법.
-. fcntl(2) 사용
int flag;
flag = fcntl( sock_fd, F_GETFL, 0 );
fcntl( sock_fd, F_SETFL, flag | O_NONBLOCK );

* Blocking Socket vs Nonblocking Socket
B( Blocking Socket ), N( Nonblocking Socket )
-. read
-. B : read 버퍼가 비어있을때 block
-. N : read 버퍼가 비어있을때 -1 return, errno==EWOULDBLOCK/EAGAIN
**. Blocking socket의 경우에 read 버퍼에 존재하는 데이터의 크기가 read시 요청한 데이터의 크기보다 작은 경우라도 read 버퍼에 존재하는 데이터만큼 리턴되며 block 되지 않음.

-. write
-. B : write 버퍼가 꽉 차있을때 block
-. N : write 버퍼가 꽉 차있을때 -1 return, errno==EWOULDBLOCK/EAGAIN

-. accept
-. B : backlog( 현재의 connection 요청 큐 )가 비어있을때 block
-. N : backlog( 현재의 connection 요청 큐 )가 비어있을때 -1 return, errno==EWOULDBLOCK/EAGAIN

-. connect
-. B : connection이 완전히 이루어질때까지 block
-. N : connection이 완전히 이루어지 않더라도 곧바로 return. 나중에 getsockopt로 connection이 완전히 이루어졌는지 확인가능.

* select/poll과 함께 사용하면 blocking socket도 괜찮지 않나? 라는 생각에 대해서...
-. bocking socket의 경우라도 동일 process만이 select나 poll등을 사용하여 readable/writable임을 확인한 후 곧바로 read/write를 호출하면 block 될수 없다.
-. 이러한 경우에도 nonblocking socket을 선호하는 이유는 select/poll 로 event를 확인 한 후에 read/write를 (EWOULDBLOCK이 될때까지)looping으로 처리할 수 있기 때문이다.
-. accept의 경우에도 nonblocking socket을 사용하면 listenFD가 readable한 경우 accept를 계속 호출하여 backlog가 완전히 빌때까지 connection 요청을 수용할 수 있으며, 이러한 방식의 accepting 이 훨씬 효율적이다. - 이는 read/write의 경우에도 마찬가지이다.