Microsoft MVP성태의 닷넷 이야기
.NET Framework: 489. Socket.Listen에 전달된 backlog 인자의 의미 [링크 복사], [링크+제목 복사],
조회: 29735
글쓴 사람
정성태 (techsharer at outlook.com)
홈페이지
첨부 파일
 
(연관된 글이 3개 있습니다.)

Socket.Listen에 전달된 backlog 인자의 의미

간단한 테스트를 해볼까요? ^^

TcpListener serverSock = new TcpListener(IPAddress.Any, 5000);
serverSock.Start(5); // Socket.Listen(5); 호출과 동일

TcpClient clientSocket = serverSock.AcceptTcpClient();
    
Thread.Sleep(Timeout.Infinite);

위와 같이 프로그램을 하는 경우, 클라이언트가 접속을 시도했을 때 몇번째부터 예외가 발생할까요? ^^

정답은 7입니다. 왜냐하면, 첫 번째 Connect 시도는 AcceptTcpClient 호출 덕분에 정상적으로 accept했기 때문에 backlog에 쌓이지 않습니다. 따라서 두 번째에서 여섯 번째까지의 Connect 시도가 backlog에 쌓여서 5개의 큐 제한을 꽉 채우게 됩니다. 그리고는 7번째 Connect 요청에 대해서는 서버 소켓이 명시적으로 오류를 내어 해당 클라이언트에서는 다음과 같은 예외가 발생합니다.

System.Net.Sockets.SocketException was unhandled
  _HResult=-2147467259
  _message=No connection could be made because the target machine actively refused it
  HResult=-2147467259
  IsTransient=false
  Message=No connection could be made because the target machine actively refused it 192.168.0.23:5000
  Source=System
  ErrorCode=10061
  NativeErrorCode=10061
  StackTrace:
       at System.Net.Sockets.TcpClient.Connect(String hostname, Int32 port)
       at ConsoleApplication1.Program.ClientFunc(Object obj) in e:\...\ConsoleApplication1\Program.cs:line 115
       at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
       at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
       at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
       at System.Threading.ThreadHelper.ThreadStart(Object obj)
  InnerException: 

이 상태에서 netstat로 소켓 상태를 확인해 보면 6개의 TCP 자원이 "ESTABLISHED" 상태로 진입한 것을 확인할 수 있습니다.

c:> netstat -ano | findstr ":5000"

TCP    0.0.0.0:5000           0.0.0.0:0              LISTENING       2384
TCP    192.168.0.23:5000      192.168.0.95:62724     ESTABLISHED     2384
TCP    192.168.0.23:5000      192.168.0.95:62725     ESTABLISHED     2384
TCP    192.168.0.23:5000      192.168.0.95:62726     ESTABLISHED     2384
TCP    192.168.0.23:5000      192.168.0.95:62727     ESTABLISHED     2384
TCP    192.168.0.23:5000      192.168.0.95:62728     ESTABLISHED     2384
TCP    192.168.0.23:5000      192.168.0.95:62729     ESTABLISHED     2384

이때, tcpview.exe와 같은 도구를 이용해 backlog에 쌓여 있는 "ESTABLISHED" 상태의 소켓을 강제로 닫으면 어떤 일이 발생할까요? 당연히 netstat로 확인하면 "ESTABLISHED" 상태의 소켓 수가 줄어들게 됩니다.

그렇다면 backlog에 쌓인 소켓 수가 줄었으니, 이후의 클라이언트 소켓 연결 요청을 받아들이게 될까요?

정답은, 받아들일 수 없습니다. 이를 통해서 소켓은 Listen에 지정된 숫자가 운영체제의 소켓 자원에 대한 '상태'와는 무관하게 계산된다는 것을 알 수 있습니다. 즉, Listen으로 인해 연결 요청이 들어온 것이 큐에 쌓이게 되고 그것이 빠져나가지 않는 한 해당 연결 요청에 대한 클라이언트 들의 상태와는 무관하게 accept 처리가 되는 것입니다.

(현실적으로 별로 유용한 정보는 아니지만, 그냥 심심해서 테스트 한번 해봤습니다. ^^)




[이 글에 대해서 여러분들과 의견을 공유하고 싶습니다. 틀리거나 미흡한 부분 또는 의문 사항이 있으시면 언제든 댓글 남겨주십시오.]

[연관 글]






[최초 등록일: ]
[최종 수정일: 10/26/2024]

Creative Commons License
이 저작물은 크리에이티브 커먼즈 코리아 저작자표시-비영리-변경금지 2.0 대한민국 라이센스에 따라 이용하실 수 있습니다.
by SeongTae Jeong, mailto:techsharer at outlook.com

비밀번호

댓글 작성자
 



2015-09-09 07시22분
[gwise] 좋은 정보 감사합니다.
Socket.Listen(5); 요거 db Connection 풀링하고 같은 의미네요...
[guest]
2018-01-26 01시57분
정성태
2018-02-12 01시40분
$ sysctl net.ipv4.tcp_synack_retries
net.ipv4.tcp_synack_retries = 5

$ sysctl net.ipv4.tcp_max_syn_backlog
net.ipv4.tcp_max_syn_backlog = 128

$ sysctl net.core.somaxconn
net.core.somaxconn = 128
정성태
2018-02-12 01시40분
$ ss -n state syn-recv sport = :80 | wc -l
1

