• 카테고리

    질문 & 답변
  • 세부 분야

    게임 프로그래밍

  • 해결 여부

    미해결

listenSocket.AcceptAsync 와 내부에서생성되는 스레드에 대하여..

22.12.23 16:41 작성 22.12.23 16:43 수정 조회수 315

0

질문이 https://inflearn.com/questions/238421
이 질문과 유사한 질문이긴 한단계 더 들어가보자면..

만약에
bool pending = _listenSocket.AcceptAsync(args); 이 구문이 실행 될때

동시에 여러 클라이언트에서 접속이 이뤄지면

AcceptAsync 가 두번 실행 되면서
내부적으로 스레드 두개가 돌아가는것 같은데
(ex: AcceptAsync 가 한번 실행되고 완료 되지 않은 상태에서 곧바로 다시 AcceptAsync 가 호출 되는 경우)

이렇게 되면 OnAcceptCompleted 함수가 멀티스레드 로 두개의 Completed 를 두개 실행한 것 처럼 두개의 함수가 동시에 돌아가게 되는것 아닌가요?
(즉 동기화 처리가 필요해지는 상태)

이렇게 되면 순서적으로 처리 되지 않을것은데
왜 순서적으로 처리가 된다는 것인지 잘 이해가 안가는것 같습니다

async 계열들이 내부적으로 쓰레드로 돌아가는 것이라면 다른 것들도 마찬가지 일것 같은데요..

답변 좀 부탁드리겠습니다!

답변 1

답변을 작성해보세요.

0

동시에 여러 클라이언트에서 접속이 이뤄지면
AcceptAsync 가 두번 실행 되면서
내부적으로 스레드 두개가 돌아가는것 같은데

-> 클라 접속이 이뤄지더라도 AcceptAsync를 명시적으로 호출해줘야
OnAcceptCompleted가 실행됩니다.
즉, AcceptAsync는 일종의 입장 허락의 개념이라고 생각하시면 됩니다.
그 전에 접속을 희망한 클라들은 입장 대기를 하고 있겠죠.

코드를 보면 OnAcceptCompleted를 호출해서 입장 관련 처리를 다 끝낸 다음,
마지막에 RegisterAccept를 다시 호출해서 다음 입장을 받아주기 때문에
동시에 여러 쓰레드가 OnAcceptCompleted를 실행할 수 없습니다.
image
물론 Listener Init 코드에서 위의 RegisterAccept를 여러 번 호출하게 수정을 하면
말씀하신 상황이 일어날 수 있겠죠.
(실제로 큰 규모 MMO에선 동시에 입장이 몰릴 경우 대비해 RegisterAccept 횟수를 늘려놓긴 해야 합니다)
그렇다 하더라도 항상 Lock이 필요하진 않고 [공유해서 사용하는 데이터가 있는지]가 핵심입니다.
image
그런데 위 함수에서 딱히 쓰레드끼리 공유해서 사용하는 데이터가 없기 때문에
굳이 동기화 처리를 하지 않아도 무방합니다.

(_sessionFactory가 있긴 하지만 얘는 수정이 없다고 가정)

 

dyl님의 프로필

dyl

질문자

2022.12.23

빠른 답변 감사드립니다

그렇다면 msdn 설명 처럼..
Accepting connections asynchronously gives you the ability to send and receive data within a separate execution thread. Before calling the AcceptAsync method, you must call the Listen method to listen for and queue incoming connection requests.

이 글에서 처럼 클라에서 온 애들을 '큐'에 일단 동시 발생 되지 않도록 정렬(동시 두 함수가 실행되지 않게)하여 모아 놓고 AcceptAsync 를 통해 정렬되어진 대기하고 있는 것들을 하나씩 pop 해와서 receive 처리를 하기 때문에

클라에 대한 처리가 args 가 하나만 있을때는 OnAcceptCompleted 이 함수는 한번에 하나씩만 실행 가능하다 라고 이해하면 될까요?

https://learn.microsoft.com/en-us/dotnet/api/system.net.sockets.socket.acceptasync?view=netframework-4.7.2&f1url=%3FappId%3DDev16IDEF1%26l%3DEN-US%26k%3Dk(System.Net.Sockets.Socket.AcceptAsync)%3Bk(TargetFrameworkMoniker-.NETFramework%2CVersion%253Dv4.7.2)%3Bk(DevLang-csharp)%26rd%3Dtrue

네 그렇습니다.
애당초 넘겨준 args에 접속 클라에 관한 중요 정보를 세팅하기 때문에
아직 완료되지 않은 args를 재사용하면 무시무시한 일이 일어납니다.