packet이 해당 소켓을 찾아가는 방법은?

ifyou의 이미지

프로그램 만들면서도 그냥 지나치고.. 바쁘다는 핑계로 애써

외면했는데, 시간내서 생각해보니 잘 모르겠더라고요.

간단한 서버 프로그램이라면,

bind();
listend();

while()
{
fd=accept();
thread(fd);
}

이런식으로 되어서, 접속이 일어날때마다 새로운 소켓이 생성되죠.

그런데, 이렇게 새로 생성된 소켓들도 포트 번호는 listend()할때의

포트 번호와 모두 동일한데, 어떤식으로 해서 패킷이 해당 소켓을

정확하게 찾아가는지 모르겠습니다. tcp 헤더를 봐도 별달리 소켓을 구별

하는 부분도 없는 것 같고.. sequence number로 찾아가는지..

mach의 이미지

ifyou wrote:

그런데, 이렇게 새로 생성된 소켓들도 포트 번호는 listend()할때의

포트 번호와 모두 동일한데, 어떤식으로 해서 패킷이 해당 소켓을

정확하게 찾아가는지 모르겠습니다.

답변 : 5 associations에 의해 가능합니다.
님의 예시한 TCP는 5가지 항목의 레코드를 가지게됩니다.
1) 프로토콜
2) 원격지 IP주소
3) 원격지 포트번호
4) 지역 IP주소
5) 지역 포트번호
이 5가지를 5 associations라고 부릅니다.
이 5가지 값들중 단 1개라도 틀리게 가지는 연결은 틀린연결로 인지됩니다.

또한, accept()는 성공적으로 수행한 경우, listen하고 있던 소켓으로 원격지와 연결하는 것이 아니라, accept()에 의해 새로운 소켓을 생성하여 원격지와 연결을 수립하게됩니다. 새로운 소켓을 하나 생성하는것이지요. 서버단에는 그래서 항상 n+1개의 소켓이 존재하게됩니다. 여기서 n은 클라이언트와 연결된 소켓 개수, +1은 listen()하고 있는 소켓이됩니다.(소켓은 socket(), accept()이 두개의 시스템호출로 각각 생성될 수 있습니다요)

따라서, listen()할때(이거 하니까 프로토콜은 이미 tcp라고 보고) 동일한 주소, 포트로 대기해도, 원격지 주소, 원격지 포트는 또 다르겠지요?
그 이유는 원격지 컴퓨터가 틀리다면 IP주소가 일단 틀리니 위 5 associations에 유일한 새로운 연결임을 보장하게 되고.
원격지 컴퓨터가 동일한 경우 IP주소는 같으나, port번호가 틀리게 되기 때문입니다. 보통은 connect()시에 클라이언트 포트부여를 운영체제에게 맡기는 코딩을 많이(대부분) 하지요. 동일 클라이언트 컴퓨터에서 connect()를 다수 수행시 , 운영체제는 새로운 포트번호(비어있는)를 connect()를 호출한 해당 프로세스에게 부여합니다. 따라서, 동일 클라이언트일지라도 클라이언트포트번호는 지속적으로 틀려지게 됩니다.
따라서, 5associations에 새로운 레코드로 인식되게 되어 이를 다른 연결과 구분할 수 있는 새로운 연결로 인식하게 되는 것입니다.
* 참고로, connect() 호출은 내부적으로 port와 바인드하는 루틴을 포함하고 있는데, 이때, 운영체제에게 포트할당을 맡기지 않고 강제로 특정 포트로 바인딩하는 경우가 있습니다.( 물론 흔하지 않은 코딩입니다. )
* 아래 분께서 제 글의 잘못을 지적해 주셔서 황급히 수정합니다. :oops:

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

bellus의 이미지

어라랏? 서버측의 포트가 바뀌는 거였나요?
MACH님의 글에서는 서버측의 포트번호가 바뀌는 걸로 해설을 해두셨네요.

그럼 일반적인 웹서버 80포트로 접속하여 접속이 성공하면 80포트가 아닌 다른 포트랑 통신하는겁니까?
전 서버측의 어드레스나 포트는 동일하게 유지되지만 클라이언트측의 어드레스랑 포트가 틀려져서 소켓의 유일성이 확보되는 걸로 알고 있었는데요..

