tcp 소켓 통신.......

ahj35의 이미지

tcp 소켓 통신에서 select 함수를 사용하고 있습니다.
데이터를 두개 따로 받아야 되는데 이 두 데이터를 합쳐서 하나로 받고 있습니다...
항상 이런 현상이 일어나는 것은 아님니다..다만 자주 일어 나긴 하지만요..
tcpdump를 사용해서 주고 받는 패킷을 보니 분명히 따로 존재하고 있는데 왜 이런 현상이 일어나는 걸까요??
아시는분 답변 해주세요 ㅠ.ㅠ
:cry:

펑키의 이미지

안녕하세요

질문이 너무 포괄적이어서 다른분도 대답해드리기 조금 힘들듯 싶습니다. 조금 자세히 더 알려주시겠어요.??

지금 제가 대충 알아 들을수 있는것은

1.
A (두번 보냄) -------> B(한번에 다 받음)

2.
A(하나보냄) ------> C (각각의 것은 한개로 합쳐서 받음)
B(하나보냄) ------>

1번의 경우에는 두개를 보냈다면 데이터를 구분하는 부분이 존재하는지 확인하시면 될겁니다. 예를 들면 데이터 구분자라던지 데이터 사이즈라던지 말입니다. 두가지 정도면 확실히 알아 낼수가 있습니다.

2번의 경우에는 SELECT 안에서 FD 핸들 하는 부분이 조금 잘못 된듯 싶습니다. RECV하는 FD를 한번 프린트 해보시는것은 어떨까요.?

즐거운 하루 되세요.

ahj35의 이미지

1.
A (두번 보냄) -------> B(한번에 다 받음)

제가 질문 하고싶은 것이 1번의 경우입니다...
실행 파일이 A, B 두개가 있습니다.
A가 특정 포트를 열어놓고 기다립니다.

A먼저 실행시키고 B를 실행시키면 제대로 두개다 받습니다.. 당연히 따로...
그런데 B를 실행 시키고 나서 A를 실행시키면 1번의 경우가 자주 발생합니다..
가끔 제대로 받을 때도 있습니다..
답변에서

====1번의 경우에는 두개를 보냈다면 데이터를 구분하는 부분이 존재하는지 확인하시면 될겁니다. 예를 들면 데이터 구분자라던지 데이터 사이즈라던지 말입니다. 두가지 정도면 확실히 알아 낼수가 있습니다. ======

이라고 했는데 무슨뜻인지 잘 모르겠습니다...

해결방법이 있을까요??

22:17:30.180093 localhost.33003 > localhost.smux: S 2457502841:2457502841(0) win 32767 <mss 16396,sackOK,timestamp 4678918 0,nop,wscale 0> (DF)
4500 003c e17f 4000 4006 5b3a 7f00 0001
7f00 0001 80eb 00c7 927a 8479 0000 0000
a002 7fff 91b9 0000 0204 400c 0402 080a
0047 6506 0000 0000 0103 0300
22:17:30.180131 localhost.smux > localhost.33003: S 2471086925:2471086925(0) ack 2457502842 win 32767 <mss 16396,sackOK,timestamp 4678918 4678918,nop,wscale 0> (DF)
4500 003c 0000 4000 4006 3cba 7f00 0001
7f00 0001 00c7 80eb 9349 cb4d 927a 847a
a012 7fff cdc3 0000 0204 400c 0402 080a
0047 6506 0047 6506 0103 0300
22:17:30.180161 localhost.33003 > localhost.smux: . ack 1 win 32767 <nop,nop,timestamp 4678918 4678918> (DF)
4500 0034 e180 4000 4006 5b41 7f00 0001
7f00 0001 80eb 00c7 927a 847a 9349 cb4e
8010 7fff 36e1 0000 0101 080a 0047 6506
0047 6506
22:17:30.181462 localhost.33003 > localhost.smux: P 1:31(30) ack 1 win 32767 <nop,nop,timestamp 4678918 4678918> (DF)
4500 0052 e181 4000 4006 5b22 7f00 0001
7f00 0001 80eb 00c7 927a 847a 9349 cb4e
8018 7fff e336 0000 0101 080a 0047 6506
0047 6506 601c 0201 0006 0a2b 0601 0401
9975 0102 0504 097a 6562 6f73 2d35 2e33
0400

22:17:30.181524 localhost.smux > localhost.33003: . ack 31 win 32767 <nop,nop,timestamp 4678918 4678918> (DF)
4500 0034 ae48 4000 4006 8e79 7f00 0001
7f00 0001 00c7 80eb 9349 cb4e 927a 8498
8010 7fff 36c3 0000 0101 080a 0047 6506
0047 6506
22:17:30.181538 localhost.33003 > localhost.smux: P 31:47(16) ack 1 win 32767 <nop,nop,timestamp 4678918 4678918> (DF)
4500 0044 e182 4000 4006 5b2f 7f00 0001
7f00 0001 80eb 00c7 927a 8498 9349 cb4e
8018 7fff 9f7a 0000 0101 080a 0047 6506
0047 6506 620e 0606 2b06 0102 010e 0201
ff02 0102

22:17:30.181548 localhost.smux > localhost.33003: . ack 47 win 32767 <nop,nop,timestamp 4678918 4678918> (DF)
4500 0034 ae49 4000 4006 8e78 7f00 0001
7f00 0001 00c7 80eb 9349 cb4e 927a 84a8
8010 7fff 36b3 0000 0101 080a 0047 6506
0047 6506

