본문 바로가기
네트워크 및 서버 & 웹

[TCP/IP] 소켓 통신 공부한 것 정리

by 문톰 2022. 2. 6.

이글을 읽기전 알아야 할 개념

https://aal-izz-well.tistory.com/entry/%ED%8F%AC%ED%8A%B8%EC%99%80-%EC%86%8C%EC%BC%93%EC%9D%98-%EC%B0%A8%EC%9D%B4-%EB%B0%8F-%ED%98%B8%EC%8A%A4%ED%8A%B8

 

포트와 소켓의 차이 및 호스트

오늘은 소켓과 포트의 차이에 대해서 공부한 것을 정리해보겠습니다. 먼저 소켓과 포트에 대해서 설명하기 위해 호스트에 대해서 설명하겠습니다. 1.호스트 -네트워크 주소[IP 주소]가 할당된 노

aal-izz-well.tistory.com

 

 

1.클라이언트 소켓과 서버소켓 

-서버 소켓과 클라이언트 소켓은 태생적으로 구조가 다른 별개의 구조가 아닌 동일한 구조이다.

-소켓의 역할과 구현 절차 구분을 위해 다르게 부르는 것일 뿐 전혀 다른 형태의 소켓이 아니다.

-역할에 따라 처리되는 흐름, 호출되는 API 함수의 종류와 순서들이 다를뿐이다.

-소켓 통신을 하기위해서는 서버에서 포트를 열어야 한다. 

 

 

1)클라이언트 소켓 

-서버에 요청을 보내서 응답을 받거나 혹은 서버에 요청을 보내지 않아도 실시간으로 서버의

응답을 받는 소켓 

 

2)서버 소켓

-실시간으로 클라이언트의 요청을 받아서 응답을 보내는 소켓

 

3)HTTP 통신과의 차이 

-HTTP 통신은 클라이언트가 요청을 보낼때만 서버에 응답을 받을 수 있지만 

소켓통신의 경우에는 클라이언트가 요청을 보내지 않아도 실시간으로 서버가 클라이언트에게 응답을 보낼 수 있다.

EX) HTTP 통신 -> 무전기    소켓통신 -> 핸드폰 통화 

 

-만약 채팅을 HTTP 통신으로 만든다면 다른 사람이 보낸 채팅을 확인하기 위해서 계속 새로고침을 눌러야 할 것이다.

 

여담이지만 카톡의 경우 초창기에  빨리 만들어서 사용자들을 확보하기위해 HTTP 통신으로 채팅을 만들고 다른 사용자가 보낸 메세지를 실시간으로 확인하기 위해서 몇초에 한번씩 계속 새로고침을하여 실시간 통신을 하는 것처럼 둔갑시켰다. 

 

 

 

 

 

2.소켓 통신의 실행 흐름

1)클라이언트 소켓

생성(Socket) -> 연결(Connect) -> 송수신(Send/Recv) -> 닫기(Close)

 

 

1-1) 클라이언트 소켓 생성(socket())

-TCP 소켓은 (Stream)타입 UDP 소켓은(Datagram)타입으로 소켓의 타입을 지정할 수 있다.

(물론, 좀 더 다양한 소켓 옵션(family, raw)들이 존재하지만, 여기서는 따로 언급하지 않습니다.)

-최초 소켓이 만들어지는 시점에는 어떠한 "연결 대상"에 대한 정보도 들어있지 않고 껍데기뿐인

소켓이 만들어져있다.

-연결 대상(서버 IP: PORT)을 지정하고 연결 요청을 하기 위해서는 생성한 소켓을 사용하여 connect() API를 호출해야 한다.

 

1-2)연결 요청(Connect)

-connect() API는 "IP주소"와 "포트번호"로 서버에 연결요청을 보냅니다.

-Block 방식(연결 요청에 대한 결과가 결정되기 전에는 실행되지 않음)으로 동작합니다.

-connect() API가 실행되자마자 실행 결과와 관계없이 무조건 리턴될것이라고 가정하면 안된다.

-connect() API 호출에 성공하면 이제 send()/recv() API를 통해 데이터를 주고받을 수 있다.

 

1-3)데이터 송수신(send()/recv())

-연결된 소켓을 통해 데이터를 보낼 때는 send(), 데이터를 받을 때는 recv() API를 사용한다.

-send()와 recv() API가 모두 블럭방식으로 동작하므로 실행 결과(성공, 실패, 종료)가

결정되기 전에는 API 실행결과가 리턴되지 않는다.

-특히 recv()는 데이터를 수신하거나 에러가 발생하기 전에는 실행이 종료되지 않는다.

(데이터를 수신하는 경우 통신 대상이언제, 어떤 데이터를 보낼 것인지 특저알 수 없기 때문에 

recv()API가 한번 실행되면 언제 끝날지 모르는 상태가 되는 것입니다.)

-수신을 위한 recv() API는 별도의 스레드에서 실행합니다. 소켓의 생성과 연결이 완료된 후

새로운 스레드를 만든 후 그곳에서 recv()를 실행하고 수신되길 기다린다.

 

