서버는 보낼 클라이언트 포트를 어떻게 알 수 있습니까?


26

내가 알기로 이것은 클라이언트가 연결 요청을 할 때 발생합니다.

  1. 서버는 특정 포트 번호에 바인딩됩니다. 포트 번호는 항상 청취 프로세스에 바인딩됩니다. 서버 만이 들어오는 연결을 수신하고 있기 때문에 클라이언트 쪽에서 바인딩 할 필요가 없습니다.
  2. 서버는 해당 포트 번호에서 수신 대기 상태를 유지합니다.
  3. 클라이언트가 connect()요청 을 보냅니다 .
  4. 서버는를 사용하여 요청을 수락합니다 accept(). 즉시 서버가 클라이언트 요청, 추가의 서버에 임의의 포트 번호 커널 할당 받아으로 send()하고 receive(), 서버에 동일한 포트 번호를 청취뿐만 아니라 보내는 데 사용할 수 없기 때문에, 이전 포트가 여전히를 새로운 연결 청취

이 모든 것을 감안할 때 서버는 클라이언트가 수신하는 포트를 어떻게 알 수 있습니까? 클라이언트가 소스 포트와 대상 포트가있는 TCP 세그먼트를 전송한다는 것을 알고 서버는 해당 세그먼트의 소스 포트를 대상 포트로 사용하지만 서버는 해당 포트에 대해 어떤 기능을 호출합니까? 그렇 accept()습니까?


답변:


33

패킷에서 TCP (또는 UDP 등) 헤더의 일부입니다. 따라서 서버는 클라이언트가 알려주기 때문에 알아냅니다. 이는 클라이언트의 IP 주소 (IP 헤더의 일부)를 찾는 방법과 유사합니다.

예를 들어, 모든 TCP 패킷에는 IP 헤더가 포함됩니다 (적어도 소스 IP, 대상 IP 및 프로토콜 [TCP] 포함). 그런 다음 TCP 헤더가 있습니다 (소스 및 대상 포트와 함께).

커널은 원격 IP 10.11.12.13 (IP 헤더) 및 원격 포트 12345 (TCP 헤더)의 SYN 패킷 (TCP 연결 시작)을 수신하면 원격 IP 및 포트를 인식합니다. . SYN | ACK를 다시 보냅니다. ACK를 다시 listen받으면 호출은 새 소켓을 반환하고 해당 연결에 대해 설정됩니다.

TCP 소켓은 4 가지 값 (원격 IP, 로컬 IP, 원격 포트, 로컬 포트)으로 고유하게 식별됩니다. 최소한 하나의 연결이 다른 한 여러 연결 / 소켓을 가질 수 있습니다.

일반적으로 로컬 포트와 로컬 IP는 서버 프로세스에 대한 모든 연결에서 동일합니다 (예 : sshd에 대한 모든 연결은 local-ip : 22에 있음). 하나의 원격 시스템이 여러 개의 연결을 수행하는 경우 각 원격 시스템은 서로 다른 원격 포트를 사용합니다. 따라서 원격 포트를 제외한 모든 것은 동일하지만 괜찮습니다. 4 개 중 하나만 달라야합니다.

예를 들어 wirehsark를 사용하여 패킷을 볼 수 있으며 모든 데이터에 레이블을 지정합니다. 다음은 강조 표시된 소스 포트입니다 (디코딩 된 패킷에서 강조 표시되고 맨 아래의 16 진 덤프).

TCP SYN 패킷을 보여주는 Wireshark


u는 accept () 이후에 얻은 새 서버 소켓 설명자 (예 : 튜플)에 클라이언트 포트 및 클라이언트 주소 세부 정보가 있고 해당 새 소켓 설명자 서버가 데이터를주고 받는다는 의미입니다. 새로운 소켓 파일 디스크립터는 커널, 서버 IP, 클라이언트 IP 및 클라이언트 포트에 의해 할당 된 새로운 서버 포트 번호를 갖게 될 것입니다.
수비 수레시

