SY 개발일지
article thumbnail

프로젝트를 진행하면서 채팅 등 실시간 기능을 이용해보신 분이라면 웹소켓에 대해서 들어보신 적이 있으실 겁니다.

이번 포스팅에서는 저번 포스팅에 이어 소켓이 어떻게 통신하는지에 대해 정리해보겠습니다

 

웹소켓에 대한 설명은 다음 포스팅을 참고해주세요🥰

https://soyeonnnb.tistory.com/74

 

[CS] WebSocket이란 ?

프로젝트를 진행하며 채팅 기능이 필요할 시 웹소켓을 통해 연결하는 경우가 많습니다. 따라서 웹소켓의 개념에 대해 한번 정리해보고자 합니다.웹소켓이란웹소켓은 두 프로그램 간의 메세지

soyeonnnb.tistory.com

파일이란?

소켓에 대해 알기 위해서는 파일에 대해 먼저 알아야 합니다.

파일이란 무엇일까요 ?? 아마 파일에 대해서는 다들 알고있지만, 정확하게 무엇이다 ! 라고 대답은 잘 할 수 없을 것 같습니다.

 

파일은 컴퓨터가 저장하고 있는 데이터입니다.

 

저희가 일반적으로 윈도우 등에서 사용하는 파일을 메모장에 올려놓으면 다음 그림에서 확인할 수 있듯이 문자열, 즉 파일은 데이터임을 확인할 수 있습니다.

이미지 파일을 메모장에 올려놓은 결과

 

그러면 파일은 이제 그냥 컴퓨터가 저장하는 데이터임을 알게 되었습니다.

 

그리고 결론부터 말씀드리자면 소켓 = 파일입니다.

 

소켓이란 ?

통신은 문자열 데이터를 주고받는 것이라고 할 수 있습니다. 그리고, 소켓은 통신에 필요한 데이터를 담는 일종의 파일입니다. 

그래서 우리는 소켓을 통해 통신을 하고 있다고 말할 수 있습니다.

 

컴퓨터 2대가 있다고 가정해봅시다. 이 컴퓨터들이 통신을 하기 위해 데이터를 소켓에 작성을 한 후, 소켓에 적힌 내용을 반대편 컴퓨터의 소켓에 그대로 복사한다고 생각하면 됩니다. 물론 이 과정중에 무수히 많은 일이 일어납니다😏

 

그래서, 소켓을 연다라는 말은, 통신에 필요한 파일을 연다는 뜻이 됩니다.

 

그렇다면 패킷은 뭘까요 ?

소켓은 그냥 통신에 사용되는 파일이라면, 패킷은 소켓에 담기는 데이터를 말합니다.

 

그리고, 패킷에 데이터 구조를 약속한 것이 프로토콜입니다.

그래서 저희가 잘 사용하는 HTTP 프로토콜은 소켓에 담겨져있는 패킷의 형태가 HTTP 에서 약속한 방식의 데이터 형식을 사용하는 것입니다. (즉, HTTP 또한 소켓 통신을 활용한 방식입니다)


더 이론적으로 접근해보겠습니다.

소켓은 프로그램이 네트워크에서 데이터를 주고받을 수 있도록 네트워크 환경에 연결할 수 있도록 만들어진 연결부입니다.

일반적으로 TCP/IP 프로토콜을 이용합니다.

 

 

TCP/IP 4계층에서 전송 계층 위에 놓이면서 전송 계층 위에서 전송계층의 프로토콜 제어를 위한 코드를 제공합니다.

즉, 소켓은 엔드포인트이며, IP와 포트를 활용하여 만들어진 통신의 양 끝단 입니다.

 

소켓이 하는 일

소켓은 크게 2가지 일을 합니다.

  1. 소프트웨어와 소프트웨어를 연결
    • IP와 서비스 포트를 통해 연결
  2. 소프트웨어간 데이터 통신
    • 인터넷에서 소켓을 찾아 연결하고, 데이터를 송수신

 

소켓이 통신하는 방법

