[완료] TCP 패킷이 늦게 도착하는 현상을 디버깅 하고 있습니다.

hados의 이미지

(일단 윈도우 환경입니다만, 네트워크 관련 내용인듯 하여 감히? 올립니다. 양해바랍니다 ^^)

24시간 돌아가는 C# 어플리케이션을 개발하여 운영중입니다.

TCP 통신으로 약 10초 ~ 몇 분 마다 한번씩 100 바이트도 채 안되는 데이터를 받아서

해당 데이터를 파싱하여 그에 따라 일을 수행하는 역할입니다. (윈도우즈7 에 닷넷 2.0 환경이며, 하드웨어 리소스는 아주 남아 돕니다.)

네트워크 구성은 기가빗으로 인터넷과 연결안된 내부망입니다. 연결된 기기도 20대 될까말까 입니다.

문제는 하루에 1~200번 정도 명령을 받아서 수행하는데, 어쩌다 한번씩

Sender 측에서 명령을 보낸지 수 초 후에 명령을 받아서 처리하는 경우가 있다는 겁니다.

이게 정확한 시간에 명령을 수행해야 하는데, socket.receive() 에서 리턴되는 시각 자체가 수 초 후이다 보니까 문제가 됩니다.

어플리케이션 자체도 그리 CPU 사용을 절대 많이 하는 것도 아니고,

윈도우즈 자체도 해당 순간에 이벤트 로그를 봐도 별다른 일을 하는게 없습니다. (V3 도 안 깔았습니다.)

다들 제가 만든 어플리케이션에서 thread 를 잘못 돌려서 그렇겠지...라고 하고 있습니다.

소켓 열어서 데이터 받는 부분은 BackgroundWorker (간편화된 thread) 로 따로 돌리며, socket.receive() 함수로

(blocking, receive timeout 은 무한대로 설정) 데이터를 받아서 처리합니다.

네트워크가 잠시 끊어졌다거나 하면 로그를 다 남기는데, 그런 로그도 전혀 없습니다.

그래서 http://www.microolap.com/products/network/tcpdump/ 에서 tcpdump 프로그램을

받아서 어플리케이션과 함께 돌렸습니다. 패킷 자체가 늦게 도착한다는 것을 보여주려고 로그를 함께 남겼습니다.

참고로 socket.receive() 를 호출하지 않아도, 지정된 포트로 데이터가 들어오면 tcpdump 에서

시간지체 없이 패킷 정보를 출력해 주는 것은 확인하였습니다.

현재는 tcpdump 로 돌려서 패킷 도착 로그를 남긴 것과 제 어플리케이션에서 데이터를 받은 시각은 일치합니다.

하지만 sender 측과 시간차이가 거의 10초 정도까지 나는 경우가 하루에 몇 차례씩 발생합니다.

도대체 어디를 의심하고 디버깅해야 하는 걸까요?

C# 어플리케이션 안에서 제가 잘못한 건지, 네트워크 문제인지, 등등도 잘 알수가 없습니다.

다만 저는 tcpdump 결과와 제 어플리케이션 로그가 일치하니 제 문제는 아니라고 말하고 싶습니다만,

어쨌거나 문제는 해결해야 하다 보니 막막하네요.

고수님들께서 제한된 정보지만, 조언 조금씩이라도 해 주시면 감사하겠습니다.

런맨의 이미지

말씀하신 내용으로 봐서는

우선 tpcdump를 데이타를 보내는 컴터에도 설치해봐서 실제로 나가는 시간도 확인 해봐야할거같습니다.

그럼 그시간도 정확하면 공유기나 허브를 교체해보심이^^
이건 설정할수가 있는 장빈지 모르겠네요^^

아님 보내는 쪽을 의심해봐야겠네요.
시간 딜레이나는 pc가 일정하면 그놈만 점검하면되겠지만
그 pc가 일정하지 않으면 보내는 pc쪽에
network 설정에서 재전송 설정을 짧게하여서 해결해보심이
어떨지 모르겠네요^^

인생은 도박이다.

hados의 이미지

아무래도 send 해 주는 쪽에다가도 tcpdump 를 해봐야 겠습니다.
그런데 이미 네트웍 스위치를 한번 교체한 상태라서 또 할수 있을지 모르겠네요 ^^

그런데 network 설정에서 재전송 설정을 짧게 한다는게 어떤 설정을 말씀하시는건지 모르겠습니다.
조금만 더 설명해 주시면 감사하겠습니다.

런맨의 이미지

네트워크 설정이라고 말씀드린것은 보내는 쪽이나 받는 쪽에
문제가 없다면 아무래도 패킷이 네트워크상에서 붕떠려린거같아서
보내는 쪽에서 리눅스같은걸 보면 syn패킷을 보내고 응답이 없을 때
재전송을 생각한건데

님 글을 다시보니 소켓이 맺어지고 받는것에서 딜레이가 생기니
제 글을 도움이 안되겠네요 ㅠㅠㅠㅠ