@SubiSuresh 예, 튜플은 해당 파일 디스크립터와 관련된 커널 내부에 저장됩니다.
derobert

> 감사합니다 derobert. 그래서 새 서버 소켓 설명자에 클라이언트 포트와 클라이언트 주소가있을 것입니다. 서버가 accept ()에서 가져옵니다. 내 이해가 옳습니까?
수비 수레시

@SubiSuresh 예, 맞습니다. 응용 프로그램 관점에서는 일반적으로 신경 쓰지 않습니다 (로깅 제외). 커널은 사용자 write등 의 데이터 가 올바른 위치에 있는지 확인합니다 .
derobert

> 도와 주셔서 감사합니다. ;-)
수비 수레시

2

"연결 요청 ( connect()일반적으로 클라이언트 프로그램의 시스템 호출)은 3 방향 핸드 셰이크를 발생시킵니다. 3 방향 핸드 셰이크 의 첫 번째 패킷 (클라이언트에서 서버로)은 SYN 플래그를 설정하며 클라이언트 프로그램의 TCP 포트 번호를 포함합니다. 커널이 할당합니다.

이것은 Nmap vs Natural SYN 패킷 에 관한 기사에서 볼 수 있습니다 . Nmap SYN 패킷 디코딩에는 "source.60058> dest.22"라는 문구가 있습니다. "합법적 인 SYN 패킷"디코딩에는 "source.35970> dest.80"이라는 문구가 있습니다. 2 개의 SYN 패킷은 패킷이 각각 TCP 포트 60058 및 포트 35970에 있음을 원격 커널에 알려줍니다.


그러나 백엔드에서 발생하는 Bruce. 그러나 서버가 클라이언트 서버 프로그램에서 포트 번호와 같은 세부 정보를 정상적으로 가져 오는 방법은 클라이언트 포트와 클라이언트 주소를 가져 오는 기능을 보지 못했습니다.
Subi Suresh

시스템 호출 getpeername()을 통해 열린 소켓에서이를 수행 할 수 있습니다. accept()서버 코드가 다시 클라이언트로 통신 할 소켓의 파일 기술자를 얻기 위해 사용하는 것이 시스템 호출은 잠재 고객의 IP 주소와 TCP 포트 번호를 포함 (내 남자 페이지에서 "SOCKADDR") 매개 변수가 있습니다.
Bruce Ediger

> 내가 elloborate. 걱정하지 마십시오. 내가 얻은 모든 입력에서 accept ()는 클라이언트 세부 사항으로 채워진 sockaddr_in 구조를 가지고 있으며 accept () 이후에 반환 된 새 서버 소켓 설명자는 자동으로 클라이언트 포트와 주소를 갖습니다. 그래서 우리는 send (새로운 서버 소켓 설명자)를 사용하여 보낼 수 있습니다.이 시점까지는 희망입니까? 이것은 내가 이해 한 것이 옳은지 확인하는 것입니다.
수비 수레시

@SubiSuresh-당신이 진실을 썼다고 믿습니다.
브루스 Ediger

1

TCP 소켓은 스트림 지향 소켓입니다. 두 개의 소켓 설명자 (귀하와 동료가 소유)가 안정적으로 연결되어 있습니다. 따라서 클라이언트 포트에 대해 걱정할 필요가 없습니다. 소켓 설명자를 작성하십시오!

또한 (아마도 로깅을 위해) 정말로 알고 싶다면 getsockname (2)을 사용하십시오.


0

연결은 튜플 (소스 IP, 소스 포트, 대상 IP, 대상 포트)로 정의됩니다. 답은 그 반대입니다.


@vondrand 그 시점에서 von을 이해했지만 클라이언트 포트 번호에 대해 서버가 알 수있는 기능은 무엇입니까? 클라이언트 포트 번호를 알지 못하면 서버는 accept ()의 구조를 사용하여 클라이언트를 가져옵니다 포트 ?
Subi Suresh
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.