버그 해결을 위한 모든 질문을 던져
+1 vote
153 views

안녕하세요 서버 프로그래밍을 공부하고 있는 학생입니다! 

기본적인 윈속함수 (recv, send, accept) 호출시 Blocking 소켓과 Non-Blocking 소켓의 동작방식에 혼란이 생겨서 질문드립니다!

일단 MSDN과 각종 서적을 통해 제가 이해한 바에 따르면 다음과 같이 정리해 볼 수 있을 것 같습니다.

(여기계신분들 모두 알고 계신 내용이실테지만 저의 이해를 검증받기 위해서 첨부했습니다.

제가 잘못 이해한 부분이 있다면, 피드백주시면 감사하겠습니다.)

해당 내용을 정리하다가 제가 혼란이 생긴 부분은 다음과 같습니다.

너무 이상한 질문을 한다고 생각 하실 수도 있지만 어디 속시원하게 적혀있는 곳이 없어서 질문을 올리게 되었습니다.

만약 윈속 함수 호출 이전에 이미 리턴할 조건이 만족되어 있던 상태라면 해당 함수는 작업을 처리하고 바로 리턴하는가?

예를들어

1. recv함수 호출 이전에 이미 소켓 수신버퍼에 데이터가 도착해 있는 상태이다.


2. recv 함수를 호출한다. 

3. 소켓의 모드와 상관없이 이미 함수 리턴 조건을 충족했기 때문에 소켓 수신버퍼에 현재 들어와있는 데이터를 응용 프로그램 버퍼로 메모리 카피만 수행하고 바로 리턴하여 해당 스레드는 block 상태로 빠지지 않고 지속적으로 running 상태를 유지한다.

위와 같은 경우가 성립하는지가 궁금합니다.

혹은 다음과 같은 질문과도 일맥상통합니다.

- Select, WSAAsyncSelect, WSAEventSelect 등의 소켓 입출력 모델을 사용하여 반응이 있는 소켓들을 대상으로 윈속 함수를 호출하면 이미 해당 소켓에 대해서는 함수 리턴조건이 충족되어 있는 상태이기 때문에 메모리 카피만 일어나고 block이 되지 않는가?

- Non-Blocking 소켓은 문자그대로 절대 block 되지 않는가? 

( block이 될 상황이면 WSAEWOULDBLOCK을 리턴하고 리턴 조건이 충족된 상황이면 작업을 처리하고 바로 리턴하기 때문에?)

MSDN에 있는 remark를 참고해보면 

https://docs.microsoft.com/en-us/windows/desktop/api/winsock/nf-winsock-recv

 

If no incoming data is available at the socket, the recv call blocks and waits for data to arrive according to the blocking rules defined for WSARecv with the MSG_PARTIAL flag not set unless the socket is nonblocking. In this case, a value of SOCKET_ERROR is returned with the error code set to WSAEWOULDBLOCK. The selectWSAAsyncSelect, orWSAEventSelect functions can be used to determine when more data arrives.

 

다음과 같이 되어있는데, 저 설명에 의하면 incoming data가 이미 소켓 수신버퍼에 도착해있는 상태라면 스레드가 block되지 않는다고 해석해도 무방할까요?

 

혹시 다른 레퍼런스를 통해서 답을 얻을 수 있을까 싶어 구글링을 해보았는데, 스택 오버 플로우에서 버클리 소켓에 대해서는 다음과 같이 적혀 있는 것을 발견했습니다. 신뢰할 수 있는 정보인지는 불투명합니다.

https://stackoverflow.com/questions/5407182/blocking-sockets-when-exactly-does-send-return

Does this mean that the send() call will always return immediately if there is room in the kernel send buffer?

Yes. As long as immediately means after the memory you provided it has been copied to the kernel's buffer. Which, in some edge cases, may not be so immediate. For instance if the pointer you pass in triggers a page fault that needs to pull the buffer in from either a memory mapped file or the swap, that would add significant delay to the call returning.

이 설명에 따르면 blocking 소켓이라도 send 함수 호출시 소켓 송신 버퍼에 공간이 충분하다면 버퍼로 메모리 복사이후 block되지 않고 즉시 리턴되는 것 같은데 윈속에도 해당되는 내용일까요?

고수분들의 속시원한 답변으로 저의 답답함이 해소될 수 있기를 기원해 봅니다 ㅠㅠ 질문 읽어주셔서 감사합니다.

새해복 많이받으세요!

 

asked (19 point)
수정됨 , 153 views

1 답변

+1 vote
우수 답변

소켓 프로그래밍을 글로만 배우고 계신것은 아닐까 하는 아쉬움이 있습니다. 지금 질문주신 모든 내용들은 간단한 코딩 만으로도 바로 검증 , 확인이 가능한 내용들 입니다.

정리하여 올려주신 표의 내용은 정확하게 잘 파악 하셨습니다.  모두 맞습니다.

 

그리고 질문의 답변으로는

만약 윈속 함수 호출 이전에 이미 리턴할 조건이 만족되어 있던 상태라면 해당 함수는 작업을 처리하고 바로 리턴하는가?

네. 맞습니다.  이는 위에 표로 정리하신 내용과 일치하는 부분 입니다.

 

추가질문 select, AsyncSelect 등... 에 대해서,

select 모델을 제외한 WSAAsyncSelect , EventSelect ,비동기 입출력 등등은 블록킹 소켓을 사용하지 않습니다.. WSAAsyncSelect 에 등록하는 순간 자동으로 논블록소켓으로 전환 됩니다. 이는WSAAsyncSelect, WSAEventSelect 함수 설명을 살펴보시면 나오는 내용 입니다.  소켓 함수로 해당 스레드가 블록 될 경우 윈도우 메시지 처리에 문제가 생길 수 있기 때문에 블록킹소켓을 허용하지 않습니다.


마지막 질문에

이 설명에 따르면 blocking 소켓이라도 send 함수 호출시 소켓 송신 버퍼에 공간이 충분하다면 버퍼로 메모리 복사이후 block되지 않고 즉시 리턴되는 것 같은데 윈속에도 해당되는 내용일까요?

계속 같은 내용을 질문 하고 계시는데요,  맞습니다. 

코드 몇줄만 쳐서 테스트 해보시면 직접 확인이 가능하오니  문서로만 익히시기 보다는 실제 코드로 돌려보시길 권장 합니다.

 

화이팅 입니다.

answered (221 point)
선택됨
질문들을 다시 읽어보니 중언부언하는 내용이 많았네요 ㅠㅠ

말씀해주신대로 설명들을 찬찬히 곱씹어보면서 코드로 쳐보면 되는 내용이었던 것 같습니다.

답변과 조언 감사드립니다.

버그 해결을 위해 도움을 구하고, 도움을 주세요. 우리는 그렇게 발전합니다.

throw bug 는 프로그래밍에 대한 전분야를 다룹니다. 질문,논의거리,팁,정보공유 모든 것이 가능합니다. 프로그래밍과 관련이 없는 내용은 환영받지 못합니다.

96 질문
186 answers
194 댓글
211 users