Socket을 이용한 프로그래밍을 Socket Programing이라고 하며, 이 때 사용되는 소켓은 Client Socket과 Server Socket으로 구분합니다.

  • Server Socket: 통신 연결 요청을 받아들이는 소켓
    • 소켓 생성, 결합, 주시, 받아들이기, 데이터 송수신, 소켓 닫기
  • Client Socket: 통신 연결 요청을 보내는 소켓
    • 소켓 생성, 연결 요청, 데이터 송수신, 소켓 닫기

 

소켓을 이용한 네트워크 응용 프로그램에서 상대방과 IP 패킷을 주고받기 위해서는 다음의 다섯 가지 정보가 정해져야 합니다.

  1. 통신에 사용할 프로토콜(TCP 또는 UDP)
  2. 자신의 IP 주소
  3. 자신의 포트번호
  4. 상대방의 IP 주소
  5. 상대방의 포트번호

 

소켓 API 실행 흐름

소켓 API의 실행 흐름은 다음과 같습니다.

클라이언트 (Client)

실제로 데이터 송수신이 일어나는 소켓입니다.

1. socket(): 소켓을 생성합니다.

  • 연결 대상에 대한 정보가 들어있지 않은 소켓(껍데기 소켓)을 생성합니다.
  • 이때 소켓의 종류를 선택하는데, TCP 소켓은 stream 타입을, UDP 소켓은 데이터그램 타입으로 지정 가능합니다.

2. connect(): 통신할 서버에 설정된 ip와 port 번호에 통신을 시도합니다.

  • 연결하고 싶은 서버에 연결 요청을 보냅니다. 이 때, IP주소와 서비스 포트로 연결하고 싶은 타겟 대상을 지정합니다.
  • 요청을 보내는 것으로 끝나는 것이 아니라, 그 요청에 대한 결과가 돌아와야 connect의 실행이 끝납니다.
  • 서버와 연결이 이루어지면(connect() 문이 성공적으로 리턴되면) 서버와 데이터를 송수신할 수 있게 됩니다.
서비스 포트란 ?
서비스 포트란, 서비스 구분을 위한 번호입니다. 보통 ip주소:서비스포트 형태로 사용됩니다.
ssh 접속 시 22포트, http 접속 시 80 포트, https 접속 시 443 포트 등 기본 포트가 존재합니다.

 

3. accept(): 통신을 할 때 서버가 accept() 함수를 이용하여 클라이언트의 socket descriptor를 반환합니다.

  • socket descriptor: 소켓기술자로서, 응용 프로그램에서 소켓을 통해 목적지 호스트와 연결을 요구하거나 패킷을 송수신할 때 해당 소켓기술자를 사용합니다.

4. send(), receive(): 이를 통해 클라이언트와 서버가 서로 데이터를 송수신하며 통신합니다.(이 과정이 반복)

  • 연결 요청과 같이, 요청을 보낸다고 끝나는 것이 아니라 요청에 대한 결과(신호)가 들어와야 실행이 끝납니다.
  • 송신할 때에는 데이터를 보내는 것이기 때문에 데이터를 언제 보낼 것인지 알 수 있지만, 수신할 때에는 상대방이 언제, 얼마만큼의 데이터를 보낼 것인지 알 수 없다는 차이점이 존재합니다. 따라서 수신하는 API는 별도의 Thread에서 진행하게 됩니다.

5. close(): 소켓을 닫습니다.

  • 더이상 데이터 송수신이 없다고 판단되면 소켓을 닫습니다.

서버 (Server)

클라이언트 소켓의 연결 요청을 대기하고, 연결 요청이 오면 클라이언트 소켓을 생성하여 통신이 가능하게 합니다.

1. socket(): 소켓을 생성합니다.

  • 클라이언트 소켓과 마찬가지로 연결 대상에 대한 정보가 들어있지 않은 껍데기 소켓을 생성합니다.

