ZeroByteRecv 와 PageLocking 을 관련해서 이해가 안가서 인터넷을 뒤적뒤적 거렸다.
내가 이해한 바로는
우리가 처음 관리하고 있는 소켓 풀들에 대하여 WSARecv 로 비동기 대기를 하게 되는데
이상태에서
WSABUF wsaBuf;
wsaBuf.buf = buf;
wsaBuf.len = 100;
WSARecv(sock, &wsabuf, len ,...);
해서 소켓 풀들에 대해서 메모리를 잡고 있는 상태가 된다.
하지만 많은 소켓들에 대해서 아직 데이터를 받은 상태가 아닌데 이렇게 버퍼를 잡고 있으면
Page에 대해 메모리를 잡고 있게 되며 그 영역에 대해 Lock을 건다.
쓰지 않는 메모리를 잡고 있다가 나중에 운영체제 상에서 다른 작업들에 의해 page교환이 이루어지고
page교환이 이루어 진 뒤에 WSARecv 로 socket 들로 부터 작업을 받는 다면
page교환하는데 작업상 능률 저하 또는 오류가 발생 할 수 있다는 것이다.
때문에
WSABuf wsaBuf;
wsaBuf.buf = nullptr;
wsaBuf.len = 0;
으로 설정해서 WSARecv 를 하게 된다면 메모리를 잡지 않고서도 다른 소켓들에 대해 작업을 받아들이는 것을 할 수 있다는 것이다.
즉 zeroByte Recv 로 작업을 들어온 것을 알게되면 그 때 다시 적당한 크기의 버퍼로 WSARecv 를 호출해서 데이터를 읽어 들이는 것이다.
(0 Byte 로 설정해놨을때 데이터가 들어온다고해서 WSABUf와 연결된 버퍼의 데이터가 사라지는 것은 아니다.)
이렇게 ZeroByte 기법을 쓰고자 적용할때 문제점은 0바이트로 들어올떄의 처리이다.
다른 블로그글을 찾아봤는데 클라이언트에서 closesocket을 하거나 shutdown을 하면 GQCS에서는 오류가 안나고 0 바이트가 들어온 것으로 인식이 되기 때문에 이것을 잘 구분 해서 처리해 줘야 된다고 작성해놨었는데..
로즈서버로 돌려봤을때 0바이트로 받아지는 경우는 애초에 처음 AcceptEx로 받았을때 이외엔 나오지 않았다 (closesocket으로 했을때 0 바이트가 나오지 않음.)
AcceptEx할때 accept 와 동시에 바이트를 받을 수 있는데 그 바이트 설정을 0 으로 해놔서 그런것 같다.