성태의 닷넷 이야기
홈 주인
모아 놓은 자료
프로그래밍
질문/답변
사용자 관리
사용자
메뉴
아티클
외부 아티클
유용한 코드
온라인 기능
MathJax 입력기
최근 덧글
[정성태] 아쉽게도, 커뮤니티는 아니고 개인 블로그입니다. ^^
[정성태] 질문이 잘 이해가 안 됩니다. 우선, 해당 소스코드에서 ILis...
[양승조
] var대신 dinamic으로 선언해서 해결은 했습니다. 맞는 해...
[양승조
] 또 막혔습니다. ㅠㅠ var list = props[i].Ge...
[양승조
] 아. 감사합니다. 어제는 안됐던것 같은데....정신을 차려야겠네...
[정성태] "props[i].GetValue(props[i])" 코드에서 ...
[정성태] 저렇게 조각 코드 말고, 실제로 재현이 되는 예제 프로젝트를 압...
[정성태] Modules 창(Ctrl+Shift+U)을 띄워서, 해당 Op...
[정성태] 만드실 수 있습니다. 단지, Unity 엔진 내의 스크립트와 W...
[공진영] 안녕하세요 좋은글 감사합니다. 현재 제가 wpf로 관제 모...
글쓰기
제목
이름
암호
전자우편
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> </pre> <br /> <a name='clnt_svr_src'></a><br /> MSS를 실제 C# Socket과 <a target='tab' href='https://www.sysnet.pe.kr/2/0/12518'>Wireshark</a>를 통해 ^^ 확인해 보겠습니다. C# 소스 코드는 테스트 용도이므로 다음과 같이 간단하게 서버와 클라이언트를 구성할 수 있습니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > // 서버 - <a target='tab' href='https://www.sysnet.pe.kr/2/0/12519'>Oracle Cloud VM Ubuntu 20.04</a> using System; using System.Net; using System.Net.Sockets; class Program { static void Main(string[] args) { Socket server = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); server.Bind(new IPEndPoint(IPAddress.Any, 15000)); server.Listen(5); while (true) { Console.WriteLine("Accepting..."); Socket client = server.Accept(); do { string text = Console.ReadLine(); if (string.IsNullOrEmpty(text) == true) { break; } int readLen = int.Parse(text); byte[] buf = new byte[readLen]; readLen = client.Receive(buf, 0, buf.Length, SocketFlags.None); Console.WriteLine($"read: {readLen}"); } while (true); client.Close(); } } } </pre> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > // 클라이언트 - 물리 머신 Ubuntu 20.04 using System; using System.Net.Sockets; unsafe class Program { static void Main(string[] args) { { Socket client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); client.Connect("...serverip...", 15000); while (true) { string text = Console.ReadLine(); if (string.IsNullOrEmpty(text) == true) { break; } int sendSize = int.Parse(text); byte[] buffer = new byte[sendSize]; client.Send(buffer, 0, buffer.Length, SocketFlags.None); } client.Close(); } } } </pre> <br /> 하는 일은 매우 간단합니다. 서버는 연결 하나를 받지만 recv를 사용자가 원하는 크기를 지정할 때까지 호출하지 않습니다. 또한 클라이언트 측도 마찬가지로 연결만 해두고 이후 send는 사용자가 원하는 크기를 지정할 때까지 호출하지 않습니다.<br /> <br /> 이제 서버를 띄워놓고 클라이언트에서 접속할 때 Wireshark로 패킷을 캡처하면 다음과 같은 결과가 나옵니다.<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... ...svr_ip... TCP 74 32912 → 15000 [SYN] Seq=0 Win=64240 Len=0 MSS=<span style='color: blue; font-weight: bold'>1460</span> SACK_PERM=1 TSval=3363140511 TSecr=0 WS=128 ...svr_ip... ...client_ip.. TCP 74 15000 → 32912 [SYN, ACK] Seq=0 Ack=1 Win=62636 Len=0 MSS=<span style='color: blue; font-weight: bold'>8960</span> SACK_PERM=1 TSval=1612454569 TSecr=3363140511 WS=128 ...client_ip... ...svr_ip... TCP 66 32912 → 15000 [ACK] Seq=1 Ack=1 Win=64256 Len=0 TSval=3363140514 TSecr=1612454569 </pre> <br /> 보는 바와 같이 클라이언트에서 서버로 전송할 때는 MSS=1460이고, 서버에서 클라이언트로 보낼 때는 8960이라고 나옵니다. 이전에 설명했듯이, <a target='tab' href='https://www.sysnet.pe.kr/2/0/12521'>1460은 일반적인 설정의 MSS 값</a>이고, <a target='tab' href='https://www.sysnet.pe.kr/2/0/12522'>8960은 Jumbo Frame이 설정된 환경</a>의 값입니다.<br /> <br /> 어쨌든, 클라이언트는 1460을, 서버는 8960을 보냈으므로,<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > TCP/IP performance tuning for Azure VMs ; <a target='tab' href='https://learn.microsoft.com/en-us/azure/virtual-network/virtual-network-tcpip-performance-tuning'>https://learn.microsoft.com/en-us/azure/virtual-network/virtual-network-tcpip-performance-tuning</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'> This setting is agreed to in the TCP three-way handshake when a TCP session is set up between a source and a destination. <span style='color: blue; font-weight: bold'>Both sides send an MSS value, and the lower of the two is used</span> for the TCP connection. </div><br /> <br /> 둘 중의 작은 값인 1460이 해당 TCP 통신에서의 MSS 값이 됩니다.<br /> <br /> <hr style='width: 50%' /><br /> <br /> 자, 그럼 이제 소스 코드에 작성한 대로 임의의 데이터를 서버로 전송해 볼 텐데요, 우선 협의된 MSS 값보다 1이 큰 데이터를 서버로 보냈을 때의 Wireshark 캡처는 다음과 같이 나옵니다.<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 1514 32912 → 15000 [ACK] Seq=1 Ack=1 Win=64256 Len=<span style='color: blue; font-weight: bold'>1448</span> TSval=3445313658 TSecr=1693752398 ..client_ip... ...serverip... TCP 79 32912 → 15000 [PSH, ACK] Seq=1449 Ack=1 Win=64256 Len=<span style='color: blue; font-weight: bold'>13</span> TSval=3445313658 TSecr=1693752398 ...serverip... ..client_ip... TCP 66 15000 → 32912 [ACK] Seq=1 Ack=1462 Win=61184 Len=0 TSval=1694627715 TSecr=3445313658 </pre> <br /> 예상했던 것처럼 2개의 패킷이 서버로 전송되긴 했지만, 크기가 1460이 아닌, 1448로 나와 있습니다. 왜 그런 것일까요? 그 이유는 TCP 헤더가 20바이트가 아닌, TSval, TSecr 정보에 해당하는 12 바이트를 더 점유하고 있기 때문입니다. 실제로 저 상황에서의 TCP 데이터를 보면,<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > Transmission Control Protocol, Src Port: 15000, Dst Port: 33544, Seq: 1, Ack: 1462, Len: 0 Source Port: 15000 Destination Port: 33544 [Stream index: 3] [TCP Segment Len: 0] Sequence number: 1 (relative sequence number) Sequence number (raw): 2415159352 [Next sequence number: 1 (relative sequence number)] Acknowledgment number: 1462 (relative ack number) Acknowledgment number (raw): 2123235886 <span style='color: blue; font-weight: bold'>1000 .... = Header Length: 32 bytes (8)</span> Flags: 0x010 (ACK) Window size value: 478 [Calculated window size: 61184] [Window size scaling factor: 128] Checksum: 0x5672 [unverified] [Checksum Status: Unverified] Urgent pointer: 0 <span style='color: blue; font-weight: bold'>Options: (12 bytes), No-Operation (NOP), No-Operation (NOP), Timestamps TCP Option - No-Operation (NOP) Kind: No-Operation (1) TCP Option - No-Operation (NOP) Kind: No-Operation (1) TCP Option - Timestamps: TSval 1694627715, TSecr 3445313658 Kind: Time Stamp Option (8) Length: 10 Timestamp value: 1694627715 Timestamp echo reply: 3445313658</span> [SEQ/ACK analysis] [This is an ACK to the segment in frame: 49156] [The RTT to ACK the segment was: 0.003061175 seconds] [iRTT: 0.003105376 seconds] [Timestamps] </pre> <br /> 헤더 크기가 32로 나옵니다. 따라서, IP MTU(1500) - IPHeader(20) - TCPHeader(32) = 1448이 TCP 데이터로 보낼 수 있는 최대 크기가 됩니다. 따라서, 클라이언트에서 1448을 보내도록 다시 테스트를 해보면,<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 1514 33544 → 15000 [PSH, ACK] <span style='color: blue; font-weight: bold'>Seq=1462</span> Ack=1 Win=64256 Len=<span style='color: blue; font-weight: bold'>1448</span> TSval=3445823525 TSecr=1694627715 ...serverip... ..client_ip... TCP 66 15000 → 33544 [ACK] Seq=1 <span style='color: blue; font-weight: bold'>Ack=2910</span> Win=59776 Len=0 TSval=1695137582 TSecr=3445823525 </pre> <br /> 정확히 1개의 전송 패킷과, 1개의 ACK 패킷만을 확인할 수 있습니다. (단일 패킷 전송/ACK인 경우 전송 측의 Seq=1462와 Ack 패킷의 Ack=2910의 번호 차이도 1,448만큼 나오는 것이 우연은 아닙니다.)<br /> <br /> (<a target='tab' href='https://www.sysnet.pe.kr/bbs/DownloadAttachment.aspx?fid=1724&boardid=331301885'>첨부 파일은 이 글의 예제 코드를 포함</a>합니다.)<br /> </p><br /> <br /><hr /><span style='color: Maroon'>[이 글에 대해서 여러분들과 의견을 공유하고 싶습니다. 틀리거나 미흡한 부분 또는 의문 사항이 있으시면 언제든 댓글 남겨주십시오.]</span> </div>
첨부파일
스팸 방지용 인증 번호
1503
(왼쪽의 숫자를 입력해야 합니다.)