서버와 클라이언트가 연결하는 방법

c4fiber·2023년 12월 21일
0

SW사관학교 정글7기

목록 보기
30/49

client -> connect() 수행 시 진행 시퀀스


  • listenfd의 file descriptor를 3으로 추측하는 이유는 0(stdin), 1(stdout), 2(stderr)를 제외하고 3번이 유력하기 때문이다.
  • connfd가 적어도 file descriptor 3이 아닌 이유는 file descriptor은 원칙적으로 겹칠 수 없고, 요청이 들어온 client를 위해 새 file descriptor를 생성해서 전달했기 때문이다 (4로 유추할 수 있다.)

다수의 클라이언트가 연결을 요청할 경우


모든 클라이언트는 서버의 열린포트(listenfd)를 통해서 connect를 요청한다.
서버가 accept를 하면 서버 내부에 각 client에 배정된 소켓을 생성하고 매핑한다.

이 내용을 이해하면서 착각했던 부분이 서버는 내부에서 사용하는 포트번호를 전달하지 않는다.

  • 클라이언트에게 각 하나의 포트를 할당하여 연결해주는데 그 포트번호로 통신해라! 라면서 소켓 번호를 전달해주는 걸로 이해했다. 하지만 방화벽 필터링이 걸려있다면? 그 클라이언트는 운이 나빠서 서버와 통신할 수 없는 것이다.
  • 확인해보니 서버 내부에서 각 클라이언트를 위한 소켓을 매핑하는 것은 사실이지만 accept()이후에도 클라이언트는 계속 열린 포트(ex 8080)를 통해 소통한다.
  • 서버 내부에서 특정 클라이언트로 부터 데이터가 왔음을 확인하고 (ip + port 조합) 매핑된 소켓으로 데이터를 전달하면 서버는 클라이언트를 인식하는 것이다.

이해가 안되는 부분이 아직 남아있는데 어차피 ip+port 조합으로 클라이언트를 식별할 수 있는데 포트를 하나 할당해두는건 낭비가 아닌가? 이다.

하지만 해당 클라이언트의 정보를 포함하고 있는 소켓을 생성하고, 이를 관리하기 위해서는 내부포트번호를 매핑해서 관리해야한다. 자세한 부분은 다음 단락에서 다루겠다.

네, 클라이언트 식별 과정에 대해 더 자세히 설명하겠습니다. 서버가 accept() 함수를 호출하여 클라이언트의 연결 요청을 수락할 때, 서버는 클라이언트와의 통신을 위한 새로운 소켓을 생성합니다. 이 소켓은 클라이언트를 식별하는 데 사용되는 중요한 정보를 포함하고 있습니다.

클라이언트 식별 과정은 다음과 같습니다:

  1. 클라이언트의 연결 요청: 클라이언트가 서버의 IP 주소와 포트로 연결을 시도합니다. 예를 들어, 클라이언트의 IP가 192.168.1.10이고, 서버의 IP가 192.168.1.20, 서버의 포트가 8080이라고 가정해 봅시다.
  1. 서버에서의 accept() 호출: 서버가 accept() 함수를 호출하면, 클라이언트의 연결 요청을 수락합니다. 이 함수는 새로운 소켓을 반환합니다. 이 새로운 소켓은 클라이언트의 연결에 대한 정보를 가지고 있습니다.
  1. 소켓 주소 정보: 새로운 소켓은 클라이언트의 고유한 소켓 주소 정보를 포함합니다. 이 정보는 클라이언트의 IP 주소와 클라이언트가 사용하는 포트 번호로 구성됩니다. 예를 들어, 클라이언트가 자신의 로컬 포트 12345를 사용하여 서버에 연결했다고 가정하면, 새로운 소켓의 주소 정보는 192.168.1.10:12345가 됩니다.
  1. 고유한 연결 식별: 이제 서버는 클라이언트의 IP 주소(192.168.1.10)와 포트 번호(12345) 조합을 사용하여 클라이언트를 고유하게 식별합니다. 이 조합은 네트워크상에서 해당 클라이언트와의 연결을 구별하는 데 사용됩니다.
  1. 데이터 교환: 서버는 이 새로운 소켓을 통해 특정 클라이언트와 데이터를 주고받습니다. 서버가 여러 클라이언트로부터 데이터를 받을 때, 각 데이터 패킷의 출처 IP 주소와 포트를 확인하여 올바른 소켓에 데이터를 전달합니다.

