[질문] 네트워크 소켓에서 질문 있습니다

hados의 이미지

일을 하다가 문제점이 있어서 글을 올리니다.

네트워크를 통해서 UDP로 패킷을 받아서 파일로 저장을 하려고 합니다

프로그램은 뭐...매우 간단하죠. 보통 소켓 프로그래밍 예제 수준의

100줄 정도의 프로그램을 짜서, 패킷을 받아서 파일로 저장하도록

짰습니다.

그런데 가끔씩 data에 손실이 생깁니다.

sender에서 보낸 파일 크기와 receiver 쪽에서 받은 파일의 크기가

약간 차이가 날 때가 있습니다.

지금 생각으로는

sender에서 보낸 파일이 버퍼에 저장되고, receiver 프로그램이

이 버퍼에서 데이터를 읽어와서 파일로 저장하는데,

이 버퍼의 크기가 작고, sender 에서 보내는 속도와

receiver 쪽에서 data를 가져가는 속도에 차이가 나서

버퍼 오버플로우가 나서 거기서 데이타가 좀 손실되지 않나

생각하고 있습니다.

문제가 이것이라고 할 때,

socket을 열면서 setsockopt() 함수를 써서 소켓 버퍼를

늘려주는 방법을 썼었는데, 무작정 이 버퍼를 늘려주기만

하면 되는건가요?

소켓 버퍼를 한 100MB 로 잡아도 소켓 버퍼가 그만큼 잡힐 거

같지도 않고, 또 limit가 있다면 어디에 있는지,

아니면 아예 다른 방법으로 접근해야 하는지

감이 잘 안잡히네요

고수님들의 조언 바랍니다 :)

kalstein의 이미지

UDP는...out of order 입니다 -_-;

순서가 뒤죽박죽 올수있고...게다가 중간에 빠질수도 있습니다...

파일전송엔 지극히 좋지않습니다 :)

TCP로 쓰세요~ 아니면 UDP를 굳이 쓰시겠다면....

Reliable하게 Application Protocol을 다 정의해서 seq_num등을

부여해서 만드셔야 할겁니다.


------------------------------------------
Let`s Smart Move!!
http://kalstein.tistory.com/

mach의 이미지

udp는 사용자 영역이 아닌 커널(운영체제)에서 필요시(불가피시) 패켓을 버리기도 합니다. 사용자가 열심히 파라메터를 세팅하고 노력해도 신뢰성 있는 송수신을 보장받지 못한다는 얘기입니다.

다른 목적이 없다면, tcp를 사용하면 그런 문제가 없어지겠지만, 반드시 udp를 써서 파일전송등 신뢰성있는 데이터전송을 하고 싶다면, 신뢰성부분을 응용프로그램수준에서 구현해보는 방법(순서조정, 중복처리, 재전송, 타임아웃 등등)이 있습니다.

신뢰성, reliable, reliability , udp를 키워드로 kldp에서 검색해보시면 좋은 답변들이 다수개 있으리라고 봅니다.

------------------ P.S. --------------
지식은 오픈해서 검증받아야 산지식이된다고 동네 아저씨가 그러더라.

spacelee의 이미지

두 모듈이 통신한다고 할때
받는쪽 모듈의 속도가 보내는쪽 보다 항상 빠르다는 보장이 없으면
큐잉 버퍼를 늘려줘도 언젠가는 문제가 생깁니다.
queuing theory라는 간단한 수학 분야에서 증명이 된 내용입니다.

따라서 버퍼크기를 늘리는건 해답이 안되고
위엣분 말씀처럼 TCP를 이용하시던지,
udp를 이용해서 tcp처럼 만드시던지 해야 합니다.
tcp에는 기본적으로 받는쪽의 속도가 느릴 경우
보내는 쪽에 천천히 보내라고 하는 기능이 포함되어 있습니다. (flow control)

권위를 의심할 것,어긋남을 존경할 것,자리잡기를 거부할 것,항상 자신을 재창조할 것 - MIT 미디어랩 -

freezm7의 이미지

Quote:

소켓 버퍼를 한 100MB 로 잡아도 소켓 버퍼가 그만큼 잡힐 거

같지도 않고, 또 limit가 있다면 어디에 있는지,

아니면 아예 다른 방법으로 접근해야 하는지

감이 잘 안잡히네요

setsocketopt 로 100MB 를 잡으신 후, 다시 getsocketopt 로 확인하시면 얼마나 잡혔는지 아실 수 있겠죠..

근데 버퍼 늘려서 해결할 수 있는 문제는 아닌 것 같습니다.
유한이라는 점에서는 100MB 든 1G 든 버퍼에 쌓이는 속도가 더 빠르면 언젠가는 바닥 날테니까요.
flow control 기능이 있는 tcp 를 쓰시든지, udp 상에서 자체적으로 flow control 을 구현하시던지 해야할 듯.. (말하다 보니 윗분들이랑 같은 말이네요 헉..)

즐겁게 살아 볼까나~*

pynoos의 이미지

버퍼를 늘일수도 있지만
프로토콜 설계하실 때, 받는 쪽에서 offset을 보내면, 보내는쪽은 그 뒤로 계속 보낸다고 하고,
패킷하나 보낼때, offset, size, 마지막 패킷인지의 여부를 주어서 계속 전송하게 한다음,
받는 쪽에서 중간에 하나 빠지면 그 빠진 곳의 offset을 한번씩 보내면 될 것 같습니다.

hados의 이미지

답변 감사합니다. :)

여러분의 답변이 다 비슷한것으로 보아

tcp를 쓰거나 프로토콜을 tcp처럼 만드는 것이 왕도인듯 합니다...만

제가 제 상황을 그리 많이 쓰지 않은 것이 문제군요. -_-;;;

현 상황에서 sender 쪽은 건드릴 수가 없습니다.

저는 sender 프로그램 등등을 받아서 일을 하는 상태여서

sender 쪽을 수정할 수도 없고, udp대신 tcp를 쓸 수도 없습니다.

이런 상황이므로 sender 를 만든 쪽과 협의해서

tcp를 쓴다거나 sender를 좀 수정한다거나 하는 식으로 해결하던지

아니면 현 상황에서 끝을 내야 겠네요 ㅠㅠ

답변 감사합니다 :)

댓글 달기

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