TCP의 신뢰성과 Socket API에서의 전송단위

stylix의 이미지

안정적인 네트워크 프로그램 작성을 위해 네트워크에 대한 깊은 지식을 가지고 싶습니다..
보통 Socket 코드를 작성할 때 Send(byte[] data) 가 실행되면 이 바이트 어레이가 네트워크 건너편 어플리케이션에서 하나의 단위로 받게 되는 것인가요?

데이터가 뭉쳐서 들어오는 것은 이해가 갑니다. 예를 들어
Send(byte[] data1);
Send(byte[] data2);
Send(byte[] data3);

로 보내면 상대편에서 data1, data2, data3가 이어져서 들어올 수 있다고 하는데 이건 충분히 그럴 수 있다고 생각합니다.
그런데 data1가 쪼개져서 두번에 나눠져서 들어오는 것을 경험한 적이 있습니다.
C# 비동기 수신을 했는데 가끔 수신 이벤트가 두번 나눠서 발생하더군요. 데이터가 크지도 않았습니다.10byte 정도?
이게 좀 꺼림직합니다.
TCP는 호스트와 호스트간의 신뢰성 있는 전송을 수행하는 특성이 있는데
정작 어플리케이션 차원에서는 데이터의 일부만을 전송하고 끊어지는 경우를 고려해야 하는 것인지...

제가 가정하고 싶은 부분은
어플리케이션에서 특정 패킷의 일부를 수신하였다면 나머지도 반드시 버퍼에 있다고 가정해도 되는 건지..?
(TCP는 데이터의 일부만을 보내지는 않으니까..?)

또, 제가 걱정스러운 부분은
Socket API가 Send(byte[] data)를 data의 크기에 따라 여려 TCP 전송으로 나눌수도 있는 것인지...입니다.
예를 들어 data가 그림 파일처럼 큰 용량을 가지더라도 한번에 전송된다고 가정할 수 있는 것인지...

