code

TCP : 두 개의 다른 소켓이 포트를 공유 할 수 있습니까?

codestyles 2020. 8. 31. 07:48
반응형

TCP : 두 개의 다른 소켓이 포트를 공유 할 수 있습니까?


이것은 매우 기본적인 질문 일 수 있지만 저를 혼란스럽게합니다.

두 개의 서로 다른 연결된 소켓이 포트를 공유 할 수 있습니까? 저는 10 만 개 이상의 동시 연결을 처리 할 수있는 애플리케이션 서버를 작성 중이며 시스템에서 사용할 수있는 포트 수가 약 60k (16 비트)라는 것을 알고 있습니다. 연결된 소켓은 새 (전용) 포트에 할당되므로 여러 소켓이 동일한 포트를 공유 할 수없는 경우 동시 연결 수가 포트 수에 의해 제한됩니다. 그래서 질문입니다.

미리 도와 주셔서 감사합니다!


서버 소켓은 단일 포트에서 수신 대기합니다. 해당 서버에 설정된 모든 클라이언트 연결은 연결 의 서버 측에있는 동일한 수신 포트와 연관됩니다 . 설정된 연결은 클라이언트 측 및 서버 측 IP / 포트 쌍의 조합으로 고유하게 식별됩니다. 동일한 서버의 다중 연결은 서로 다른 클라이언트 측 IP / 포트 쌍과 연결되어있는 한 동일한 서버 IP / 포트 쌍을 공유 할 수 있으며, 서버 는 사용 가능한 시스템 리소스가 허용하는 한 많은 클라이언트를 처리 할 수 ​​있습니다. 에.

클라이언트 측 , 그것은 새로운 아웃 바운드 연결이 임의 사용에 대한 일반적이다 클라이언트 측 당신이 짧은 시간에 많은 연결을 할 경우 사용 가능한 포트 밖으로 실행하는 것이 가능하다이 경우 포트.


포트에서 TCP / HTTP 수신 : 여러 사용자가 동일한 포트를 공유하는 방법

그렇다면 서버가 TCP 포트에서 들어오는 연결을 수신하면 어떻게 될까요? 예를 들어 포트 80에 웹 서버가 있다고 가정합니다. 컴퓨터의 공용 IP 주소가 24.14.181.229이고 연결을 시도하는 사람의 IP 주소가 10.1.2.3이라고 가정합니다. 이 사람은 24.14.181.229:80에 대한 TCP 소켓을 열어 귀하에게 연결할 수 있습니다. 충분히 간단합니다.

직관적으로 (그리고 잘못) 대부분의 사람들은 다음과 같이 보인다고 가정합니다.

    Local Computer    | Remote Computer
    --------------------------------
    <local_ip>:80     | <foreign_ip>:80

    ^^ not actually what happens, but this is the conceptual model a lot of people have in mind.

클라이언트의 관점에서 볼 때 그는 IP 주소가 있고 IP : PORT에서 서버에 연결하기 때문에 직관적입니다. 클라이언트가 포트 80에 연결되었으므로 그의 포트도 80이어야합니까? 이것은 생각하기에 현명한 일이지만 실제로 일어나는 일은 아닙니다. 그게 맞다면 외부 IP 주소 당 한 명의 사용자 만 서비스 할 수 있습니다. 원격 컴퓨터가 연결되면 그는 포트 80을 포트 80으로 연결하고 다른 사람은 연결할 수 없습니다.

다음 세 가지를 이해해야합니다.

1.) 서버에서 프로세스는 포트에서 수신 대기 합니다. 일단 연결되면 다른 스레드로 넘깁니다. 통신은 청취 포트를 절대로 잡아 먹지 않습니다.

2.) 연결은 다음 5- 튜플 (로컬 IP, 로컬 포트, 원격 IP, 원격 포트, 프로토콜)에 의해 OS에서 고유하게 식별됩니다. 튜플의 요소가 다른 경우 이것은 완전히 독립적 인 연결입니다.

3.) 클라이언트가 서버에 연결할 때 사용되지 않는 임의의 상위 소스 포트를 선택 합니다. 이러한 방식으로 단일 클라이언트는 동일한 대상 포트에 대해 최대 64k까지 서버에 연결할 수 있습니다.

따라서 이것은 클라이언트가 서버에 연결할 때 실제로 생성되는 것입니다.

    Local Computer   | Remote Computer           | Role
    -----------------------------------------------------------
    0.0.0.0:80       | <none>                    | LISTENING
    127.0.0.1:80     | 10.1.2.3:<random_port>    | ESTABLISHED

