ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • iocp 송신 관련 주의점
    프로그래밍/의문 2016. 1. 26. 17:58
    반응형

    http://www.gpgstudy.com/forum/viewtopic.php?p=43020


    질문


    IOCP에서 Recv 할 때는 당연히 버퍼(큐)를 만들어서 저장 후 패킷 처리를 하고 있습니다. 
    그런데, Send 할 때는 어플리케이션 레벨의 별도의 버퍼를 궂이 만들 필요가 있는지 궁금합니다. 
    다시 말해서, 
    Q1. 소켓 옵션으로 설정해 준 크기 만큼의 버퍼만이 IOCP에서 관리되는 것인지? 
    Q2. 그래서, 아주 많은 Send 오퍼레이션이 요청될 경우, 버퍼 오버플로우로 Send가 실패할 수도 있는지? 
    (WSASend()를 콜(비동기) 할 때, 패킷 데이터를 소켓 버퍼로 즉시 메모리 카피 해버리는지.. 
    그래서 카피에 실패하면 전송 실패를 리턴하는지..) 

    Q2 같은 경우, 전송 실패가 리턴되지 않는다면, Send를 위한 별도의 버퍼를 만드는 것은 
    패킷 데이터의 메모리 카피를 쓸데없이 한 번 더 하게 만드는 꼴인것 같아서요..


    +


    가령 예를 들면, 실제 서비스 되는 상황에서 
    1024바이트 크기의 패킷을 한 유저에게 연속해서 1천번을 전송한다고 하면, 
    (TCP/IP를 자체 헤더 크기를 제외하고라도 데이터의 크기가 
    1M 정도로 소켓 자체의 송신 버퍼보다는 큰 데이터가 되어버린다고 가정합니다.) 
    다시 말해서 WSASend(1024바이트 크기의 패킷)를 연속으로 1천번 콜 했을 때(물론 그 이상도..) 
    과연 에러가 리턴 되느냐/되지 않느냐를 질문한 겁니다. 


    답변들

    0) IOCP를 사용해서 Send를 할때는 위와 같은 경우 에러가 리턴되지 않습니다. 

    물론 중간에 소켓이 끊어지거나 한다면 에러가 리턴됩니다. 

    하지만 IOCP를 이용한 WSASend에서 문제가 되는 것은 WSASend에서 지정한 크기 보다 작은 크기를 보낼 수 있다는 것입니다. 
    이때는 에러 상황으로 오는 것이아니라 GetQueuedCompletionStatus에서는 정상 상태에 대한 리턴을 주는 대신 lpNumberOfBytes 가 원래 지정한 값보다 작은 값으로 옮니다. 
    그렇기 때문에 하나의 소켓에 대해서 위와 같이 쭉 밀어 넣어 버리게 되면 뭔가 중간에 원하는 데이터가 빠져서 전송될 수 있습니다.

    즉 IOCP를 사용할 때 가장 주의해야 할 점이 하나의 소켓에 여러개의 WSARecv나 WSASend가 걸리는 것을 방지해야 한다는 것 입니다. 
    자세한 내용은 다음 URL을 참조하세요 (http://www.codeproject.com/internet/reusablesocketserver4.asp)


    1) 요 문제는 계속 논란이 되던 부분인데요. 제가 IOCP를 약 4년째 사용해봤는데요.. 수많은 부하테스트에서도 WSASend에서 지정한 크기 보다 작은 크기가 보내졌던 경우는 단 한번도 없었습니다. 어디까지나 제 경험상의 얘기입니다. 


    그리고.. "IOCP에서 하나의 소켓에 여러개의 WSARecv나 WSASend가 걸리는 것"에 대한 이슈도.. 저도 첨에는 하나의 세션은 한번의 WSASend를 요청하는식으로 구현했었는데요. 한 세션에 대해서는 너무나도 효율이 떨어졌습니다. 그래서 완료통지 무시하고.. 무조건 WSASend를 요청하는 식으로 테스트 해봤는데 잘되더군요. 너무 많은 WSASend를 요청하면 Non-paaged pool이 모두 소모되서 세션에 심각한 문제가 생기긴 했습니다. 
    이것도 제 경험의 얘기입니다.



    요약. 


    송신 시 못 보내는 경우는 거의 없으나, 지정한 값보다 작은 값을 보낼 수도 있으므로 버퍼를 계속 간직해야 함.

    한 번에 WSASend가 여러개 걸리면 곤란할 수 있음(답변1)

    반응형
Designed by Tistory.