Post

Port, Socket, Connection

server 측 socket programming sequence
1
2
3
4
5
socket()        //socket 생성 파라미터로 넘긴 값들이 socket 구조체에 들어간다.
bind()          //IP와 port 할당
listen()        //대기
accept()

Port / Socket / Connection

A TCP connection is defined by two endpoints aka sockets.

socket은 IP와 port로 정의되는 endpoint다. ( 사실 상태나 프로토콜도 정의 요소에 포함해야 한다. ) 즉, TCP connection은 srcIP:port , dstIP:port( two sockets, 4-tuple )로 정의된다.

하나의 port에 여러 socket이 존재할 수 있다. 단, 둘 이상의 listening socket이 존재한다면 TCP가 dst port만 보고 어떤 프로세스가 segment를 수신할지 결정할 수 없으므로, listen state socket은 유일해야 한다.

RFC 793

A local socket may participate in many connections to different foreign sockets. 이렇게 나와있기는 한데 위의 개념과 전혀 상반되는 내용이고 실제로 이렇게 작용하지도 않으며 프로그래밍에 도움도 안되는 개념이라고 함.

아래와 같이 54.252.94.236(서버)의 80포트에 두개의 connection이 있다고 가정해보자.

1
2
3
TCP    192.168.1.3:63240      54.252.94.236:80       SYN\_SENT
TCP    192.168.1.3:63241      54.252.94.236:80       SYN\_SENT

클라이언트에 2개, 서버 80포트에 2개의 소켓이 각각 존재하는 상황이다. (listen 하고있는 socket은 고려하지 않는다.) 서버가 클라이언트와 송수신하려 할 때 80에 소켓이 둘 이상 존재하므로 어느 소켓으로 송수신 할지 정해야한다. 소켓은 IP와 port로 정의된다고 했다. 그런데 서버 측에서 보면 둘 다 54.252.94.236:80이므로 소켓을 구분할 수 없다. 따라서 서버 측에서는 connection( 4-tuple ) 단위로 송수신 대상을 구별하는 수 밖에 없고 그렇게 되면 소켓이 서로 구별도 안되는데 각 네트워크 객체를 구별하는 식별자로서의 의미는 없는 거 아니냐고 생각할 수 있다.

송수신에서 결국 connection 정보를 확인해야 하는 것은 맞다. 수신의 경우 위에서 기술한 대로 client를 확인해야 어떤 socket이 수신 대상인지 알 수 있고, 송신의 경우 client 주소를 확인해야 IP헤더에 dst IP, port를 적을 수 있으니까.

그러나 지금까지 기술한 내용은 OS에서 각 네트워크 객체를 어떻게 구분하는 지에 대한 얘기다.

송신의 경우, 시야를 좁혀 보면 네트워크 입출력이 실제로 이루어지기 전에 패킷이 발생하는 곳은 각 프로세스 다.

1
2
3
4
TCP    192.168.1.3:63240      54.252.94.236:80       SYN\_SENT    proc1
TCP    192.168.1.3:63241      54.252.94.236:80       SYN\_SENT    proc2

커널의 관점에서 보면 54.252.94.236:80에 대한 소켓이 2개지만 각 프로세스에서 socket 함수 호출 시 socket 구조체를 생성하게 되고 ( 파라미터로 넘긴 값들이 구조체에 들어간다. ) socket descriptor를 반환 받아 socket에 바로 접근할 수 있게 되므로 각각의 프로세스는 한 포트에 대해 소켓이 몇 개나 있는지 알 필요 없이 그냥 socket descriptor를 이용해 데이터를 쓰면 된다.

This post is licensed under CC BY 4.0 by the author.