성태의 닷넷 이야기
홈 주인
모아 놓은 자료
프로그래밍
질문/답변
사용자 관리
사용자
메뉴
아티클
외부 아티클
유용한 코드
온라인 기능
MathJax 입력기
최근 덧글
[정성태] Working with Rust Libraries from C#...
[정성태] Detecting blocking calls using asyn...
[정성태] 아쉽게도, 커뮤니티는 아니고 개인 블로그입니다. ^^
[정성태] 질문이 잘 이해가 안 됩니다. 우선, 해당 소스코드에서 ILis...
[양승조
] var대신 dinamic으로 선언해서 해결은 했습니다. 맞는 해...
[양승조
] 또 막혔습니다. ㅠㅠ var list = props[i].Ge...
[양승조
] 아. 감사합니다. 어제는 안됐던것 같은데....정신을 차려야겠네...
[정성태] "props[i].GetValue(props[i])" 코드에서 ...
[정성태] 저렇게 조각 코드 말고, 실제로 재현이 되는 예제 프로젝트를 압...
[정성태] Modules 창(Ctrl+Shift+U)을 띄워서, 해당 Op...
글쓰기
제목
이름
암호
전자우편
HTML
홈페이지
유형
제니퍼 .NET
닷넷
COM 개체 관련
스크립트
VC++
VS.NET IDE
Windows
Team Foundation Server
디버깅 기술
오류 유형
개발 환경 구성
웹
기타
Linux
Java
DDK
Math
Phone
Graphics
사물인터넷
부모글 보이기/감추기
내용
<div style='display: inline'> <h1 style='font-family: Malgun Gothic, Consolas; font-size: 20pt; color: #006699; text-align: center; font-weight: bold'>Wireshark + C#으로 확인하는 TCP 통신의 MSS(Maximum Segment Size) - 윈도우 환경</h1> <p> 지난 글에서 살펴 본,<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > 이더넷(Ethernet) 환경의 TCP 통신에서 MSS(Maximum Segment Size) 확인 ; <a target='tab' href='https://www.sysnet.pe.kr/2/0/12521'>https://www.sysnet.pe.kr/2/0/12521</a> Wireshark + C#으로 확인하는 TCP 통신의 MSS(Maximum Segment Size) - 리눅스 환경 ; <a target='tab' href='https://www.sysnet.pe.kr/2/0/12527'>https://www.sysnet.pe.kr/2/0/12527</a> </pre> <br /> 몇몇 실습을 윈도우 환경에서도 해보겠습니다. 우선 MTU 값은 netsh 명령어를 이용해 확인할 수 있습니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > C:\Users\kevin> <span style='color: blue; font-weight: bold'>netsh interface ipv4 show interfaces</span> <span style='color: blue; font-weight: bold'>Idx</span> Met <span style='color: blue; font-weight: bold'>MTU</span> State Name --- ---------- ---------- ------------ --------------------------- <span style='color: blue; font-weight: bold'>1</span> 75 <span style='color: blue; font-weight: bold'>4294967295</span> connected Loopback Pseudo-Interface 1 <span style='color: blue; font-weight: bold'>6</span> 25 <span style='color: blue; font-weight: bold'>1500</span> disconnected Local Area Connection <span style='color: blue; font-weight: bold'>15</span> 10 <span style='color: blue; font-weight: bold'>1500</span> connected Ethernet 3 C:\Users\kevin> <span style='color: blue; font-weight: bold'>netsh interface ipv4 show interfaces 15</span> Interface Ethernet 3 Parameters ---------------------------------------------- IfLuid : ethernet_32774 IfIndex : 15 State : connected Metric : 10 <span style='color: blue; font-weight: bold'>Link MTU : 1500 bytes</span> Reachable Time : 32000 ms Base Reachable Time : 30000 ms Retransmission Interval : 1000 ms DAD Transmits : 3 Site Prefix Length : 64 Site Id : 1 Forwarding : disabled Advertising : disabled Neighbor Discovery : enabled Neighbor Unreachability Detection : enabled Router Discovery : dhcp Managed Address Configuration : enabled Other Stateful Configuration : enabled Weak Host Sends : disabled Weak Host Receives : disabled Use Automatic Metric : enabled Ignore Default Routes : disabled Advertised Router Lifetime : 1800 seconds Advertise Default Route : disabled Current Hop Limit : 0 Force ARPND Wake up patterns : disabled Directed MAC Wake up patterns : disabled ECN capability : application </pre> <br /> IP MTU 값이 1500이므로, IP Header == 20, TCP Header == 20인 일반적인 상황이라면 MSS는 1460이 될 것입니다. 실제로 ping 테스트를 (리눅스와는 옵션을 약간 다르게 조정해서) 이렇게 실행할 수 있습니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > C:\temp> <span style='color: blue; font-weight: bold'>ping www.microsoft.com -l 1473 -f -n 1</span> Pinging e13678.dscb.akamaiedge.net [23.212.13.232] with 1473 bytes of data: <span style='color: blue; font-weight: bold'>Packet needs to be fragmented but DF set.</span> Ping statistics for 23.212.13.232: Packets: Sent = 1, Received = 0, Lost = 1 (100% loss), C:\temp> <span style='color: blue; font-weight: bold'>ping www.microsoft.com -l 1472 -f -n 1</span> Pinging e13678.dscb.akamaiedge.net [23.212.13.232] with 1472 bytes of data: Reply from 23.212.13.232: bytes=1472 time=4ms TTL=56 Ping statistics for 23.212.13.232: Packets: Sent = 1, Received = 1, Lost = 0 (0% loss), Approximate round trip times in milli-seconds: Minimum = 4ms, Maximum = 4ms, Average = 4ms </pre> <br /> 보다시피 리눅스에서와 동일하게 ICMP 8바이트를 제외한 1472 바이트가 하나의 패킷에 전달되는 것을 확인할 수 있습니다.<br /> <br /> <hr style='width: 50%' /><br /> <br /> <a target='tab' href='https://www.sysnet.pe.kr/2/0/12527#clnt_svr_src'>지난 글의 클라이언트/서버 C# 코드</a>를 이번에는 Azure VM(Windows Server 2016)을 서버로, 물리 PC에 설치한 Windows 10을 클라이언트로 테스트하면 연결 시 다음과 같은 3-way handshake를 확인할 수 있습니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > [...clnt_ip...] [...azure_svr_ip..] TCP 66 2406 → 15000 [SYN] Seq=0 Win=64240 Len=0 <span style='color: blue; font-weight: bold'>MSS=1460</span> WS=256 SACK_PERM=1 [...azure_svr_ip..] [...clnt_ip...] TCP 66 15000 → 2406 [SYN, ACK] Seq=0 Ack=1 Win=8192 Len=0 <span style='color: blue; font-weight: bold'>MSS=1440</span> WS=256 SACK_PERM=1 [...clnt_ip...] [...azure_svr_ip..] TCP 54 2406 → 15000 [ACK] Seq=1 Ack=1 Win=263424 Len=0 </pre> <br /> 보는 바와 같이 클라이언트에서 서버로 전송할 때는 MSS=1460이고, 서버에서 클라이언트로 보낼 때는 1440이라고 나옵니다. 서버가 왜 1440을 보냈는지 이유는 알 수 없으나, 어쨌든 이렇게 되면 <a target='tab' href='https://docs.microsoft.com/en-us/azure/virtual-network/virtual-network-tcpip-performance-tuning'>협상에 따라</a> MSS=1440으로 결정됩니다.<br /> <br /> 참고로, IPv6의 경우 IP 헤더가 40바이트이기 때문에 1460으로 나올 수 있습니다. 그 외에, <a target='tab' href='https://garimoo.github.io/study/2018/03/26/MSS_MTU.html'>IP-in-IP 터널링에서도 발생</a>할 수도 있고, 혹은 options가 20바이트를 점유하는 경우에도 발생할 수 있습니다.<br /> <br /> <hr style='width: 50%' /><br /> <a name='lso_option'></a> <br /> 그런데, 재미있는 점이 하나 있습니다. <a target='tab' href=''>리눅스 환경에서는 MSS 크기에 맞게 서버로 패킷이 전송</a>되는 반면, 윈도우의 경우에는 MSS 크기를 무시하고 전송한다는 점입니다. 가령, 리눅스에서 12,960 바이트를 전송하면 다음과 같이 정확히 9개의 패킷(1448 * 8 + 1376)으로 나눠 전달이 되는 것을 확인할 수 있습니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > "..clnt_ip...","...serverip...","TCP","1514","32990 > 15000 [ACK] Seq=1 Ack=1 Win=64256 Len=<span style='color: blue; font-weight: bold'>1448</span> TSval=3494193047 TSecr=1743410262" "..clnt_ip...","...serverip...","TCP","1514","32990 > 15000 [ACK] Seq=1449 Ack=1 Win=64256 Len=<span style='color: blue; font-weight: bold'>1448</span> TSval=3494193047 TSecr=1743410262" "..clnt_ip...","...serverip...","TCP","1514","32990 > 15000 [ACK] Seq=2897 Ack=1 Win=64256 Len=<span style='color: blue; font-weight: bold'>1448</span> TSval=3494193047 TSecr=1743410262" "..clnt_ip...","...serverip...","TCP","1514","32990 > 15000 [ACK] Seq=4345 Ack=1 Win=64256 Len=<span style='color: blue; font-weight: bold'>1448</span> TSval=3494193047 TSecr=1743410262" "..clnt_ip...","...serverip...","TCP","1514","32990 > 15000 [PSH, ACK] Seq=5793 Ack=1 Win=64256 Len=<span style='color: blue; font-weight: bold'>1448</span> TSval=3494193047 TSecr=1743410262" "..clnt_ip...","...serverip...","TCP","1514","32990 > 15000 [ACK] Seq=7241 Ack=1 Win=64256 Len=<span style='color: blue; font-weight: bold'>1448</span> TSval=3494193047 TSecr=1743410262" "..clnt_ip...","...serverip...","TCP","1514","32990 > 15000 [ACK] Seq=8689 Ack=1 Win=64256 Len=<span style='color: blue; font-weight: bold'>1448</span> TSval=3494193047 TSecr=1743410262" "..clnt_ip...","...serverip...","TCP","1514","32990 > 15000 [ACK] Seq=10137 Ack=1 Win=64256 Len=<span style='color: blue; font-weight: bold'>1448</span> TSval=3494193047 TSecr=1743410262" "..clnt_ip...","...serverip...","TCP","1442","32990 > 15000 [PSH, ACK] Seq=11585 Ack=1 Win=64256 Len=<span style='color: blue; font-weight: bold'>1376</span> TSval=3494193047 TSecr=1743410262" "...serverip...","..clnt_ip...","TCP","66","15000 > 32990 [ACK] Seq=1 Ack=7241 Win=56576 Len=0 TSval=1743507109 TSecr=3494193047" "...serverip...","..clnt_ip...","TCP","66","15000 > 32990 [ACK] Seq=1 Ack=12961 Win=56576 Len=0 TSval=1743507109 TSecr=3494193047" </pre> <br /> 반면, 아래는 Window 10 Client에서 Windows Server 2016 Azure VM Server에 12,960 바이트를 send한 경우인데,<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > ..client_ip... ..server_ip.. TCP 7254 31894 → 15000 [ACK] Seq=1 Ack=1 Win=263424 Len=<span style='color: blue; font-weight: bold'>7200</span> ..server_ip.. ..client_ip... TCP 60 15000 → 31894 [ACK] Seq=1 Ack=2881 Win=262656 Len=0 ..server_ip.. ..client_ip... TCP 60 15000 → 31894 [ACK] Seq=1 Ack=5761 Win=262656 Len=0 ..client_ip... ..server_ip.. TCP 5814 31894 → 15000 [PSH, ACK] Seq=7201 Ack=1 Win=263424 Len=<span style='color: blue; font-weight: bold'>5760</span> ..server_ip.. ..client_ip... TCP 60 15000 → 31894 [ACK] Seq=1 Ack=12961 Win=262656 Len=0 </pre> <br /> 2개의 패킷으로만 나눠 가고 있습니다. (패킷 1개에 가기도 합니다.) 이러한 차이점이 서버와의 협상 차이에서 오는 것은 아닌 것 같습니다. 왜냐하면 리눅스 때와 같이 Oracle Cloud의 Linux VM에 12,960 바이트를 보내도,<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > ..client_ip... ...serverip... TCP 13014 31905 → 15000 [PSH, ACK] Seq=1 Ack=1 Win=262656 Len=<span style='color: blue; font-weight: bold'>12960</span> ...serverip... ..client_ip... TCP 60 15000 → 31905 [ACK] Seq=1 Ack=7301 Win=56576 Len=0 ...serverip... ..client_ip... TCP 60 15000 → 31905 [ACK] Seq=1 Ack=12961 Win=56576 Len=0 </pre> <br /> 1개의 패킷으로만 처리하고 있으니 최대 크기가 9000의 Jumbo Frame으로도 설명이 안 됩니다. (사실, 애당초 연결 시 결정되는 MSS 값은 1440이라 Jumbo Frame과도 연관이 없습니다.)<br /> <br /> 참... 이걸 뭐라고 해석해야 할지 모르겠군요. 관련 문서를 찾아 보면 다음과 같은 설명이 있습니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > What is MSS (maximum segment size)? ; <a target='tab' href='https://www.cloudflare.com/learning/network-layer/what-is-mss/'>https://www.cloudflare.com/learning/network-layer/what-is-mss/</a> </pre> <br /> <div style='BACKGROUND-COLOR: #ccffcc; padding: 10px 10px 5px 10px; MARGIN: 0px 10px 10px 10px; FONT-FAMILY: Malgun Gothic, Consolas, Verdana; COLOR: #005555'> Essentially, the MSS is equal to MTU minus the size of a TCP header and an IP header:<br /> <br /> MTU - (TCP header + IP header) = MSS<br /> <br /> One of the key differences between MTU and MSS is that if a packet exceeds a device's MTU, it is broken up into smaller pieces, or "fragmented." <span style='color: blue; font-weight: bold'>In contrast, if a packet exceeds the MSS, it is dropped and not delivered.</span> </div><br /> <br /> <span style='text-decoration: line-through'>혹시 윈도우 버전의 Wireshark에 버그가 있는 걸까요? 그렇다 해도 저런 식으로 버그가 발생하는 것은 쉽지 않을 듯 싶은데요. ^^; 갈수록 더 미궁으로 빠지는군요. (이와 관련한 네트워크 전문가가 계시다면 덧글 부탁드립니다. ^^)</span> (2021-02-09 업데이트: <a href='https://www.sysnet.pe.kr/2/0/12535'>이것의 원인은 "Large Send Offload" 때문</a>입니다.)<br /> <br /> <hr style='width: 50%' /><br /> <br /> <span style='text-decoration: line-through'>(2021-02-03 업데이트) 위의 결과를 설명할 수 있는 한 가지 가정이라면, Wireshark의 device driver가 Network 레이어의 상단에 위치해서 저런 식의 출력이 되지 않을까 싶습니다. 가령, 연결만 하고 대상 서버의 VM을 paused 상태로 바꾼 다음 send를 시도하면 다음과 같이 출력되는 것을 확인할 수 있습니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > ...[생략]... 3713 42.664245 ..client_ip... ..server_ip... TCP <span style='color: blue; font-weight: bold'>14654</span> 2436 → 15000 [ACK] Seq=1 Ack=1 Win=262656 Len=14600 3731 42.972303 ..client_ip... ..server_ip... TCP <span style='color: blue; font-weight: bold'>1514</span> [TCP Retransmission] 2436 → 15000 [ACK] Seq=1 Ack=1 Win=262656 Len=1460 3774 43.580628 ..client_ip... ..server_ip... TCP <span style='color: blue; font-weight: bold'>1514</span> [TCP Retransmission] 2436 → 15000 [ACK] Seq=1 Ack=1 Win=262656 Len=1460 3874 44.784230 ..client_ip... ..server_ip... TCP <span style='color: blue; font-weight: bold'>1514</span> [TCP Retransmission] 2436 → 15000 [ACK] Seq=1 Ack=1 Win=262656 Len=1460 4074 47.194383 ..client_ip... ..server_ip... TCP <span style='color: blue; font-weight: bold'>1514</span> [TCP Retransmission] 2436 → 15000 [ACK] Seq=1 Ack=1 Win=262656 Len=1460 4493 51.998457 ..client_ip... ..server_ip... TCP <span style='color: blue; font-weight: bold'>1514</span> [TCP Retransmission] 2436 → 15000 [ACK] Seq=1 Ack=1 Win=262656 Len=1460 ...[생략]... </pre> <br /> 저렇게 나오는 것을 보면, 14654라고 뜨긴 했지만 내부적으로는 1514로 쪼개 네트워크에 싣는 것으로 예측됩니다. (아무튼... 가정입니다. ^^)</span> </p><br /> <br /><hr /><span style='color: Maroon'>[이 글에 대해서 여러분들과 의견을 공유하고 싶습니다. 틀리거나 미흡한 부분 또는 의문 사항이 있으시면 언제든 댓글 남겨주십시오.]</span> </div>
첨부파일
스팸 방지용 인증 번호
1444
(왼쪽의 숫자를 입력해야 합니다.)