[질문]서버에서 동시 접속하는 클라이언트 처리

paraline의 이미지

서버 프로그래밍 중에 궁금한 점이 있어서 질문을 올립니다.
클라이언트 접속시, *닉스 계열에서는 select나 poll을 사용하는데, FD_READ가 오면 여기에서 accept를 해줍니다.
윈도에서는 일반적으로 CAsyncSocket을 쓰는데, OnAccept에서 Accept()를 호출합니다.
여태까지는 별 생각없이 그냥 종전 방식대로 해왔는데, 이번에 스트레스 테스트를 위해서, 쓰레드를 1000개 이상 띄워서 각각 소켓을 생성해서 서버로 접속을 시도합니다. 쓰레드 방식이긴 하지만, 거의 동시에 접속을 시도한다고 볼수 있죠.
그런데, 1000개 이상의 시도가 있을 경우, 예전에 작성했던, 솔라리스 서버에서는 놓치지 않고, 모두 accept를 하므로, 클라이언트는 모두 connect 성공으로 나옵니다. 그런데, 윈도 서버는 몇십개 정도는 connect fail이 됩니다.
처음에는 서버 스펙에 따라서 좌우될거라고 생각했고, 어느 시점에 1000개의 클라이언트 접속 상태일수는 있어도 동시에 1000개 접속을 시도하는 일은 없을거라고 생각하고, 그냥 넘겼는데, 아무리 생각해도 좀 이상합니다.
물론, OnAccept()에서 Accept()시에 시간이 너무 많이 걸리면 대기 큐에 있던 소켓들 중에는 connect fail이 날수도 있다고 생각합니다만, 어떻게 하면 모두 받아줄수 있을까요?
listen socket의 backlog값도 최대로 바꿔보고 했지만, 보다 효율적으로 접속을 처리해 주려면 어떻게 해야 할까요?

paraline의 이미지

보통 일반적인 방식은 OnAccept에서 클라이언트 소켓을 생성하고, 이것을 Accept()한 다음에 별도의 큐에 추가하고 Listen Socket은 다시 Listen을 하는 방식으로 하는데, 아무리 생각해도 이보다 더 빨리 Accept() 처리를 할수는 없을것 같은데, 좋은 방법이 있으시면 한수 지도 부탁드립니다.

좌절금지!!!
피할수 없다면 즐겨라.

codebank의 이미지

저도 이런 현상이 궁금했었는데 아직까지 적절한 답변이 없네요. 그래서 찾아봤더니...

http://white.chungbuk.ac.kr/~jchern/WSAEventSelect.html

음... 결국은 거의 동시에 FD_READ가 도착했다면 한번의 Accept에서 두 메시지를
하나로 취급을 하고 하나의 FD_READ는 이벤트 리스테에서 사라진다는 의미 같은데...
제가 정확하게 이해하고 있는건지는 모르겠지만 어쨌든 Event방식의 메시지교환상에서
발생할 수 있는 현상같네요.

------------------------------
좋은 하루 되세요.

kihongss의 이미지

paraline wrote:
서버 프로그래밍 중에 궁금한 점이 있어서 질문을 올립니다.
클라이언트 접속시, *닉스 계열에서는 select나 poll을 사용하는데, FD_READ가 오면 여기에서 accept를 해줍니다.
윈도에서는 일반적으로 CAsyncSocket을 쓰는데, OnAccept에서 Accept()를 호출합니다.
여태까지는 별 생각없이 그냥 종전 방식대로 해왔는데, 이번에 스트레스 테스트를 위해서, 쓰레드를 1000개 이상 띄워서 각각 소켓을 생성해서 서버로 접속을 시도합니다. 쓰레드 방식이긴 하지만, 거의 동시에 접속을 시도한다고 볼수 있죠.
그런데, 1000개 이상의 시도가 있을 경우, 예전에 작성했던, 솔라리스 서버에서는 놓치지 않고, 모두 accept를 하므로, 클라이언트는 모두 connect 성공으로 나옵니다. 그런데, 윈도 서버는 몇십개 정도는 connect fail이 됩니다.
처음에는 서버 스펙에 따라서 좌우될거라고 생각했고, 어느 시점에 1000개의 클라이언트 접속 상태일수는 있어도 동시에 1000개 접속을 시도하는 일은 없을거라고 생각하고, 그냥 넘겼는데, 아무리 생각해도 좀 이상합니다.
물론, OnAccept()에서 Accept()시에 시간이 너무 많이 걸리면 대기 큐에 있던 소켓들 중에는 connect fail이 날수도 있다고 생각합니다만, 어떻게 하면 모두 받아줄수 있을까요?
listen socket의 backlog값도 최대로 바꿔보고 했지만, 보다 효율적으로 접속을 처리해 주려면 어떻게 해야 할까요?

윈도우즈에서도 유닉스/리눅스처럼 BSD 소켓 스타일로 코딩하면 어떨까요?
MFC에서 제공하는 소켓 클래스인 CSocket / CAsyncSocket 계열은 간단한 테스트용이면 모르나, 다른 상황에서는 다들 쓰지 말라더군요. 또한, 메시지 큐 기반으로 OnAccept()가 호출되기 때문에, 큐가 다 찼을 경우에도, OnAccept()가 호출안될수도 있지요.
직접 윈속 API로 코딩해서 쓰시는게 좋을듯합니다. 예전에 데브피아에서 찾았던 문서인데, 윈속 프로그래밍시 참고하세요.

roach10의 이미지

윈도우 플랫폼에서 최고의 성능을 낸다고 하는
IOCP 를 써보세요
select() 류 보다 접속을 많이 받을 수 있다고 들었습니다.
Network Programming For MS Windows ,2nd
에 보면
성능 비교표가 나와있더군요.

그럼.

kihongss의 이미지

roach10 wrote:
윈도우 플랫폼에서 최고의 성능을 낸다고 하는
IOCP 를 써보세요
select() 류 보다 접속을 많이 받을 수 있다고 들었습니다.
Network Programming For MS Windows ,2nd
에 보면
성능 비교표가 나와있더군요.

그럼.


접속보다는 퍼포먼스 문제입니다.
얼마나 부하를 적게하면서 클라이언트에 응답을
빨리 줄수 있나 문제입니다. 그래도 역시, 윈도우즈에서
최적의 방법은 IOCP 네요~

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.