[질문] ADSL망에서 TCP소켓으로 연결시 데이터가 유실됩니다.

iyouhe의 이미지

서버는 리눅스(redhat 9.0)에서 TCP소켓(blocking)을 만들어서 Listen하고 있습니다.

클라이언트는 윈도우즈에서 MFC 어싱크로 소켓을 상속받아서 구현하였습니다.

서버에 UPlink 800kbps의 ADSL모뎀에 연결되어 있습니다.

이 상태에서 클라이언트가 서버로 파일을 요청하고, 서버는 그파일(400kbyte 크기)을 읽어서, 연결된 소켓으로 데이터를 보냅니다.

근데, 서버는 데이터를 오류없이 보냈는데, 클라이언트에서는 데이터를 중간까지만 받는 경우가 생깁니다.

물론 100Mbps망에서는 정상동작 합니다.

위와 같이 TCP가 유실되는 경우가 있나요? 원래 TCP는 데이터가 유실 되도, 커널단에서 다시 요청하는 거 아닌가요?

자세한 테스트 환경은 클라이언트가 400kbyte파일을 요청하면, 서버는 그 파일을 읽어서 4kbyte씩 잘라서 자신만의 헤더를 붇이고, 소켓에 write()를 합니다. 클러이언트에서는 패킷을 받아서, 해더 분석후, 읽은 내용을 모니터에 출력만 합니다. 400kbyte를 받으면, 클라이언트는 다시 400kbyte파일을 요청하면서 과정을 계속 반복합니다.
얼마간 정상적으로 되었다가, 서버는 데이터를 모두 write()했는데(리턴값은 보낸 사이즈. 0이나 -1이 발생한 경우 없음) 클라이언트에서 패킷을 받지 못하는 상태가 발생합니다.

익명 사용자의 이미지

iyouhe wrote:
위와 같이 TCP가 유실되는 경우가 있나요? 원래 TCP는 데이터가 유실 되도, 커널단에서 다시 요청하는 거 아닌가요?

네~.

그런데... 드라이버가 불안할 경우,
패킷이 유실되기도 합니다.

특히... 3Com사 제품 중 1Gbit일 경우 ,
3com사 다른 제품하고 통신할 때는 문제가 없는데,
realtek사 제품하고 통신할 경우, 패킷이 유실되는 경우가
생기기도 하더군요.

Redhat 9였습니다.

모지리의 이미지

라인 상태에 따른 통상적인 데이터 유실로 보이지는 않아 보입니다. 송수신측 코드를 다시 한번 살펴 보시는게 좋을듯 보입니다. 송수신 통신 프레임이(멀티 플렉싱 등등) 어떠한 방식인지, 송수신 데이터 송/수신 방식이 어떠한 방식인지(시간을 두고 버퍼 단위로 읽는지, 시간에 상관없이 길이 단위로 읽는지)등을 한번 다시 리뷰 해보시는게 어떨까 싶습니다.

ADSL 라인에서 그정도 데이터가 유실될정도면 항의감이죠. 그리고 TCP에서 데이터 유실은 접속 단절로 보셔도 무방합니다. 송신측 보다 수신측 코드를 유의 깊게 한번 보시길 권합니다.

wfellow의 이미지

내용을 찬찬히 들여다 보니 윗분 말씀대로 수신측의 코드가 문제가 있어 보입니다. 다른 모든 내용들은 차치하고서라도 서버측의 소켓 옵션을 NonBlocking으로 변경을 하시고서 받아 보시지요.. 받으실 때 간단한 버퍼를 구현하셔서 한번 출력을 해보시면 이유를 알것 같은데요.. :roll: 데이터 유실은 확실히 아닌것 같습니다.

-----[꼬릿말 절취선 시작]-----
삽질전에 먼저 구글신께 기도하자.
-----[꼬릿말 절취선 끝]-----

iyouhe의 이미지

클라이언트에서 ethereal을 설치한 후 분석해보니 패킷 유실은 없었습니다.

클라이언트 프로그램에서 제대로 처리를 못한 거 였습니다.

아무래도, 윈도우즈 MFC 어싱크로 소켓이 제대로 이벤트를 발생하지 않더던가, 아님 다른 이유로 이벤트 큐가 꽉차서, 드롭되는 거 같습니다.

그치만 위와 같은 상황이라도 이해하기 힘든것이, 100Mbps에서는 정상 동작한 것이, 왜 ADSL망에서 정상적으로 처리하지 못한 걸가요?

배울수 있어서 좋다.

익명 사용자의 이미지

iyouhe wrote:

...
아무래도, 윈도우즈 MFC 어싱크로 소켓이 제대로 이벤트를 발생하지 않더던가, 아님 다른 이유로 이벤트 큐가 꽉차서, 드롭되는 거 같습니다.
...

운영체제의 TCP/IP 프로토콜 스택에서 사용자로 넘기는 과정에서 드롭될 이유가 전혀없습니다. 사용자 프로그램에서의 오류로 보입니다.
MFC가 꼬지긴(개인견해.)했어도, 말씀하신 정도는 아닙니다.
사용자 프로그램이 MFC를 제대로 활용/이용해서 코딩했는지를 검토해야 할것입니다. 즉, 응용단의 에러일 확률이 99.9퍼센트 이상이라고 봅니다.
iyouhe wrote:

...
그치만 위와 같은 상황이라도 이해하기 힘든것이, 100Mbps에서는 정상 동작한 것이, 왜 ADSL망에서 정상적으로 처리하지 못한 걸가요?
...

실험실에서 코딩한 것이(이상적으로 동작하는 경우가 대부분), 실제 필드(험한 세상~)로 나가면 이런 문제가 발생하는 경우가 많습니다. 안정적인 코드는 대체로 실험실 망에서 돌릴때는 투박해 보일 수 있으나, 필드로 나갈때 진가가 나오게 되는 것입니다. 조금 더 노력하시면, 훌륭한 코드로 발전되리라고 믿습니다.

* 참고:
TCP/IP는 물리망에 제한없이(Ethernet, Fast Ethernet, Serial, ATM, ADSL, PARALLEL등) 논리적으로 그 스펙을 보장하는 프로토콜입니다. 이를 보장 못한다면, 이미 TCP/IP가 아니지요.
대체로, 현재 사용되는 TCP/IP프로토콜 스택(논리/소프트웨어 프로토콜임!)은 이러한 정도는 충분히 보장하고 있습니다. 5년정도 이전에는 몇몇 운영체제의 프로토콜 스택이 문제를 내포하고 있었으나(현재 패치되었고), 질문자께서 문제시한 부분이 대두된 적은 없었습니다.

익명 사용자의 이미지

서버와 클라이언트 사이에 시간이 짧아서 그럴수도 있습니다.

서버는 데이터를 읽어서 바로 보내는데.. 클라이언트는 처리를 하다가 다음 데이터가 바로 들어오니깐 이전 데이터는 유실되는 경우도 생기구요
급한대로 저는 보내는 타임을 좀 길게 해서 했더니 일단은 해결이 됬지만 좀더 보완사항입니다.

한번 확인해보세요!

댓글 달기

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