작성
·
554
0
wsasend가 멀티쓰레드환경을 보장하지 않아 lock을 걸어준다고 하셨는데 어떤부분을 보장하지 않는 건가요?
버퍼문제라면 혹시 이번 수업의 코드는 임시로 event마다 독립적인 버퍼를 가지게 했으니 lock을 안걸어주어도 되나요?
wsarecv 는 멀티쓰레드환경에서 문제가 발생하지 않나요?
답변 1
0
앞으로 API 관한 부분은 늘 궁금함이 생기실텐데
항상 정답은 MSDN이나 구글에 있다고 보셔야 합니다.
https://social.msdn.microsoft.com/Forums/en-US/1f85557c-15f6-42b3-a8f7-1630b4099bb6/wsasend-from-multiple-thread-safe?forum=vcgeneral
recv에서 락을 안 건 이유는, 애당초 RegisterRecv를 딱 1개만 걸어줬기 때문입니다.
따라서 2 쓰레드가 동시에 WSARECV를 호출할 경우의 수가 나오지 않습니다.
반면 Send는 밖에서 신나게 원하는 타이밍에 호출할 수 있어서 상황이 다릅니다.
ClientServiceRef service = MakeShared<ClientService>(
NetAddress(L"127.0.0.1", 7777),
MakeShared<IocpCore>(),
MakeShared<ServerSession>, // TODO : SessionManager 등
1);
이부분에서 마지막인자를 1로 설정했기 때문이라는 말씀이신거죠?
이렇게 하면 실질적으로 한명의 유저만이 서버에 접속하게 되는 것이어서 lock을 안 걸어준 것이라고 이해하면 될까요?
아뇨 그 부분은 아닙니다. 동접이 5천명이라 하더라도,
한 유저에 대해서는 Recv를 한 번에 1번만 호출해주게 될 것이라는게 핵심입니다.
현재 구조에서 RegisterRecv -> ProcessRecv -> RegisterRecv -> ProcessRecv
이렇게 계속 왔다 갔다 하면서 패킷 수신이 이루어지고 있는데요.
이 부분은 제가 강의에서 낚시대에 비유를 많이 하곤 합니다.
낚시대가 유저마다 딱 1개만 있고, 이 낚시대를 바다에 던져서 물고기를 잡고,
물고기를 끌어올리고 다시 낚시대를 바다에 던지는 행동을 반복하겠죠.
RegisterRecv가 멀티쓰레드 환경에서 돌아간다고는 하나,
어차피 동일한 세션에 대해 RegisterRecv가 동시에 두 번 호출될 수 없습니다.
따라서 굳이 Recv할 때 락을 걸어줄 필요가 없는 것입니다.
Send는 외부에서 원할 때 호출할 수 있으니,
별도 안전 처리를 하지 않으면 여러번 호출될 수 있습니다.
따라서 락을 걸던, 이전 애가 보낼 동안에는
데이터를 보내지 않는 등 무엇이든 좋으니 보호를 해줄 필요가 있습니다.
https://stackoverflow.com/questions/28770789/is-calling-wsasend-and-wsarecv-from-two-threads-safe-when-using-iocp
여기서 보면 wsarecv도 멀티쓰레드환경에서 사용하면 위험하다고 하는데 수업코드에서는 recv할때는 lock이 안 결려있어서 질문드립니다