Windows 에서 listen함수의 Backlog Queue의 크기를 구해보자.

2021. 10. 27. 21:56게임서버/win socket 프로그래밍

320x100
안녕하세요 대학생 개발자입니다.
오늘의 목표는

listen을 했을 때 커널에 back log queue(listen queue)가 생기는데 그 큐의 사이즈의 크기를 코드로 직접 구해보려고 합니다.

listen side code
connect side code

 

 

서버 측에서 listen을 콜 할 때 SOMAXCONN -> 7fffffff signed int 중 가장 큰 값을 인자로 전달합니다.

client에서 실제 connect를 과연 몇 개까지 할 수 있을까를 실험해봤습니다.

client는 무한루프를 돌면서 loop back address:8000 으로 connect를 시도합니다.

실제 연결된 클라이언트 수는 200명에 불과합니다.

분명 나는 signed int 중 가장 큰 값인 7fffffff를 인자로 전달했는데 왜 200개밖에 되지 않을까?

당연히 21억어쩌고하는 값이 나오지 않을 거란 것은 알고 있었습니다.

나에게 주어진 메모리는 한정적이기 때문입니다.

하지만 200은 너무 적잖아요!!

 

궁금해진 저는 msdn에 listen을 검색해봤습니다.

 

"If set to SOMAXCONN, the underlying service provider responsible for socket s will set the backlog to a maximum reasonable value."

 

이런글이 있더라구요... SOMAXCONN을 넣게 되면 백로그의 값을 합리적인 최댓값으로 바꿔준다고 적혀있었습니다.

아... 그값이 200인가?

합리적이라는 게 무슨 의미일까요...

  • 1. 너네 컴퓨터가 아무리 좋아도 200개 이상은 받을 수 없다
  • 1-1. 다른 사양의 pc에서는 200보다 클 수도 적을 수도 있는 건가..?
  •       다른 pc의 경우는 어떨지 궁금했습니다... pc가 한대라서 서럽다ㅠㅠ
  • 2. 아무리 파바박 들어와도 200은 넘을 일이 없으니까 괜찮을 거다

고민을 해보긴 했는데 저는 아무리 많이 동시에 connect를 파바박 치고 들어온다고 해도 200은 넘지 않을 것이라는 의미에서 일거라고 추측합니다. (이렇게 생각한 이유는 나중에 나옵니다)

 

그럼... 여기서 드는 의문은 200보다 작은 값은 과연 적용이 될까 였습니다.

그래서 해보았습니다. listen함수의 백로그를 100으로 수정후 실행해보았습니다.

listen(s,100)

오... msdn에 적혀있던 maximum reasonable value 보다 작은 값을 입력하니 바로 적용이 되어버리는 걸 확인할 수 있었습니다.

 

그렇다면 200 이상의 값으로는 세팅을 할 수 없는가... 하면 msdn/listen함수에 나왔던 다음 문장을 보겠습니다.

 

If set to SOMAXCONN_HINT(N) (where N is a number), the backlog value will be N, adjusted to be within the range (200, 65535). Note that SOMAXCONN_HINT can be used to set the backlog to a larger value than possible with SOMAXCONN.

 

즉 SOMAXCONN_HINT(n)를 사용하게 되면 backlog queue가 n개가 될 것이다. SOMAXCONN을 했을 때 보다 더 큰 값을 가능하게 할 수 있다라는 의미인데요.

range가 200~65535입니다.

200 ~ unsigned short의 최댓값 범위네요

 

어.. 그러면 아까 maximum reasonable value가 왜 200 인지에 대한 추측이 1개로 좁혀지는군요...

65535까지 가능하다면 사양이 달려서는 아닐 것이라고 생각됩니다.

실제 task manager를 들어가 보면 핸들만 1000개 넘게 쓰고 있는 프로세스들도 많이 보이니깐요.(물론 다 소켓은 아니겠지만. 소켓도 결국 핸들이니까요. 그렇다고요...)

 

그러면 남은 추측하나는 아무리 동시에 파 바바 바박 들어와도 200명은 안 넘어서 그런 거야 라는 방향으로 굳어지게 되는군요.

 

그럼 또 궁금한 게 두 가지가 생기는데 SOMAXCONN_HINT를 이용해서는 200 밑으로는 안될까 와 65535보다 큰 값도 안될까입니다.

분명 listen함수의 backlog는 타입이 int기 때문에 -21억 어쩌고~ 21억어쩌고 까지 가능할 텐데 말이죠.