이런게 확인하려면 어디를 찾아봐야 할까요? (C#, Windows 유저이지만 C, Unix관련 자료도 괜찮습니다.)
이유를 알고 계신분이 바로 알려주시면 더욱 감사하고요..

bushi의 이미지

stylix의 이미지

이건 뭉쳐서 보내는 거라 일부만 가는 거랑은 상관없지 않나요?..

bushi의 이미지

똑같은 생각을 하는 사람이 또 있구나 싶어서 보니, 본문 올리신 바로 그 분이네요.

최대한 뭉쳐서 보내므로 당연히 찢어져서 갈 수도 있습니다.
nagle 은 application 수준에서 data 를 다루는 것이 아니라 tcp/ip 수준에서 payload 를 다룹니다.

tcp/ip 수준에서 한 개의 packet 으로 데이타를 보냈다하더라도 받는 쪽의 application 이 한번에 read 한다는 보장이 없고,
tcp/ip 수준에서 여러 개의 packet 으로 찢어진 데이타를 보냈다하더라도 받는 쪽의 application 이 여러 번에 걸쳐 read 해야만 하는 것은 아닙니다.
중간에 끼어있는 OS 도 생각을 하세요.

UDP 는 도착한다는 보장도 없고, 따라서 보낸 순서 그대로 패킷이 도착한다는 보장도 없습니다.
UDP 를 사용하는 TFTP 의 protocol 을 보시면 좀 더 피부에 와 닿으실 겁니다.

익명 사용자의 이미지

UDP는 DATAGRAM, TCP는 STREAM의 의미 그대로 동작합니다.
TCP는 스트림이니 몇개로 쪼개서 오든, 몇개가 붙어서 오든 정상 동작입니다.

괜히 사람들이 TCP 프로토콜 헤더에 괜히 LENGTH를 넣는게 아닙니다.
TCP는 데이터의 일부만 보낼 수도 있습니다.
보내다가 선이 맛이가면 일부만 보내죠.
당연히 이 경우에는 버퍼에 없습니다.

서버쪽에 몇개는 정상적으로 보냈다는 정보가 가기때문에, 나머지를 더 보낼지는 서버에서 처리해야할 문제죠.
반대로, 클라이언트에서는 원하는 길이만큼 몇초내에 안오면, 시간만료으로 버려버리든지 하는 처리를 해줘야 합니다.

한번에 다 보내고 싶으면 UDP로 쏘면 됩니다.
물론, 한방에 다 가겠지만, 도착할런지를 보장할 수는 없습니다.

stylix의 이미지

답변 감사합니다.

그럼 UDP의 경우는 전송 도착의 신뢰성은 없어도 "단위성"은 있다고 생각해도 되나요?
예를 들어 UDP도 일부만 보내고 끊어지면 버퍼에 일부만 있는 상황이 발생할 수 있나요?

익명 사용자의 이미지

단위성은 분명 있습니다만
도착의 신뢰성 뿐만 아니라 tcp가 제공하는 다른 모든 신뢰성도 없다고 봐야합니다
단지 크기만 보낸 크기입니다

stylix의 이미지

정리하자면..

UDP - 전송도중에 장애 발생해도 일부만 수신하는 경우는 없음
TCP - 전송도중에 장애 발생하면 일부만 수신하는 경우도 가능

맞나요?

익명 사용자의 이미지

오해를 할까봐 계속 말합니다만
UDP는 길이만 보장합니다
일부만 제대로 오고 일부는 쓰레기 값일 가능성이 있어요
이러면 물리적으로 전부 수신해도 논리적으로는 전부 수신된게 아니죠

jick의 이미지

TCP: 100% 정상적인 네트웍에서도 일부만 수신하는 것이 가능합니다.

TCP는 스트림이라서 보낸 쪽에서 send를 몇 번 불렀는지는 기억하지 않습니다. 단 10바이트를 보내도 재수가 없으면 쪼개질 수도 있는 거고 열 번에 나눠 보내도 하나로 묶여서 도착할 수도 있습니다.

물론 네트웍이 정상이라면 계속 읽는 것을 반복하고 있으면 언젠가는(?) 다 읽히는 것을 보장합니다.

익명 사용자의 이미지

UDP 가 일부가 쓰레기값일 수 있다는 건 무슨 소린지 모르겠네요.

TCP든 UDP든 기본적으로 헤더에 Checksum 은 존재하고, 이건 프로그래머가
처리하는 게 아니라 그 아래 네트웍 단에서 미리 체크해서 처리됩니다.
그러니 데이터가 일부만 손상되어 오는 걸 소프트웨어 단에서 확인할 길은 없습니다.

익명 사용자의 이미지

간단하게 말하자면 udp는 체크섬 취소가 가능합니다

익명 사용자의 이미지

길게 쓰다가 날렸는데 휴대폰으로 적는거라 다시 적지는 못하겠고
말씀대로 체크섬은 단말에 붙어있는 프로그래머가 제어하기 힘든 부분입니다
그래서 체크섬 취소가 될 수 있다는 걸 모르면 가끔이라도 데이터 오류났다고 엄한 사람이나 잡고 있겠죠
그래서 확실하지 않은 네트웍에서 UDP는 데이터 신뢰성이 100%가 아니라는걸 명심해야 합니다

emptynote의 이미지

tcp/ip 실제 전송은 띄엄 띄엄 입니다.

Send(byte[] data3); 했는데 data3 전체가 전달되지도 않고

receive(byte[] data3) 해도 data3 전체를 받지 않아 개인적으로 많이 당황했지요.

tcp/ip 가 이렇게 띄엄 띄엄이지만

네트워크가 끊기지만 않는다면 tcp/ip 는 보낸 데이터 그대로 받을 수 있습니다.

tcp/ip 자체가 신뢰성 있는 데이터 전송을 목적으로 설계된 프로토콜이니깐요.

단 상식을 뛰어 넘을 정도로 느린 회선이라면 타임아웃 처리가 옳은지 아닌지는 논쟁이 되겠지요.

익명 사용자의 이미지

댓글 달기

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
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.