위의 데이터는 서로 주고 받는 패킷내용입니다...
위에 붉은색으로 표시한 부분이 실제적으로 받고자 하는 데이터 입니다.....

펑키의 이미지

안녕하세요.

제가 정확히 이해했는지 모르지만... 아니시라면 다시 올려 주세요. 하여간..

패킷의 프로토콜을 디자인 하실때 보내고자 하는 패킷의 크기를 반드시 지정해서 보내주시는게 안전하게 송/수신하는 첫걸음입니다. 보통의 경우에는 프로토콜을 디자인할때 헤더+바디 이런식으로 설정해서 전송하는 편입니다. 이때 헤더의 크기는 정해져있고 바디의 크기는 헤더에서 바디의 크기를 지정해서 보내줍니다. 이러면 수신시에 해더부(지정된 사이즈)를 먼저 받아서 읽어 본후 바디부의 크기를 알수가 있으므로 이만큼만!! 받게 됩니다. 여러가지 방법이 있으나 대체적으로 보통 이렇게 사용합니다. 또 다른 방법은 데이터의 끝을 알리는 구분자를 포함해서 전송하는데 이럴 경우에는 조금더 복잡해지지만 가능하기도 합니다.

예를 들어 보면

typedef _header{

char nTraceNumber[4];
char nBodyLen[4];

}
int나 뭐 이런식으로 선언하셔도 되지만 플렛폼마다 걸리는 바이트 패딩 문제가 생깁니다. 그냥 편하게....

이렇게 헤더는 8바이트의 크기를 갇게 되고 보내는 쪽에서 먼저 이 헤더부를 보내고 그 다음에 바디부를 전송하게 됩니다. 그러면 받는 쪽에서 헤더부 8바이트를 먼저 읽어 보고 나머지 크기를 설정해서 받을수가 있습니다.

헤더 바디 크기가 지정되어 있다면 더욱 손쉽게 받을수가 있겠죠. 그렇지 않다면 어디부터 어디까지가 이번에 전송된것인지 아닌지 판단하기가 까다롭습니다. TCP/IP의 특성을 다시 한번 보면

1. 반드시 전송이 된다.
2. 언제 전송될지는 모른다.

2번에 주목해 보시면 4000바이트를 지금 전송했을때 받는쪽에서 저것을 한번에 받지 않고 100 바이트만 먼저 받고 계속 대기할수가 있습니다. 혹은 보내는쪽에서 2000 바이트씩 두번 전송된 전혀 다른 데이터인데 받는쪽에서는 한번에 4000 바이트를 받을수도 있습니다.

즐거운 하루 되세요.

불량청년의 이미지

자세한 얘긴 윗분이 다 얘길 해주셨는데요.

쉽게 생각하자면

write(sd, "a", 1);
write(sd, "b", 1);

서버에서 이렇게 보내주면 클라이언트도

read(sd, buf1, 1);
read(sd, buf2, 1);

꼭 이렇게 받으라는 법은 없습니다.

read(sd, buf3, 2);

이렇게 한번에 받을 수도 있죠.

왜냐하면 경계가 없는 TCP_STREAM으로 데이터가

전달 됨으로(스트림 : 데이터의 경계가 없다), 이런

현상이 발생 되는 것입니다.

윗 분이 말씀하셨듯이 데이터를 구분할 수 있는 구분자를

데이터 중간중간에 넣어주면 해결이 될 수 있고, 아니면

전달될 데이터의 싸이즈를 수신측에 우선 알려주고 해도

될것입니다. 그것도 안된다면 송/수신측 데이터 버퍼를 이리

약속하시고 하셔도 될것입니다.

H/W가 컴퓨터의 심장이라면 S/W는 컴퓨터의 영혼이다!

ahj35의 이미지

수신하는 쪽에서 데이터를 받기 전까지 데이터 사이즈를 알수가 없습니다..
그래서 데이터 사이즈를 정할수가 없습니다..
그리고 송신측은 어떻게 수정할수 없는 상태입니다...
수정을 한다면 수신측을 수정해야 합니다..

합쳐진 데이터를 받아서 두개로 나눠서 해봤지만 문제가 좀 생겨서 이렇게도 할수가 없습니다.. 두 데이터를 각각 받아서 처리해야 합니다....
이문제를 어떻게 하면 해결 할수 있을까요...

펑키의 이미지

안녕하세요.

그러시면 혹시 데이터의 시작과 끝 둘중에 하나라도 구분할수 있는 정보는 받으실수 있으시나요.? 그러시다면 그 방법을 이용하는 것이지만 이것도 완전히 할수 있는것은 아니고 조금 불안합니다. 조금 뭐랄까 경우의 수가 많아서저 이것 저것 귀찮아 지거든요. 하여간 그나마 그것이 존재하면 어느정도 만들어 내실수는 있을겁니다.

불량청년의 이미지

말씀하시는 것을 곰곰히 생각해 보니 서버측의 코드는 수정할 수 없는

특별한(?) 상황 같군요.

어쩔 수 없습니다. 프로토콜이란것이 이래서 존재하는 것이고 서버에서

어떤 프로세스를 거쳐 어떤 데이터를 전달하는지는 자세히 모르겠지만,

서버(송신측)의 프로토콜을 아셔야 클라이언트(수신측)에서 그 데이터를

가공할 수 있습니다.

도움이 못 된거 같네요. 분명히 해결책은 존재할 텐데... 힘내세요~

H/W가 컴퓨터의 심장이라면 S/W는 컴퓨터의 영혼이다!

댓글 달기

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