1-4)소켓닫기(Close())

-더이상 데이터 송수신이 필요없게되면 소켓을 닫기 위해 close() API를 호출한다.

-close()에 닫힌 소켓은 더이상 유효한 소켓이 아니기 때문에 닫힌 소켓을 다시 사용하여 데이터를

송수신할 수 없습니다.

-만약 소켓 연결이 종료된 후 다시 데이터를 주고받으려면 또 한번의 소켓 생성(socket())과 연결(connect())과정을 거쳐서 소켓이 데이터를 송수신할 수 있는 상태가 되어야 한다.

 

 

2)서버 소켓

-서버소켓을 처리하는 과정은 Bind()와 Listen()이 추가되어있습니다.

생성(Sokcet) -> 결합(Bind) -> 주시(Listen) -> 받아들이기(Accept) -> 송수신(Send/Recv) -> 닫기(Close)

 

2-1)서버소켓생성(socket())

-클라이언트 소켓과 마찬가지로 서버 소켓을 사용하려면 최초에 소켓을 생성해야한다.

-최초 소켓이 만들어지는 시점에는 어떠한 "연결 대상"에 대한 정보도 들어있지 않고 껍데기뿐인

소켓이 만들어져있다.

 

2-2)서버 소켓 바인딩(bind())

-bind는 "결합하다", "묶다", "구속하다"등의 사전적 의미를 가지고 있습니다.

-bind() API를 사용해서 인자에 소켓과 포트 번호(또는 IP주소 + 포트 번호)를입력해서 생성한

소켓과 결합시킵니다.

-운영체제가 특정한 포트 번호를 서버 소켓이 사용하도록 만들기 위해 소켓과 포트번호를 결합(Bind)해야 하므로 이 떄 bind() API를 사용한다.

* 포트번호가 중복되는 경우 

-각 서버소켓은 시스템이 관리하는 포트(0~65535)중 하나의 포트번호를 사용하게된다.

만약 서버소켓이 사용하는 포트번호가 다른 서버소켓의 포트번호와 중복된다면 어떤 소켓에 Accept()해서 데이터를 처리할지 알 수 없다.

ex) 10000번 포트를 사용하는 여러개의 소켓이 있는 경우 

-이런 이유로 운영체제에선 소켓들이 중복된 포트번호를 사용하지 않게 내부적으로 포트번호와 소켓연결 정보를 관리합니다. (만약 지정된 포트번호를 다른 소켓이 사용한다면 bind() API는 에러를 리턴합니다.)

 

2-3)클라이언트 연결 요청 대기(listen())

-클라이언트에 의한 연결 요청이 수신될 때까지 기다리는 것을 수행

-서버 소켓에 바인딩된 포트번호로 클라이언트의 연결 요청이 있는지 확인하며 대기하는 상태 

-클라이언트에서 connect() API를 통해 연결 요청을 수신받은 후 대기 상태를 종료하고 성공 or 실패에 대한

반환값을 리턴

-클라이언트 연결 요청에 대한 정보는 시스템 내부적으로 큐(Queue)에서 쌓이게 되는데 이 시점에서 클라이언트와의 연결은 아직 완전히 연결되지 않은 대기 상태입니다.

 

*listen() API가 주로 대기상태를 빠져나오는 상황

1)클라이언트 요청이 수신되는 경우

2)에러가 발생하는 경우

 

 

2-4)클라이언트 연결 수립(accept())

-listen() API가 클라리언트의 연결 요청을 확인하고 문제없이 리턴한다고 해서 클라이언트와의 연결 과정이

완료된 것이 아니다. 

-최종적으로 클라이언트와의 연결 요청을 받아들여 소켓간의 연결을 수립하는 역할을 수행

-최종적으로 데이터 통신을 위해 연결되는 소켓이 앞서 bind()또는 listen() API에서 사용한 서버소켓이 아니고accept() API 내부에서 새로 만들어지는 소켓이다.

-서버 소켓의 핵심역할은 소켓에 포트 번호를 바인딩하고 요청 대기큐(Queue)를 생성하여 클라리언트의 요청을 대기하는 것이고 accept() API에서 데이터 송수신을 위한 새로운 소켓을 만들고 서버 소켓의 대기 큐에 쌓여있는 첫 번째 연결

요청을 매핑시킨다.

 

2-5)데이터 송수신(send()/recv())

-클라이언트 소켓에서 처리되는 과정과 동일

 

2-6)소켓 연결 종료(close())

-클라이언트 소켓에서 처리되는 과정과 동일

 

 

서버와 클라이언트가 소켓통신이 연결된 그림

 

참고

https://recipes4dev.tistory.com/153

 

소켓 프로그래밍. (Socket Programming)

1. 소켓(Socket) 만약 네트워크와 관련된 프로젝트를 진행하면서, 사용자(User)의 관점이 아닌, 개발자(Developer)의 관점에서 네트워크를 다뤄본 경험이 있다면, "소켓(Socket)"이라는 용어가 아주 낯설

recipes4dev.tistory.com

 

댓글