실제로 일어나는 일보기

먼저 netstat를 사용하여이 컴퓨터에서 무슨 일이 일어나는지 살펴 보겠습니다. 80 대신 포트 500을 사용할 것입니다 (일반 포트이기 때문에 포트 80에서 많은 일이 발생하지만 기능적으로는 차이가 없기 때문입니다).

    netstat -atnp | grep -i ":500 "

예상대로 출력이 비어 있습니다. 이제 웹 서버를 시작하겠습니다.

    sudo python3 -m http.server 500

이제 다음은 netstat를 다시 실행 한 결과입니다.

    Proto Recv-Q Send-Q Local Address           Foreign Address         State  
    tcp        0      0 0.0.0.0:500             0.0.0.0:*               LISTEN      - 

이제 포트 500에서 능동적으로 수신하는 프로세스 (상태 : LISTEN)가 하나 있습니다. 로컬 주소는 0.0.0.0이며 "모든 IP 주소 수신"을위한 코드입니다. 쉬운 실수는 현재 컴퓨터의 연결 만 허용하는 127.0.0.1 포트에서만 수신하는 것입니다. 따라서 이것은 연결이 아닙니다. 이것은 프로세스가 포트 IP에 bind ()를 요청했고 해당 프로세스가 해당 포트에 대한 모든 연결을 처리 할 책임이 있음을 의미합니다. 이것은 포트에서 수신 대기하는 컴퓨터 당 하나의 프로세스 만있을 수 있다는 제한을 암시합니다 (멀티플렉싱을 사용하여이를 우회하는 방법이 있지만 이것은 훨씬 더 복잡한 주제입니다). 웹 서버가 포트 80에서 수신 대기하는 경우 해당 포트를 다른 웹 서버와 공유 할 수 없습니다.

이제 사용자를 컴퓨터에 연결해 보겠습니다.

    quicknet -m tcp -t localhost:500 -p Test payload.

This is a simple script (https://github.com/grokit/quickweb) that opens a TCP socket, sends the payload ("Test payload." in this case), waits a few seconds and disconnects. Doing netstat again while this is happening displays the following:

    Proto Recv-Q Send-Q Local Address           Foreign Address         State  
    tcp        0      0 0.0.0.0:500             0.0.0.0:*               LISTEN      -
    tcp        0      0 192.168.1.10:500        192.168.1.13:54240      ESTABLISHED -

If you connect with another client and do netstat again, you will see the following:

    Proto Recv-Q Send-Q Local Address           Foreign Address         State  
    tcp        0      0 0.0.0.0:500             0.0.0.0:*               LISTEN      -
    tcp        0      0 192.168.1.10:500        192.168.1.13:26813      ESTABLISHED -

... that is, the client used another random port for the connection. So there is never confusion between the IP addresses.


A connected socket is assigned to a new (dedicated) port

That's a common intuition, but it's incorrect. A connected socket is not assigned to a new/dedicated port. The only actual constraint that the TCP stack must satisfy is that the tuple of (local_address, local_port, remote_address, remote_port) must be unique for each socket connection. Thus the server can have many TCP sockets using the same local port, as long as each of the sockets on the port is connected to a different remote location.

See the "Socket Pair" paragraph at: http://books.google.com/books?id=ptSC4LpwGA0C&lpg=PA52&dq=socket%20pair%20tuple&pg=PA52#v=onepage&q=socket%20pair%20tuple&f=false


Theoretically, yes. Practice, not. Most kernels (incl. linux) doesn't allow you a second bind() to an already allocated port. It weren't a really big patch to make this allowed.

Conceptionally, we should differentiate between socket and port. Sockets are bidirectional communication endpoints, i.e. "things" where we can send and receive bytes. It is a conceptional thing, there is no such field in a packet header named "socket".

Port is an identifier which is capable to identify a socket. In case of the TCP, a port is a 16 bit integer, but there are other protocols as well (for example, on unix sockets, a "port" is essentially a string).

The main problem is the following: if an incoming packet arrives, the kernel can identify its socket by its destination port number. It is a most common way, but it is not the only possibility:

  • Sockets can be identified by the destination IP of the incoming packets. This is the case, for example, if we have a server using two IPs simultanously. Then we can run, for example, different webservers on the same ports, but on the different IPs.
  • Sockets can be identified by their source port and ip as well. This is the case in many load balancing configurations.

Because you are working on an application server, it will be able to do that.

참고URL : https://stackoverflow.com/questions/11129212/tcp-can-two-different-sockets-share-a-port

반응형