본문 바로가기

네트워크

[네트워크] 소켓 프로그래밍이란(Socket Programming)

1. 소켓 프로그래밍 개요

□ 소켓의 의미

그림 참조: https://realpython.com/python-sockets/

  • 사전적으로 '구멍', '연결', '콘센트' 등의 의미
  • 프로그램이 네트워크에서 데이터를 송수신할 수 있도록, '네트워크 환경에 연결할 수 있게 만들어진 연결부
  • 전원 소켓처럼 '쓰고싶을 때 연결해서 사용한다'는 의미 내포
  • 소켓(socket)은 1982년 BSD(Berkeley Software Distribution) UNIX 4.1에서 처음 소개됨
  • 현재 널리 사용되는 것은 1986년의 BSD UNIX 4.3에서 개정된 것

 □ TCP/IP 소켓 통신이란

  • 전기 소켓이 전기를 공급받기 위해 정해진 규격(110V, 220V 등)에 맞게 만들어져야 하듯, 네트워크에 연결하기 위한 소켓 또한 정해진 규약, 즉, 통신을 위한 프로토콜(Protocol)에 맞게 만들어져야 함
  • 보통 OSI 7 Layer(Open System Interconnection 7 Layer)의 네 번째 계층인 TCP(Transport Control Protocol) 상에서 동작하는 소켓을 주로 사용하는데, 이를 "TCP 소켓" 또는 "TCP/IP 소켓"이라고 부름
  • UDP 소켓도 있음 

□ TCP/IP란

  • TCP/IP는 패킷 통신 방식의 인터넷 프로토콜인 IP와, 전송 조절 프로토콜인 TCP로 이루어져 있음
  •  IP는 패킷 전달 여부를 보증하지 않고, 패킷을 보낸 순서와 받는 순서가 다를 수 있음
  • TCP는 IP위에서 동작하는 프로토콜로, 데이터의 전달을 보증하고 보낸 순서대로 받게 해줌
  • TCP/IP에 대한 내용 참조 : https://brunch.co.kr/@wangho/6

 □ 소켓의 종류

  • 통신 연결 요청을 보내는지 또는 요청을 받아들이는지에 따라 소켓의 역할이 나뉨
  • 전자에 사용되는 소켓을 클라이언트 소켓(Client Socket)
  • 후자에 사용되는 소켓을 서버 소켓(Server Socket)
  • 두 소켓은 동일한 구조임. 단지 역할에 따라 처리되는 흐름이 다를 뿐임

[주의]

  • 소켓 연결이 완료된 다음 클라이언트 소켓과 서버 소켓이 직접 데이터를 주고 받는다고 생각하면 안 됨
  • 서버 소켓은 클라이언트 소켓의 연결 요청을 받아들이는 역할만 수행할 뿐, 직접적인 데이터 송수신은 서버 소켓의 연결 요청 수락의 결과로 만들어지는 새로운 소켓을 통해 처리됨

 □ 소켓 통신 흐름

그림 및 내용 참조: https://recipes4dev.tistory.com/153

[서버 소켓(Server Socket)]

  1. 소켓(Socket)을 생성(create)함
  2. 서버가 사용할 IP 주소와 포트 번호를, 생성한 소켓에 결합(bind)시킴
  3. 클라이언트로부터 연결 요청이 수신되는지 주시(listen)함
  4. 요청이 수신되면 요청을 받아들여(accept) 데이터 통신을 위한 '새로운' 소켓을 생성함
  5. 연결 후 데이터를 송수신(send/recv)
  6. 데이터 송수신이 완료되면, 소켓(Socket)을 닫음(close)

[클라이언트 소켓(Client Socket)]

  1. 소켓(Socket)을 생성(create)함
  2. 서버 측에 연결(connect)을 요청함
  3. 서버 소켓에서 연결이 받아들여지면 데이터를 송수신(send/recv)함
  4. 모든 처리가 완료되면 소켓(Socket)을 닫음(close)