$ ss -n state syn-recv sport = :443 | wc -l
1

$ sysctl net.ipv4.tcp_abort_on_overflow
net.ipv4.tcp_abort_on_overflow = 0

정성태
2018-02-12 01시40분
$ nstat -az TcpExtListenDrops
#kernel
TcpExtListenDrops 0 0.0

$ ss -plnt sport = :80|cat
State Recv-Q Send-Q Local Address:Port Peer Address:Port

$ nstat -az TcpExtTCPReqQFullDoCookies
#kernel
TcpExtTCPReqQFullDoCookies 0 0.0
정성태
2018-02-12 01시40분
$ nstat -az TcpExtSyncookiesSent
#kernel
TcpExtSyncookiesSent 0 0.0

$ sysctl net.ipv4.tcp_syncookies
net.ipv4.tcp_syncookies = 1

$ sysctl net.ipv4.tcp_timestamps
net.ipv4.tcp_timestamps = 1
정성태

... 46  47  48  49  50  51  52  53  54  55  56  [57]  58  59  60  ...
NoWriterDateCnt.TitleFile(s)
12546정성태3/3/202118469개발 환경 구성: 545. github workflow/actions에서 빌드시 snk 파일 다루는 방법 - Encrypted secrets
12545정성태3/2/202121215.NET Framework: 1026. 닷넷 5에 추가된 POH (Pinned Object Heap) [10]
12544정성태2/26/202121578.NET Framework: 1025. C# - Control의 Invalidate, Update, Refresh 차이점 [2]
12543정성태2/26/202119243VS.NET IDE: 158. C# - 디자인 타임(design-time)과 런타임(runtime)의 코드 실행 구분
12542정성태2/20/202120899개발 환경 구성: 544. github repo의 Release 활성화 및 Actions를 이용한 자동화 방법 [1]
12541정성태2/18/202118412개발 환경 구성: 543. 애저듣보잡 - Github Workflow/Actions 소개
12540정성태2/17/202119852.NET Framework: 1024. C# - Win32 API에 대한 P/Invoke를 대신하는 Microsoft.Windows.CsWin32 패키지
12539정성태2/16/202119669Windows: 189. WM_TIMER의 동작 방식 개요파일 다운로드1
12538정성태2/15/202120213.NET Framework: 1023. C# - GC 힙이 아닌 Native 힙에 인스턴스 생성 - 0SuperComicLib.LowLevel 라이브러리 소개 [2]
12537정성태2/11/202120271.NET Framework: 1022. UI 요소의 접근은 반드시 그 UI를 만든 스레드에서! - 두 번째 이야기 [2]
12536정성태2/9/202119356개발 환경 구성: 542. BDP(Bandwidth-delay product)와 TCP Receive Window
12535정성태2/9/202118451개발 환경 구성: 541. Wireshark로 확인하는 LSO(Large Send Offload), RSC(Receive Segment Coalescing) 옵션
12534정성태2/8/202119185개발 환경 구성: 540. Wireshark + C/C++로 확인하는 TCP 연결에서의 closesocket 동작 [1]파일 다운로드1
12533정성태2/8/202117660개발 환경 구성: 539. Wireshark + C/C++로 확인하는 TCP 연결에서의 shutdown 동작파일 다운로드1
12532정성태2/6/202119453개발 환경 구성: 538. Wireshark + C#으로 확인하는 ReceiveBufferSize(SO_RCVBUF), SendBufferSize(SO_SNDBUF) [3]
12531정성태2/5/202117966개발 환경 구성: 537. Wireshark + C#으로 확인하는 PSH flag와 Nagle 알고리듬파일 다운로드1
12530정성태2/4/202121396개발 환경 구성: 536. Wireshark + C#으로 확인하는 TCP 통신의 Receive Window
12529정성태2/4/202119892개발 환경 구성: 535. Wireshark + C#으로 확인하는 TCP 통신의 MIN RTO [1]
12528정성태2/1/202119703개발 환경 구성: 534. Wireshark + C#으로 확인하는 TCP 통신의 MSS(Maximum Segment Size) - 윈도우 환경
12527정성태2/1/202119694개발 환경 구성: 533. Wireshark + C#으로 확인하는 TCP 통신의 MSS(Maximum Segment Size) - 리눅스 환경파일 다운로드1
12526정성태2/1/202116423개발 환경 구성: 532. Azure Devops의 파이프라인 빌드 시 snk 파일 다루는 방법 - Secure file
12525정성태2/1/202115279개발 환경 구성: 531. Azure Devops - 파이프라인 실행 시 빌드 이벤트를 생략하는 방법
12524정성태1/31/202115815개발 환경 구성: 530. 기존 github 프로젝트를 Azure Devops의 빌드 Pipeline에 연결하는 방법 [1]
12523정성태1/31/202117693개발 환경 구성: 529. 기존 github 프로젝트를 Azure Devops의 Board에 연결하는 방법
12522정성태1/31/202119905개발 환경 구성: 528. 오라클 클라우드의 리눅스 VM - 9000 MTU Jumbo Frame 테스트
12521정성태1/31/202118198개발 환경 구성: 527. 이더넷(Ethernet) 환경의 TCP 통신에서 MSS(Maximum Segment Size) 확인 [1]
... 46  47  48  49  50  51  52  53  54  55  56  [57]  58  59  60  ...