소켓 API accept () 함수는 어떻게 작동합니까?


126

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

반 공식적인 정의를 빌리려면 :

accept ()는 서버 측에서 사용됩니다. 원격 클라이언트에서 새 TCP 연결을 만들기 위해 수신 된 수신 시도를 수락하고이 연결의 소켓 주소 쌍과 관련된 새 소켓을 만듭니다.

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

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

소켓 설명자와 연결되는 클라이언트 주소의 줄을 따라가는 것 같고 데이터가 올 때마다 recv올바른 소켓으로 라우팅되지만 확실하지 않습니다.

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


2
따라서 모든 클라이언트 요청에 대해 서버 끝에서 새로운 소켓 연결이 열립니다. 들어오는 호출을 수신하려면 서버가 항상 80에 열려 있어야합니다. 호출을 받으면 즉시 아래에 언급 된 4 개의 튜플이있는 NEW 소켓을 생성하여 클라이언트와 서버간에 TCP 연결을 만듭니다. 내 이해가 맞습니까?
— 두뇌 폭풍

1
이것은 매우 근본적인 질문이며 저는 최근 인터뷰에서 이것에 대해 테스트를 받았습니다 : stackoverflow.com/questions/24871827/… 이것에 대한 의견이 있으면 게시하십시오
— brain storm

@brainstorm HTTP 연결 유지의 존재를 완전히 무시하는 경우에만 해당됩니다.
— Marquis of Lorne

답변:


140

당신의 혼란은 소켓이 서버 IP : 서버 포트로 식별된다는 생각에 있습니다. 실제로 소켓은 4 개의 정보로 고유하게 식별됩니다.

Client IP : Client Port 과 Server IP : Server Port

따라서 허용되는 모든 연결에서 서버 IP와 서버 포트는 일정하지만 클라이언트 측 정보는 모든 것이 진행되는 위치를 추적 할 수 있도록합니다.

사물을 명확히하는 예 :

에 서버 하나 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

3
구현 세부 사항 (플랫폼마다 다를 수 있음)을 모르지만 개념적으로 소켓이 내가 설명한 정보의 사 중선에 의해 식별된다는 것을 알고 있습니다.
— 17 of 26

3
이것에 대한 언급이 있습니까?
— qeek

3
임의의 질문 : NAT가 사용 중이고 동일한 네트워크에있는 두 클라이언트가 서버에 연결할 때 동일한 로컬 포트를 사용하려고하면 어떻게됩니까? 예를 들어 10.0.0.1과 10.0.0.2가 모두 외부 IP가 192.168.0.1 인 라우터에 연결된 경우 192.168.1.1의 서버는 192.168.0.1에서 두 개의 연결을 확인합니다. 난수 생성기의 우연에 의해 10.0.0.1과 10.0.0.2가 동일한 로컬 포트를 선택하면 어떻게됩니까?
— aroth

4
라우터의 NAT 지원이 세부 사항을 처리합니다. 네트워크 트래픽은 실제로 클라이언트에서 라우터로, 라우터에서 서버로의 두 연결을 통해 이동합니다. 라우터는 두 개의 다른 포트 192.168.0.1:1234 및 192.168.0.1:5678에서 나가는 연결을 만듭니다. 그런 다음 들어오는 트래픽은 라우터에 의해 올바른 클라이언트로 리디렉션됩니다.
— 17 of 26

3
소켓이 사 중선으로 식별되는 경우 청취 소켓의 사 중선 정보는 무엇입니까?
— Eric Zheng

74

사용자 "17/26"이 제공 한 답변에 추가하기 위해

소켓은 실제로 5 개의 튜플 (소스 IP, 소스 포트, 대상 IP, 대상 포트, 프로토콜)로 구성됩니다. 여기서 프로토콜은 TCP 또는 UDP 또는 모든 전송 계층 프로토콜이 될 수 있습니다. 이 프로토콜은 IP 데이터 그램의 '프로토콜'필드에있는 패킷에서 식별됩니다.

따라서 서버의 서로 다른 응용 프로그램이 정확히 동일한 4- 튜플에서 동일한 클라이언트와 통신하지만 프로토콜 필드가 다른 경우가 가능합니다. 예를 들면

서버 측의 Apache (TCP의 server1.com:880-client1:1234) 및 World of Warcraft (UDP의 server1.com:880-client1:1234)