이러한 방식으로, 서버는 각각의 클라이언트와의 연결을 구별하고 관리할 수 있습니다. 클라이언트의 IP 주소와 포트 번호는 각 연결을 유일하게 식별하는 데 중요한 역할을 합니다.

왜 서버는 클라이언트 마다 개별 포트를 열어줄까?


이 그림에서 틀린 부분은 전용포트를 갖다줘 이다.
실제로 포트를 전달하지는 않고 내부적으로 소켓정보를 보유하면서 listenfd로 들어온 데이터를 식별하는 용도로 사용한다.

나는 여기서 이런 생각이 들었다. listening port로 들어온 데이터를 식별하기 위해 클라이언트 정보 + 내부 포트 번호를 가진 소켓을 찾아 매핑해주는 방식인가?
또한 서버가 response를 보낼 때 내부 포트번호를 사용하는가?

답은 아니다. 클라이언트를 식별하기 위해 내부포트번호를 소켓에 부여하고 관리하고 있는건 맞지만, 핵심역할은 클라이언트의 ip + port 정보이지 내부포트번호가 아니다.

이 내부 포트번호의 사용처는 몇가지가 있는데
연결 상태관리, 데이터 흐름제어, 보안 및 인증, 자원 및 데이터 제한, 로그 및 모니터링 등이 있다.

아래는 chatGPT의 답변이다

서버 내부에서 현재 활성화된 연결의 개수를 파악하는 것 외에도, 서버 내부의 소켓과 관련된 정보는 다른 여러 목적으로도 사용됩니다. 여기에는 다음과 같은 중요한 기능들이 포함됩니다:

  1. 연결 상태 관리: 서버는 각 소켓의 상태를 추적합니다. 이는 연결이 활성화되어 있는지, 비정상적으로 종료되었는지, 아직 데이터를 기다리고 있는지 등의 상태를 포함할 수 있습니다.
  1. 데이터 흐름 제어: 서버는 특정 소켓을 통한 데이터 흐름을 관리하고, 필요에 따라 흐름을 제어할 수 있습니다. 이는 네트워크 대역폭 관리, 오류 제어, 데이터 병목 현상 방지 등을 위해 중요합니다.
  1. 보안 및 인증: 특정 연결에 대한 보안 및 인증 절차를 관리할 때, 서버는 해당 소켓의 정보를 사용합니다. 이를 통해 특정 클라이언트의 신원을 확인하거나, 암호화된 통신을 설정할 수 있습니다.
  1. 자원 할당 및 제한: 서버는 각 소켓에 대해 필요한 시스템 자원(메모리, 파일 디스크립터 등)을 할당하고, 필요에 따라 이러한 자원의 사용을 제한할 수 있습니다.
  1. 로그 및 모니터링: 네트워크 활동을 기록하고 문제를 진단하기 위해, 서버는 각 소켓을 통한 데이터 전송 및 연결 상태에 대한 정보를 로깅할 수 있습니다.
  1. 비동기 처리 및 이벤트 기반 프로그래밍: 서버는 비동기 소켓 I/O 또는 이벤트 기반 프로그래밍 모델을 사용하여 효율적으로 네트워크 요청을 처리할 수 있으며, 이때 각 소켓의 상태와 이벤트를 관리합니다.

따라서 서버의 내부 소켓과 관련된 정보는 단순히 활성화된 연결의 개수를 파악하는 것 이상의 여러 중요한 용도로 사용됩니다. 이러한 정보는 서버의 성능, 안정성, 보안 및 유지 관리에 핵심적인 역할을 합니다.

참고자료


chatGPT 답변 링크
https://chat.openai.com/share/465b3027-70fb-4db9-ab8c-8c387d195674

profile
amazing idiot

0개의 댓글