소켓 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 PortServer 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

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

따라서 데이터 구조는 다른 클라이언트와의 연결을 분리 할 수 ​​있도록 구현됩니다. 에 관해서는 어떻게 그들이 구현하고, 답은이.)는, 소켓 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.