우선 아까와 똑같이 세팅을 한 상태로 backlog 만 100에서 SOMAXCONN_HINT(100)으로 바꿔 보았습니다.

 

 

listen(S,SOMAXCONN_HINT(100))결과

오... 진짜 200이 나왔네요?

그러면 200 이하로는 안 되니까 65535 이상도 안될 것 같다는 의심이 드는데요

 

SOMAXCONN_HINT

SOMAXCONN_HINT를 자세히 봤습니다.

그저 음수로 바꿔주는 일만 하는데요...

뭐 큰 특이점은 없는 것 같습니다

 

 

65535번의 connect를 해보는 실제 실험은... 해봤는데 실패했습니다...

소켓이 16000개가 넘어버리니까 더 이상 확보도 안될뿐더러...  크롬을 켰더니 다른 사이트들 접속도 안 되는 현상이... 아마 클라가 closesocket을 해주지 않은 것이 원인 같습니다...

클라이언트의 경우 서버와 달리 바인딩을 따로하지 않아 connect시에 동적포트 영역을 사용하는데 사용후 closesocket 을 하지 않아서 closesocket를 하지않아 동적 포트가 고갈된 것이 원인인 것 같습니다...

 

그럼 클라이언트의 소스를 살짝 수정해봐야 할 것 같습니다.!

 

어... 클라이언트의 소스를 수정했습니다만... 그래도 16000개 정도 넘어가버리니까 더 이상 확보가 안되네요 ㅠㅠ

아마 윈도우에서 closesocket을 시도해도 TIME_WAIT상태로 남아있기 때문에 다음 연결이 되지 않아서 이런 문제가 생긴것으로 추측했습니다.

netstat을 확인 해보니 추측과 동일하게 클라이언트 프로세스가 종료되었음에도 불구하고 여전히 TIME_WAIT 상태로 남아있더군요...

아마 그렇다면 linger를 통해서 time wait이 없게 만들어서 바로바로 다시 들어오게 만들어 줘야 할 것 같습니다. 

처음에 잘못 생각을 하고 있었던 부분은 accept를 해서 뽑아내면 65535까지 받아지지 않을까 했던 부분이 있었습니다만 잘못 생각했었습니다.

결국에는 time wait상태가 되어버린다면 동적 포트 하나를 못쓰게 되기 때문인데요...

서버가 accept를 수행하기 이전에 클라이언트가 closesocket을 먼저 해버리면 backlog queue에서 사라지지 않습니다. queue인데 중간에서 유효하지 않은 데이터를 꺼낸다는 것 자체도 말이 안 되는 경우입니다.

queue에 작동방식이 아니죠 그건.

그래서 서버 측에서 accept를 통한 dequeue를 하거나 혹은 서버를 종료해서 os에서 처리하게 만들어버리는 방법 외엔 없는것 같습니다.

서버측에서 accept를 호출하면 바로 close 되어버리기 때문에 dequeue의 기능을 통해서 처리할 수 있습니다...

 

그렇다면 추측상

-200보다 크면서 0보다 작은 값은 200으로

-65535보다 더 낮은 값들은 다 65535로 만들어주는 코드가 listen내부에 포함되어있을 것 같다는 생각이 들었습니다...(뭔가 똥을 싸다가 만 느낌 같지만 이게 최종 결론입니다.

 

  • 결론 1 -> listen의 백로그 큐는 음수가 아니면서 동시에 200보다 작은 값이 아니라면 200개로 내려진다.
  • 결론 2 -> listen의 백로그 큐를 200 이상으로 만들고 싶다면 SOMAXCONN_HINT를 이용해서 음수로 만들어 주면 가능해진다.
  • 결론 3 -> SOMAXCONN_HINT를 사용하면 listen함수에서 200 아래로 떨어지는 값은 200위로 올려버린다.
  • 결론 4 -> SOMAXCONN_HINT를 사용하면 listen 함수에서 65535위로 가는 값은 65535로 자른다.

긴 글 읽어주셔서 감사합니다 큰 도움이 될진 모르겠지만

첫 게시글인데... 잘 봐주셔서 감사합니다 그럼 다음에 오겠습니다

안녕히 계세요

320x100

'게임서버 > win socket 프로그래밍' 카테고리의 다른 글

Overlapped IO Model + heap  (0) 2022.02.11
Overlapped IO Introduction  (0) 2022.02.10
L4와 L7그리고 서버  (0) 2021.11.04
Win socket API2  (0) 2021.11.03
Window Socket API 기본 정리1  (0) 2021.11.01