[주의 사항]

  • 최종적으로 클라이언트 소켓(Client Socket)과 연결(Connection)이 만들어지는 소켓(Socket)은 앞서 사용한 서버 소켓(Server Socket)이 아니라, accept API 내부에서 새로 만들어지는 소켓임
  • 실질적인 데이터 송수신은 accept API에서 생성된, 연결(Connection)이 수립(Established)된 소켓(Socket)을 통해 처리됨

2. 다중 클라이언트 처리

□ 개요

  • 기본 서버-클라이언트 모델에서 서버는 한 번에 하나의 클라이언트만 처리함
  • 다중 클라이언트를 처리하려면, 멀티프로세싱, 멀티스레딩, 멀티플렉싱 등을 활용해야 함

□ 멀티프로세싱 활용

[프로세스란]

  • 프로세스의 의미는 'Program in execution(실행 중인 프로그램)'
  • 프로세스는 각각 독립된 메모리 영역(Code, Data, Stack, Heap의 구조)을 할당받음
  • 기본적으로 프로세스당 최소 1개의 스레드(메인 스레드)를 가지고 있음
  • 각 프로세스는 별도의 주소 공간에서 실행되며, 한 프로세스는 다른 프로세스의 변수나 자료구조에 접근할 수 없음
  • 한 프로세스가 다른 프로세스의 자원에 접근하려면 프로세스 간의 통신(IPC, inter-process-communication)을 사용해야 함

그림 및 내용 참조: https://woovictory.github.io/2018/12/25/OS-Process/

[프로세스 구성]

  • stack : 지역변수 할당과 함수 호출 시 전달되는 인자값들을 저장하기 위한 공간
  • heap : C의 malloc, calloc와 C++,Java의 new를 통한 동적 할당을 위해 존재하는 공간
  • data : 전역 변수나 static 변수의 할당을 위해 존재하는 공간
  • code : 프로그램을 실행시키면 실행파일 내에 존재하는 명령어가 메모리 상에 올라가야 프로그램을 동작시킬 수 있음. 이 명령어들을 위해 존재하는 공간(쉽게 말해 소스코드가 올라간다고 생각하면 됨)

[멀티프로세싱]

  • 말 그대로, 프로세스를 여러 개 사용하여 클라이언트를 처리할 수 있음
  • 프로세스 당 하나의 클라이언트를 처리함
  • 흔히 알고 있는, fork()를 통해 멀티 프로세스를 만들 수 있음
  • 부모 프로세스 1개에 자식 프로세스 N개를 만들 수 있음
  • 부모 프로세스와 자식 프로세스는 독립 프로세스로 각각 실행됨
  • 아래 그림에서 fork 뜬 하나하나가 프로세스임

 

그림 참조: https://jongmin92.github.io/2019/02/28/Java/java-with-non-blocking-io/

 

그림 참조: https://www.crocus.co.kr/462

 

그림 참조: https://www.fun-coding.org/ipc.html

[장점]

  • 독립된 구조이기 때문에 안정성이 높음
  • 클라이언트와 서버 간의 송수신 데이터 용량이 큰 경우 적합
  • 송수신이 쉬지 않고 연속적으로 발생하는 경우 적합

[단점]

  • 프로세스가 많이 생성될수록 메모리 사용량이 증가하고 프로세스 스케줄링 횟수도 많아져서 프로그램 성능이 떨어지게 됨
  • 프로세스들 사이에 데이터를 공유할 수 없음. 프로세스 간 데이터를 공유하려면 운영체제의 도움을 받아 프로세스 간 통신(Inter Process Communication, 이하 IPC)을 해야 함. 이로 인해 프로그램 구현이 복잡해질 수 있음

