networking - 프로그램 - 소켓 API accept() 함수는 어떻게 작동합니까?




파이썬 소켓 통신 (3)

내가 이것을 배울 때 혼란 스러웠던 것은 socketport 라는 용어가 물리적 인 것, 실제로는 커널이 네트워킹의 세부 사항을 추상화하는 데 사용하는 데이터 구조 일 뿐이라는 것입니다.

따라서 데이터 구조는 다른 클라이언트의 연결을 분리 할 수 ​​있도록 구현됩니다. 어떻게 구현 되는지 에 대한 대답은 다음 중 하나입니다.) 중요하지 않습니다. 소켓 API의 목적은 구현이 중요하지 않아야한다는 것입니다. 한 가지 구현에 대한 자세한 설명을 제공하는 매우 권장되는 Stevens 서적 외에도 Linux 또는 Solaris 또는 BSD 중 하나에서 소스를 확인하십시오.

소켓 API는 TCP / IP 및 UDP / IP 통신 (즉, 우리가 알고있는 네트워킹 코드)에 대한 사실상의 표준입니다. 그러나 핵심 기능 중 하나 인 accept() 는 약간 마술 적입니다.

세미 형식 정의를 빌리려면 다음을 수행하십시오.

accept ()는 서버 측에서 사용됩니다. 원격 클라이언트로부터 새로운 TCP 연결을 작성하기 위해 수신 된 수신 시도를 승인하고이 연결의 소켓 주소 쌍과 연관된 새 소켓을 작성합니다.

즉, accept 는 서버가 새로 연결된 클라이언트와 통신 할 수있는 새 소켓을 반환합니다. 기존 소켓 ( accept 가 호출 된)은 동일한 포트에서 새로운 연결을 수신 대기 상태로 유지됩니다.

accept 은 어떻게 작동합니까? 어떻게 구현됩니까? 이 주제에 많은 혼란이 있습니다. 많은 사람들이 accept가 새로운 포트를 열 것이라고 주장하며,이를 통해 클라이언트와 통신합니다. 그러나 이것은 분명히 새로운 포트가 열리지 않기 때문에 사실이 아닙니다. 실제로 다른 클라이언트와 동일한 포트를 통해 통신 할 수 있지만 어떻게 할 수 있습니까? 여러 스레드가 같은 포트에서 recv 를 호출 할 때 데이터가 어디로 가는지 어떻게 알 수 있습니까?

소켓 디스크립터와 관련된 클라이언트 주소의 줄을 따라 뭔가를 추측하고 recv 통해 데이터가 올 때마다 올바른 소켓으로 라우트되지만 확실하지 않습니다.

이 메커니즘의 내부 동작에 대한 철저한 설명을 얻는 것이 좋습니다.


다른 사람이 말했듯이, 소켓은 4- 튜플 (클라이언트 IP, 클라이언트 포트, 서버 IP, 서버 포트)에 의해 고유하게 식별됩니다.

서버 IP에서 실행되는 서버 프로세스는 활성 소켓의 데이터베이스 (테이블 / 목록 / 트리 / 배열 / 매직 데이터 구조의 종류는 상관하지 않음)를 유지하고 서버 포트에서 수신 대기한다는 것을 의미합니다. 서버의 TCP / IP 스택을 통해 메시지를 받으면 데이터베이스와 클라이언트 IP 및 포트를 확인합니다. 클라이언트 IP 및 클라이언트 포트가 데이터베이스 항목에서 발견되면 메시지는 기존 처리기로 전달되고 그렇지 않으면 새 데이터베이스 항목이 만들어지고 새 소켓 핸들러가 생성되어 해당 소켓을 처리합니다.

ARPAnet 초창기에 특정 프로토콜 (FTP는 하나의 프로토콜)은 연결 요청에 대해 지정된 포트를 수신하고 핸드 오프 포트로 응답합니다. 그 연결을위한 추가 통신은 핸드 오프 포트를 거쳐야합니다. 이것은 패킷 당 성능을 향상시키기 위해 수행되었습니다. 컴퓨터는 그 당시에는 몇 배 더 느려졌습니다.


소켓이 Server IP : Server Port로 식별된다고 생각하면 혼란 스러울 것입니다. 실제로 소켓은 4 중 정보에 의해 고유하게 식별됩니다.

Client IP : Client PortServer IP : Server Port

따라서 Server IP와 Server Port는 허용되는 모든 연결에서 일정하지만 클라이언트 측 정보는 모든 것이 진행되는 곳을 추적 할 수있게 해줍니다.

사물을 명확히하는 예 :

서버가 192.168.1.1:80이고 두 개의 클라이언트가 10.0.0.1과 10.0.0.2라고 가정 해보십시오.

10.0.0.1은 로컬 포트 ​​1234에서 연결을 열고 서버에 연결합니다. 이제 서버에는 다음과 같이 식별되는 하나의 소켓이 있습니다.

10.0.0.1:1234 - 192.168.1.1:80

이제 10.0.0.2는 로컬 포트 ​​5678에서 연결을 열고 서버에 연결합니다. 이제 서버에는 다음과 같이 식별되는 두 개의 소켓이 있습니다.

10.0.0.1:1234 - 192.168.1.1:80
10.0.0.2:5678 - 192.168.1.1:80





tcp