예를 들어 111.111.111.111 클라이언트에서 3333포트로 222.222.222.222의 80포트에 접속하면
HTTP/111.111.111.1111:3333/222.222.222.222:80 의 유니크한 소켓이 생성되고,,, 같은 클라이언트에서 역시나 같은 서버로 접속하는 경우에는 클라이언트측의 포트가 새로 열려서
HTTP/111.111.111.111:3334/222.222.222.222:80 의 또다른 소켓이 생성되고,,
그러니 어떤 클라이언트에서 222.222.222.222:80으로 접속하면 소켓페어에서 서버측의 어드레스와 포트는 바뀌지 않고 클라이언트측의 어드레스와 포트가 바뀌어서 유일성이 확보되는 거 아닌가요?

mach의 이미지

bellus wrote:
어라랏? 서버측의 포트가 바뀌는 거였나요?
MACH님의 글에서는 서버측의 포트번호가 바뀌는 걸로 해설을 해두셨네요.

그럼 일반적인 웹서버 80포트로 접속하여 접속이 성공하면 80포트가 아닌 다른 포트랑 통신하는겁니까?
전 서버측의 어드레스나 포트는 동일하게 유지되지만 클라이언트측의 어드레스랑 포트가 틀려져서 소켓의 유일성이 확보되는 걸로 알고 있었는데요..

예를 들어 111.111.111.111 클라이언트에서 3333포트로 222.222.222.222의 80포트에 접속하면
HTTP/111.111.111.1111:3333/222.222.222.222:80 의 유니크한 소켓이 생성되고,,, 같은 클라이언트에서 역시나 같은 서버로 접속하는 경우에는 클라이언트측의 포트가 새로 열려서
HTTP/111.111.111.111:3334/222.222.222.222:80 의 또다른 소켓이 생성되고,,
그러니 어떤 클라이언트에서 222.222.222.222:80으로 접속하면 소켓페어에서 서버측의 어드레스와 포트는 바뀌지 않고 클라이언트측의 어드레스와 포트가 바뀌어서 유일성이 확보되는 거 아닌가요?


켁~ 맞습니다요. 글을 수정하도록 하겠습니다.
이런 엄청난 사고를 치다니 --;
읽으신 분들께는 너무 죄송합니다.
3시 24분 후에 수정토록하겠습니다.
단 프로토콜은 http가 아니라 tcp가 맞습니다.
Quote:
HTTP/111.111.111.111:3334/222.222.222.222:80 의 또다른 소켓이 생성되고,,
==>
tcp/111.111.111.111:3334/222.222.222.222:80 의 또다른 소켓이 생성되고,,

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

ifyou의 이미지

그러면, 커널 혹은 소켓 라이브러리 같은 놈이

클라이언트의 IP와 port 번호, 서버(자신)의 ip와 port 번호 등을 참조해서

패킷을 소켓으로 보낸다는 것이네요.

구현의 문제이겠지만, 매번 ip, port번호를 비교해서 패킷과 소켓을 매칭

시킬까요? 아니면, ip, port번호를 기반으로해서 unique한 값을 만들어서

만드나요? 꼭 필요해서 그런것이 아니고, 궁금해서.. :lol:

처음부터 tcp/ip head에 관련 항목이 있었다면 간단했을텐데.. 물론 그러면

또 다른 문제가 생기겠지만요.. 패킷이 랜카드에 도착하면, 그놈 커널로 올리고

ip layer에서 checksum검사하고 tcp layer에서 checksum검사하고, 이 놈이

어느 소켓으로 갈런지 또 연산하고.. 그리고 나서 application으로 올리고..

참 많이도 거치네요 :lol:

커널 소스 보면 알겠지만, 바빠서 시간이 나지를 않으니~ :cry:

mach의 이미지

(참고)
매번 그러할 수 밖에 없습니다.
통신 프로토콜을 이렇게 layering하는 장점은 성능의 관점과는 다르다고 봐야할것입니다.
이러한 프로토콜 처리에 따른 오버헤드를 줄여보고자 한 노력들이 이미 7-8년전에 미국, 유럽 및 국내 대학들에서 시도 되었었습니다. 실험실적이었다고 생각합니다. 여러모로 보아도, 아직은 그리고 아주 먼(?) 미래까지도 tcp/ip의 대안은 없다고 생각합니다. 특정 연구소나 사내의 로컬랜정도에서 다른 프로토콜을 사용하더라도, 결국 게이트웨이에서는 tcp/ip를 지원하지 않을 수 없을테고말입니다.
* 그나마, tcp/ip는 4단계 프로토콜이라고 볼수있지요. osi 7 layer reference model은 말그대로 7단계를 주장합니다.
* TCP/IP보다 훨신 가벼운 프로토콜을 생각해 보는 것은 가능한 것이지만, 이를 대중화 시키는방법을 생각하는것은 불가능에 가깝다고 생각합니다.

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

댓글 달기

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