인생은 도박이다.

onhachoe의 이미지

혹시 네트워크 자체가 flood되고 있지는 않은지요?

hados의 이미지

절대 그럴 일은 없을 것 같습니다만,

네트워크 자체가 flood 되는지는 무엇으로 확인하면 좋을까요?

관련된 쪽까지는 경험이 부족해서 잘 모르겠습니다.

조금만 더 설명해 주신다면 정말 감사하겠습니다 ^^

snowall의 이미지

당연히 두 컴퓨터 사이에 시간은 동기화 되어 있겠죠? 이건 그냥 설마 해서 던져 봅니다 -_-

제가 이런 상황이라면...

그냥 매 1초마다 sender에서 명령어가 없는 빈 패킷이라도 무조건 던지도록 할 것 같네요.

윈도우즈 기본 방화벽 문제일지도 모르고요..

별 도움은 안되는 댓글 같아서 죄송하네요.

피할 수 있을때 즐겨라! http://melotopia.net/b

hados의 이미지

두 컴퓨터 사이에 시간이 꼭 동기화 되어 있어야 하나요?

몇 초 정도는 틀릴 수가 있는데, 그럴 경우 문제가 되기도 하는지요??

gilgil의 이미지

[구분]
thread1 : recv()를 호출하는 thread(user thread)
thread2 : 상대방(송신자)로부터 tcp data를 받아 오는 thread(kernel thread)

[thread1의 구조]

while (not connected)
{
  log("bef log");
  buf = recv();
  log("aft log");
  process(buf);
  log("aft process");
}

tcpdump를 이용하였을 때 수신부에서 packet에 제시간에 도착을 한다고 해도, thread1이 제대로 처리를 해 주지 않는다고 한다면(thread1의 process에서 load가 걸리게 되면) 당연히 해당 packet(data)를 처리해 주지 못하는 경우가 발생할 수 있습니다.

[디버깅 방법]
위의 코드와 같이 log 함수를 이용하여 recv, process 사이 사이에 어디에서 hang이 걸리는지에 대한 log를 남겨 보시기 바랍니다.

hados의 이미지

답변 감사합니다.

일단 위에 적어놓으신 코드와 거의(!) 똑같은 식으로 로그를 남기고 있습니다만, process(buf) 에서 홀딩되는 경우는 없었습니다.

문제되는 경우는 모두
log("bef log"); 를 남기고 난 후,
recv() 에서 blocking 되어 있으면서 홀딩되어 있는 경우였습니다.

정리하자마녀 recv() 와 process() 사이에서 홀딩이 아니라,
log("bef log") 와 recv() 사이에서 홀딩되는 상황입니다.

gilgil의 이미지

아, 그리고 window size도 확인해 보세요. 수신부가 송신부에게 window size를 작은 값(예를 들면 zero)을 보내게 되면 송신부는 data를 보낼 수가 없게 되어서 hang이 걸릴 것처럼 작동할 수 있습니다.

hados의 이미지

답변 주신분들 감사합니다.
며칠간의 tcpdump 잠복? 끝에, 전송측에서 delay 가 발생한 것을 확인하였습니다.

어플리케이션에서는 1, 2, 3 번 패킷을 보냈는데,
tcpdump 상에서는 1번 패킷은 그대로 보내고, 2번과 3번 패킷은 합쳐서 하나의 패킷으로 보냈더군요.

그래서 2번 패킷의 경우 약 10초 이상 delay 가 생겨버렸습니다.

sender 측에서도 Sync 방식으로 데이터를 전송했고, 정상적으로 전송했음을 확인했는데도 이렇네요.

질문 사항은 새로 글을 올리도록 하고, 일단 이쪽 쓰레드는 멈추겠습니다 :)

gilgil의 이미지

application에서 1,2,3번 패킷을 보냈는데 tcpdump상으로 2,3 번 패킷이 늦게 나갔다고 한다면

1. 수신측에 송신측에게 보내는 tcp header의 window size가 0에 수렴을 해서 송신측에 수신측에게 tcp data를 보내는 것이 지연이 생겨 버렸다.
2. packet loss가 나서 송신측에서 수신측으로 data를 retransmit했다.

등의 원인이 있을 수 있습니다.

오리뎅이의 이미지

2,3번 패킷이 합쳐져서 전송된 원인은 Application이 원인이었나요? 아니면, TCP layer 그 이하 커널 스택이 원인이었나요?

익명 사용자의 이미지

5년 전 글에 질문을 다시 하셔도 질문자가 올 확률이 그렇게 높지는 않아 보입니다. 다음에는 글 쓰기 전에 날짜를 꼭 확인하세요.

twinwings의 이미지

TCP_NODELAY를 이용해서 버퍼에 쌓아 한번에 보내지 않고 보내는 방법이 있는 듯 합니다.

http://www.buggymind.com/310

이 문서에 되게 자세히 나와있네요. 원인분석과 해결방법까지. 참고가 될만한 자료 인 듯합니다.

댓글 달기

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