클라이언트와 서버 모두 다른 4 개의 필드가 모두 동일하더라도 두 경우 모두 IP 패킷의 프로토콜 필드가 다르므로이를 처리합니다.


13

제가 이것을 배울 때 저를 혼란스럽게했던 것은 용어 socket와 port그것들이 물리적 인 것임을 암시한다는 것이 었 습니다. 사실 그것들은 네트워크의 세부 사항을 추상화하기 위해 커널이 사용하는 데이터 구조 일뿐입니다.

따라서 데이터 구조는 다른 클라이언트와의 연결을 분리 할 수 ​​있도록 구현됩니다. 에 관해서는 어떻게 그들이 구현하고, 답은이.)는, 소켓 API의 목적은 구현이 단지 모양이없는 문제 또는 b합니다.) 정확하게하는 것이 문제가되지이다 않습니다 중 하나입니다. 하나의 구현에 대한 자세한 설명을 제공하는 강력 추천 Stevens 책 외에도 Linux 또는 Solaris 또는 BSD 중 하나의 소스를 확인하십시오.


예, 대부분의 네트워킹 용어는 특정 비트 모음과 해당 값 ( "프로토콜 식별자", "라우팅", "바인딩", "소켓"등)을 기반으로 한 결정에 이름을 할당하는 것입니다. 네트워크 카드의 모든 하드웨어 는 수신하도록 설계된 비트 스트림입니다. 컴퓨터의 프로그램과 관련하여 발생하는 일은 드라이버와 OS에 의해 결정됩니다. 우리는 우리가 원하는 경우 그 용어 내일을 모두 제거하기 만 수의 비트 스트림을 전달하는 원리 보인다 근본적인 ...
— masterxilo

-1

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

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

ARPAnet의 초기에는 특정 프로토콜 (FTP)이 연결 요청에 대해 지정된 포트를 수신하고 핸드 오프 포트로 응답했습니다. 해당 연결에 대한 추가 통신은 핸드 오프 포트를 통해 이동합니다. 이는 패킷 당 성능을 개선하기 위해 수행되었습니다. 당시 컴퓨터는 몇 배 더 느 렸습니다.


'핸드 오프 포트'부분에 대해 자세히 설명해 주시겠습니까?
— Eli Bendersky

1
이것은 일부 pre-TCP 프로토콜에 대한 설명이거나 지나치게 단순화되었습니다. 리스닝 소켓에 연결을 시도하는 클라이언트는 연결을 설정하기 위해 특수 패킷을 보냅니다 (SYN 비트 세트). 새 소켓을 만드는 패킷과 기존 소켓을 사용하는 패킷 사이에는 분명한 차이가 있습니다.
— John M

... 연결을 설정하기 위해 특수 패킷을 보냅니다 (SYN 비트 세트). 내가 이해하는 것처럼 프로토콜 스택이 '리스너'(있는 경우)에게 제공하므로 주소 / 포트 / 프로토콜 조합 당 수신 포트가 하나만있을 수 있습니다. 이것이 사양에 있는지 또는 단순히 구현 규칙에 있는지 확실하지 않습니다.
— Peter Wone

1
두 번째 단락은 TCP 계층 또는 서버 프로세스 내에서 발생하는 일을 올바르게 설명하지 않습니다. 서버 프로세스는 어떤 종류의 소켓의 데이터 구조를 유지하거나 들어오는 IP : 포트 쌍을 어떤 것에 대해서도 확인할 필요가 없습니다. 그것이 소켓이있는 이유입니다. FTP는 모든 '추가 통신'이 아닌 데이터에 대해 별도의 포트를 사용하며 성능상의 이유가 아니라 프로토콜을 단순화하기 위해 수행됩니다. 어떤 식 으로든 성능을 향상시키지 않으면 서 새 포트를 사용합니다.
— Marquis of Lorne

"데이터베이스를 유지합니다 (즉, 어떤 종류의 테이블 / 목록 / 트리 / 배열 / 매직 데이터 구조를 사용하든 상관 없습니다).":) 저는 보통 이것을 "테이블"(또는 "그래프"또는 "의사 결정 트리"라고 부릅니다.) ). "데이터베이스"는 나에게 일부 구현을 제안합니다.
— masterxilo
당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.