□ 멀티스레딩 활용

  • 여러 클라이언트를 처리하는 간단한 방법은, 서버에 연결된 모든 새 클라이언트에 대해 새 스레드를 생성하는 것임
  • 스레드는 프로세스보다 작은 단위이며 프로세스 안에서 논리적으로 동작하는 하나의 작업단위
  • 두 개 이상의 스레드를 가지고 있는 프로세스를 멀티스레드 프로세스(Multi-threaded process)라고 함
  • 외부에서는 스레드들 전체가 하나의 프로세스처럼 취급됨

그림 참조: https://wooaoe.tistory.com/55
그림 참조: https://developerhenrycho.tistory.com/17

[장점]

  • IPC에 비해 스레드 간 통신 방법이 훨씬 간단함
  • 스레드는 Stack 영역을 제외한 모든 메모리를 공유하여 시스템 자원 소모가 줄어 듦
  • 멀티프로세싱보다는 Context Switching에 대한 오버헤드가 줄어 듦(멀티프로세스를 통해 PCB를 Context Switching 하는 것보다 멀티스레드를 통해 TCB를 Context Switching 하는 비용이 더 적다고 알려져 있음)

[단점]

  • 스레드는 코딩, 디버깅이 어렵고 때로는 예측할 수없는 결과가 발생함. 여러 개의 스레드를 이용하는 경우, 미묘한 시간차나 잘못된 변수를 공유함으로써 오류 발생 가능
  • 많은 수의 클라이언트에 대해 확장 불가능(운영체제 별로 다르지만, 대략 1000개 언저리까지 생성 가능)
  • 교착상태가 발생할 수 있음
  • 서버에 접속한 각 클라이언트 별로 read() 스레드를 할당할 경우, 데이터가 오지 않으면 계속 블로킹 상태가 되기 때문에 자원이 낭비될 수 있음

□ 멀티플렉싱 활용

 

  • 멀티플렉싱이란, 하나의 전송로를 여러 사용자가 동시에 사용해서 효율성을 극대화 하는 것
  • I/O 멀티플렉싱이란, 클라이언트와 입/출력하는 프로세스를 하나로 묶어버리는 형식(프로세스가 고속의 전송로에 해당)

그림 및 내용 참조: http://forum.falinux.com/zbxe/index.php?mid=lecture_tip&document_srl=463229

  • 하나의 스레드를 이용하여 여러 클라이언트와 동시에 메시지를 주고받을 수 있음
  • 서버에서 여러 명의 클라이언트와 동시에 메시지를 주고 받기 위한 멀티스레드는 각 스레드 당 메모리와 CPU의 스택을 필요로 하기 때문에 서버의 성능이 저하될 수 있음
  • 이러한 단점을 보완하기 위해 하나의 스레드만 생성하여, 여러 클라이언트와 통신할 수 있는 IO 멀티플렉싱이 등장
  • 지금까지의 흐름을 정리하자면, 여러 개의 프로세스(멀티프로세싱) 하나의 프로세스 & 여러 개의 스레드(멀티스레딩) 단일 스레드(멀티플렉싱)
  • 멀티플렉싱 설계 시 코드가 복잡해짐. 논블로킹을 위해 핸들러를 만들어야 하며, 콜백 개념도 이해해야 함
  • 하나의 스레드에 작업량이 많아지는 것을 고려해 Thread Pool을 만들어 Task들을 분산처리 해야 함
  • 이러한 것들을 쉽게 처리할 수 있는 함수가 있음(select 함수 등)

[장점]

  • 스레드 하나가 여러개의 클라이언트를 관리할 수 있어서 굉장히 효율적임
  • 클라이언트와 서버 간 송수신 데이터의 용량이 적은 경우 적합
  • 송수신이 연속적이지 않은 경우에 적합
  • 멀티프로세스에 비해 많은 수의 클라이언트 처리에 적합

 

 

 


* 전체적 내용 참조

https://recipes4dev.tistory.com/153

 

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

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

recipes4dev.tistory.com

 

'네트워크' 카테고리의 다른 글

[네트워크] 타임아웃(Timeout) 정리  (0) 2020.12.26