2. bind(): ip와 port 번호를 설정합니다.

  • 여러 개의 프로세스가 동시에 실행될 때, ip 주소만 있다면 어느 프로세스로 데이터를 보내야할 지 혼란이 올 수 있습니다. 따라서, 프로세스들은 포트번호를 이용하여 구분하게 됩니다. 따라서 서버 소켓이 고유한 포트 번호를 만들 수 있도록 소켓과 포트번호를 결합해주는 작업도 필요합니다.

  • 만약 이러한 포트번호가 중복된다면, 네트워크를 통해 데이터가 수신될 때 어떤 소켓이 처리해야하는지 결정할 수 없게 됩니다. 이러한 이유로 운영체제는 소켓들이 중복된 포트 번호를 사용하지 않도록 내부적으로 포트번호와 소켓 연결 정보를 관리합니다.
  • 하나의 프로세스는 동일한 포트번호를 가진 여러 개의 소켓을 결합할 수 있습니다. 즉, 호스트가 하나의 포트로 여러 개의 소켓을 생성하여 다른 호스트들과 주고받을 수 있습니다.
클라이언트에서는 bind()가 필요 없나요 ?
클라이언트 프로그램은 서버 프로그램과 달리 자신이 사용하는 IP 주소나 포트번호를 다른 클라이언트 또는 서버가 미리 알고 있을 필요가 없습니다. 
반대로, 서버 응용프로그램은 자신이 사용하고 있는 포트번호를 통하여 클라이언트들이 서비스를 처리해야하므로, 응용 프로그램이 소켓번호와 소켓주소를 bind()하는 것이 필수적입니다.
클라이언트는 포트번호를 임의로 사용해도되기 때문에 포트번호를 특정한 값으로 bind() 시켜둘 필요가 없습니다. 오히려 bind()를 사용하는 것이 클라이언트 프로그램의 범용성을 떨어뜨리게 됩니다. 왜냐면 같은 포트번호를 사용하는 클라이언트 프로그램들이 하나의 컴퓨터에서 두 개 이상 실행되면 에러가 발생하기 때문입니다.

 

3. listen(): 클라이언트의 접근 요청에 수신 대기열을 생성하여 몇 개의 클라이언트를 대기시킬지 결정합니다.

  • 서버 소켓에서 포트번호와 바인딩 작업을 마치고 나면 클라이언트로부터 연결 요청을 받아들일 준비가 다 되었습니다.
  • 클라이언트가 연결 요청을 할 때까지 기다리다가(수동 대기모드로 들어갑니다) 연결 요청이 오면 대기 상태를 종료하고 리턴합니다.

4. accept(): 클라이언트와 연결합니다.

  • 연결 요청이 오면, 연결 요청을 받아들임과 동시에 새로운 소켓을 생성합니다.
  • 서버 소켓의 메인 역할은 단지 클라이언트 연결 요청을 기다리는 것입니다. 따라서 클라이언트 소켓으로부터 연결 요청을 받으면 새로운 소켓을 열고, 이것을 클라이언트 소켓과 맵핑하여 넘겨줍니다.

5. send(), receive(): 이를 통해 클라이언트와 서버가 서로 데이터를 송수신하며 통신합니다.(이 과정이 반복)

  • 클라이언트와 동일합니다.

6. close(): 소켓을 닫습니다.

  • 더이상 데이터 송수신이 없다고 판단되면 소켓을 닫습니다. 클라이언트와 달리, 서버 소켓은 자신이 생성한 소켓들도 관리해야 합니다.

 

소켓 vs 웹소켓

소켓과 웹소켓은 IP와 포트를 이용하여 통신을 한다는 공통점이 있습니다. 또한 둘 다 양방향 통신을 합니다.

 

차이점은,

웹 소켓은 HTTP 레이어에서 작동하는 소켓으로 TCP/IP 소켓의 레이어와 다릅니다.

 

참고

 

'CS 정리 > 개발 상식' 카테고리의 다른 글

[CS] GSLB란?  (0) 2024.05.21
[CS] IP 주소의 개념과 기능  (0) 2024.05.20
[디자인 패턴] MVC, MVP, MVVM 디자인 패턴 비교  (0) 2024.05.14
운영 체제 서비스 Operating-System Services  (0) 2023.05.11
운영체제란 ?  (0) 2023.05.11
profile

SY 개발일지

@SY 키키

포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!