http://blog.naver.com/msd102/150010804209
네트워크 함수의 Blocking/Non Blocking I/O 동작
|
어찌보면 당연한 건데, 오해를 갖기 쉬운 "네트워크 함수의 Blocking/Non Blocking I/O" 동작들을 정리해 보았습니다.
1. 입력함수: read, readv, recv, recvfrom, recvmsg
Blocking TCP 소켓인 경우, 소켓수신버퍼에 수신된 데이터가 없으면, 프로세스는 sleep한다. 데이터가 도착하면 (그것이 충분한 크기가 아닐지라도) 프로세스는 깨어난다. 원하는 크기만큼 도착할때까지 기다리려면, while로 계속 받아 붙이던가, 아니면, MSG_WAITALL 플래그를 이용한다.
UDP 소켓인 경우, 소켓수신버퍼가 비어 있으면, 프로세스는 sleep한다. UDP패킷이 도착하면, 프로세스는 깨어난다.
Nonblocking 소켓의 경우, 수신버퍼가 비어 있는 경우, 에러 EWOULDBLOCK 으로 바로 리턴한다.
2. 출력함수: write, writev, send, sendto, sendmsg
Blocking TCP 소켓의 경우, 출력함수는 어플리케이션의 데이터를 커널의 소켓전송버퍼에 복사한다. 만약 소켓전송버퍼에 공간이 없으면, 프로세스는 sleep한다.
Nonblocking TCP 소켓의 경우, 소켓전송버퍼에 공간이 없는 경우, 에러 EWOULDBLOCK으로 바로 리턴한다. 만약 소켓전송버퍼에 약간의 공간이 있는 경우, 복사가능한 공간을 바이트로 리턴한다.
UDP소켓은 실제로 소켓 전송 버퍼가 없다. 즉, 호출 즉시 UDP/IP스택으로 전달하므로, block되지 않는다.
3. accept 함수
Blocking 소켓인 경우, 새로운 연결이 없으면, 프로세스는 sleep한다.
Nonblocking 소켓의 경우, 새로운 연결이 없으면, 에러 EWOULDBLOCK으로 리턴한다.
4. connect 함수
Blocking TCP 소켓의 경우, 실제 연결이 될 때까지, 즉 SYN에 대한 ACK을 받을때까지 block되어 있는다.
NonBlocking TCP 소켓의 경우, 에러 EINPROGRESS로 리턴한다. (같은 호스트의 경우에는 바로 정상 연결이 이루어 질 수 있다)
UDP 소켓의 경우 connect는 가상의 연결을 만드는 것이라서 바로 리턴한다.
(참고: UNIX Network Programming, vol.1, 2nd edition, Ch.15)
5. close() 에 대한 것은 엮인글 참고..
(햄릿님께서 링크해주신 html파일을 첨부하였습니다. 감사합니다.)
-----------------------------------------------------------------------------------------
1. Connect 관련 Test
정상적인 경우의 Connect
내용 |
정상적으로 Connect가 이루어지는 경우, Connect 호출 후, 접속 완료까지 소요되는 시간 |
방법 |
Connect 호출 전, 호출 후의 시간을 측정하여 표시한다. |
결과 |
호출 전 시간과 호출 호의 시간이 동일하게 표시됨 Window의 Timer의 유효치 이내의 시간으로 접속 |
결과분석 |
|
Server Process가 없는 경우의 Connect
내용 |
연결할 IP에 대한 Computer가 켜져 있으나, Server Process가 없는 경우, Connect Fail의 형태 |
방법 |
Server Process를 실행하지 않고 Connect 시도 |
결과 |
약 1, 2초 후에 Connect Fail 발생 |
결과분석 |
연결할 Computer에서 Bind된 Port가 없음을 알 수 있으므로 Timeout은 발생하지 않고, 일정 시간내에 Connect Fail이 발생함 |
연결대상 Computer가 없는 경우의 Connect
내용 |
연결할 IP에 대한 Computer가 존재하지 않거나 꺼져 있는 경우, Connect Fail의 형태 |
방법 |
없는 IP에 대한 Connect 시도 |
결과 |
20여초 후에 Connect Fail 발생 |
결과분석 |
Timeout 될 때까지 IP를 찾음 |
2. Send/Receive 관련 Test
Network Cable을 제거한 즉시 Send
내용 |
Network Cable을 제거한 즉시 Send를 하는 경우에 대한 결과 |
방법 |
Socket 연결 후, Network Cable을 제거한 즉시 Send 시킴 |
결과 |
Send가 성공함
[Non Blocking Mode] Socket Close 메시지가 발생할 때까지 성공 [Blocking Mode] Socket Close 메시지가 발생할 때까지 첫 Send는 성공, 두번째부터는 실패함
연결이 끊긴 것을 감지할 때까지는 성공함 약 7초 정도가 지난 후, 연결 끊김을 감지함 상대방의 Network Cable을 제거하였을 경우에는 약 3분 정도의 시간이 지난 후, 연결 끊김을 감지함 |
결과분석 |
Network Cable을 제거하더라도 한동안 Process는 그것을 인식하지 못함 Send는 TCP/IP 하부 레벨에 데이터 전송이 처리되면 성공으로 간주하는 것으로 판단됨 |
Network Cable을 제거한 즉시 다시 연결 후 Send
내용 |
Network Cable을 제거한 즉시, 다시 Cable을 연결하여 Send 성공여부를 Test Receive 측 Data Receive 성공여부도 함께 Test |
방법 |
Network Cable을 제거 후, Close를 감지하기 전에 다시 연결하여 Send, Receive의 성공여부를 Test함 |
결과 |
Send, Receive 모두 성공 |
결과분석 |
Close를 감지하기 전에 다시 Cable을 연결하면, 연결은 유지됨 |
Network Cable을 제거 후, 다시 연결하는 시간을 변화하여 Send
내용 |
Network Cable 제거 후, 다시 연결하는 시간을 변화시켜 위의 Test를 반복하여 성공 여부를 확인 |
방법 |
Network Cable 제거 후, 다시 연결하는 시간을 변화시켜 위의 Test를 반복하여 성공 여부를 확인 |
결과 |
Close를 감지하기 전에 다시 연결하면 Send, Receive 모두 성공 |
결과분석 |
|
Send 후, Receive를 호출하지 않은 경우
내용 |
Data를 Send하고 Receive 측에서 Receive 함수를 호출하지 않는 경우, Timeout 발생 여부와 Timeout 발생시간을 확인 |
방법 |
Data를 Send하고 Receive측에서 Receive 함수를 호출하지 않음 |
결과 |
Timeout이 발생하지 않음 |
결과분석 |
|
Send, Receive Message 발생 수 – 소규모 데이터
내용 |
비교적 작은 크기의 데이터(수십 byte 내외)를 아주 빠르게 Send를 여러 번 호출하는 경우, Receive 측에 Receive Message의 발생과 실제 Receive한 Data의 크기를 확인 - Send 수와 Receive Message 발생 수를 비교 검사 - Send한 Data 크기와 Receive한 Data 크기 비교 - Receive 시에 실제 Send한 Data보다 수배의 크기의 Buffer로 Receive한 경우와 Send한 Data의 크기와 동일한 크기의 Buffer로 Receive하는 경우의 비교 |
방법 |
100 Byte 크기의 Data를 10번 Send함 |
결과 |
Receive Buffer 크기가 1024 byte인 경우 - Receive Message 2번 발생 - 첫 번째는 100 byte를, 두 번째는 900 byte를 Receive 함 Receive Buffer 크기가 100 byte인 경우 - Receive Message는 10번 발생 - 모두 100 byte 씩 Receive함 |
결과분석 |
작은 크기의 데이터를 빠르게 연속적으로 전송하는 경우, Network 하부 Layer에서 몇 개의 데이터를 묶어서 한꺼번에 전송하게 된다. 따라서 Send한 Data와 실제 전송되는 Data 크기는 달라질 수 있으며, Send한 수와 Receive Message의 발생 또한 다를 가능성이 있다. 하지만 두 번째 Test 결과로 봤을 때, Socket의 내부적인 Buffer에서 Receive Buffer로 Data를 읽어 들일 때, 내부 Buffer를 모두 비울 때까지 Receive Message를 자체적으로 발생시키는 것으로 예상된다. |
Send, Receive Message 발생 수 – 대규모 데이터
내용 |
비교적 큰 크기의 데이터(수십 Kbyte 이상)를 Send 하는 경우, Receive 측에 Receive Message의 발생과 실제 Receive한 Data의 크기를 확인 |
방법 |
다양한 크기의 Data를 10번 Send 함 |
결과 |
- 50Kbyte 크기의 Data일 경우, Receive Message 33번 발생. 한번에 약 1.7Kbyte 수신 - 10Kbyte 크기의 Data일 경우, Receive Message 14번 발생. 한번에 받는 양이 일정하지 않음 - 100Kbyte 크기의 Data일 경우, Receive Message 63번 발생. 한번에 약 17Kbyte 수신 |
결과분석 |
한번에 큰 크기의 데이터를 Send하는 경우, Receive 측에서 Receive Message가 발생한 시점에 모든 데이터가 전송되지 않는다. 따라서 Receive Message 발생 시점에 Receive 함수를 호출하면 호출 시점까지 전송된 데이터만을 읽어 들이게 된다. 그 이후 전송되는 데이터들은 별도의 Message가 다시 발생하며, 모든 데이터가 Receive될 때까지 Receive Message가 발생한다. 따라서 대용량 Data를 Receive하는 경우에는 데이터의 길이에 대한 정보를 미리 받아서 그 데이터가 모두 도착 할 때까지 읽도록 하여야 완전한 데이터를 수신할 수 있다. Receive Message의 발생은 Receive Buffer의 크기와 한번의 Receive Message에 대해서 호출되는 Receive 함수의 수에 따라 그 발생 횟수는 달라질 수 있다. |
3. Close 관련 Test
Close Message 발생 Test
내용 |
각 상황에 따른 Close Message의 발생여부 검사 - Process를 비정상적으로 강제 Kill 시킨 경우 - Computer의 전원이 꺼진 경우 - Network Cable을 제거한 경우 - Network Cable을 제거한 후 다시 연결하고 접속을 해제하는 경우 - Network Cable을 제거한 후 Prcess를 종료하고 다시 Cable을 연결하는 경우 |
방법 |
|
결과 |
- 작업관리자에서 Process를 종료하였을 경우 Close Message 발생함 - Network Cable을 제거한 경우 자신의 Cable 제거시 7초정도, 상대방 Cable 제거시 3분 정도 후에 Cloase Message 발생 - Network Cable 제거 후 Close Message가 발생하기 전에 다시 연결하여 접속을 해제하는 경우, 정상적으로 Close Message 발생 - Network Cable을 제거한 후 Process를 종료하고 다시 Cable을 연결하는 경우, Close Message 발생하지 않음 |
결과분석 |
|
[출처] 네트워크 함수의 Blocking/Non Blocking I/O 동작|작성자 msd102