네트워크 프로그래밍

IPC: inter-process communication

클라이언트 <-> 서버 서비스를 위한 필수 프로그래밍

 

네트워크에서 존재하는 여러 에이전트(클라이언트-서버_) 간 통신 위한 프로그램이 바로 소켓이다. 소켓프로그래밍을 공부한다는 것은 C/C++ 언어로 되어있는 소켓구조체, 관련된 api 의 함수들(socket(), bind(), listen() ) 등을 학습해서 소켓을 만들고 클라이언트와 서버의 통신 프로그래밍을 만드는 것이다.

 

• 전통적으로 윈도우, 리눅스, 유닉스에서 우리가 쓰는 거의 모든 응용 SW 가 소켓 기반으로 만들어진다. 

• 기본적으로 운영체제에서 Network-layer에서 api 를 제공해주기 때문에 응용단에서  프로그래밍을 만들 수 있다.

• 전통적으로는 C/C++를 통해  서버 또는 통신 전용 프로그램를 작성했다.

• 최근에는 응용(//서버) 개발시 프레임워크 사용한다.(관련 라이브러리가 잘되어있음)

       Java Spring, Netty

       • Python Django, FastAPI
       • JavaScript Nodejs, Express

 

 
소켓프로그래밍은 아주 기초적인 함수를 이용하는 방식에서 여러 직군별로 프레임웤이 많이 생겼다. 이걸 이용하면 쉽게 소켓 프로그램을 응용해서 만들 수 있다.
 
 
 
소켓 프로그래밍 발전 트렌드
 
 
백엔드, 프론트엔드, 모바일을 보면 전통적으로는 유닉스 네트워크 프로그래밍으로 개발했지만 지금은 자바 스프링, 스크립트, 고 등의 프레임워크로 만든다. 웹쪽은 이전은 윈도우, C++, C#으로 개발했지만 웹기반에서는 자바, 자바스크립트로 개발하게 된다. 웹에서는 자바스크립트가 디폴트가 되어있다(현재) 최근에는 파이썬 계열의 장고, 플라스크, FastAPI 이용하는 것도 많이 사용되고 있다.
서버와 클라이언트가 자바스크립트를 공통으로 이용할 수 있기 때문에 풀스택으로선 최근에 자바스크립트 계열의 Node.js 같은게 주목받고 있다. 이런 건 비동기, 싱글스레드로 구현되어있다.
 

- 백엔드/서버
Unix network programming: C/C++

Application: Java/Spring Framework (JavaScript, Go) + DB

-프론트엔트/클라이언트

Windows network programming: C++/C#

Web: JavaScript, Java

- Web framework: 백엔드, 풀스택

Java Spring, Python

Flask/FastAPI/Django

Node.js: async, single thread

 

프론트엔드/모바일

Java.net.Socket class : https://do cs.oracle.com/javase/7/docs/api/ java/net/Socket.html

Android: https://developer.andr oid.com/reference/java/net/Sock et

Swift

 

소켓 프로그래밍 학습 이유

1. 네트워크 응용 SW 개발 : 가장 raw 한 소켓을 api 를 호출할 때 뿐만 아니라 프레임워크단에서 개발한다 하더라도 서버, 응용을 할 때 웹 서버, 채팅, 게임 등을 개발하려하면 소켓에 대한 개념이 있어야 쉽게 개발할 수 있다.

 

2. 분산시스템, 운영체제, 네트워크 작동 방식 이해

 

3. 고급 통신 프로그램 개발  : 대규모, 고성능 서버를 개발하려하면 여전히 소켓프로그래밍을 이용해서 직접 개발하고 있다

        • 게임 서버 (C/ C++ 로 전통적인 방식처럼 개발하고 있다)

 

4. 대규모 시스템 이해 : 대규모, 고성능 서버를 개발하려하면 여전히 소켓프로그래밍을 이용해서 직접 개발하고 있다

        • AI, 클라우드

 

소켓 프로그래밍 개요

아래는 소켓프로그램의 가장 기본적 구조이다. 소켓이란 응용 프로세스(앱)와 전송 계층 사이의 API 를 지칭하는 것이다.

그림에 보이는 것처럼 우리가 사용하는 웹 브라우저가 프로세스로 떠서 사용자계층에 실행되고 있다. 그 아래부터는 운영체제로 커널에서 제공하는 기능이다. 커널에서 네트워크 사이에 서버-클라이언트 통신 기능을 구현하는데 그 api 가 소켓이다. 

구체적이로 이해하자면 소켓은 파일이다. 

우리가 파일을 읽고, 쓰고, 종료하는 것처럼 소켓에 데이터를 읽고, 쓰고, 종료하는 것이다. 

소켓은 쉽게 생각하면 네트웤을 연결하는 파일이다. 

 

 

socket(2) Linux manual page

소켓은 endpoint 를 만드는 것인데 이 endpoint 는 communication 통신을 위한 endpoint 이다. 소켓은 file descripter 를 리턴한다. 통신의 끝단(포트번호를 이용하여 데이터를 읽고 씀) 이것이 파일과 동일하다. 파일 디스크립터로 파일을 읽고 쓰면 네트웤을 통해 데이터를 통신할 수있다. 소켓을 커널에서 제공하기 때문에 소켓함수로 쉽게 통신할 수 있다. 

https://man7.org/linux/man-pages/man2/socket.2.html

 

소켓 프로그래밍 개요(2)

소켓은 전송계층의 대표 TCP, UDP 와 일대일로 매핑이 된다. tcp 이용한 소켓프로그래밍, udp 이용한 소켓프로그래밍 이렇게 나눌 수 있다. tcp 는 신뢰성있는 기능, 연결, 바이트단위 전송, udp 는 신뢰성 x , 연결x , 멀티플렉싱만 제공 /

이 두가지를 커널에서 제공하고 있다. 

소켓 종류: UDP, TCP

 

UDP 통신

비신뢰성: 패킷 손실, 순서 바뀜 가능 연결 없음
IP 주소와 port 번호 이용하여 송수신

AF_INET: 인터넷, SOCK_DGRAM : UDP / 소켓을 만들면 서버 소켓을 이용해서 패킷을 기다리게됨(연결 x) 받고 다시 소켓 전송

 

udp 서버 : 몇번 포트가 bind 되는지 api로 호출, recvfrom() 으로 데이터 수신

 

udp 클라이언트 : 서버 포트번호 명시하여 데이터 전송, sendto로 메시지와 서버네임, 서버포트 알아내서 데이터전송

UDP 예시

 

TCP 연결

 TCP 통신
 신뢰성: 패킷 손실 복구, 순서 맞춤 제공 

 연결 설정 필요
 바이트 단위의 스트림 전송

accept() listen() 과 같은 api : 연결을 만들고 데이터를 전송한다.
SOCK_STREAM : TCP 연결임을 의미 / connect() : 서버와 연결 후 전송 / send() recv()

tcp 서버 : 소켓을 만들고 ( SOCK_STREAM: tcp) bind() 연결 만들고 listen() 상태로 들어가고 accept() 로 실제 연결이 완료되는 걸 기다리고 , 연결이 만들어지면 recv() 로 데이터 수신 대기 

 

TCP 예시

 

TCP 서버 주요함수

소켓만들기

 s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) IP주소와 포트번호로 서버 소켓 묶기: 바인드

 s.bind((IP_ADDR, TCP_PORT))


대기하기(연결요청 넣을 큐의 크기)

     • s.listen(1)
연결 수락하기

     • conn, addr = s.accept()

데이터 수신
     • data = conn.recv(BUFFER_SIZE)

 

TCP 클라이언트 주요 함수

 소켓 만들기

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

 

 연결

 s.connect((IP, TCP_PORT))

 

데이터전송

s.send(MESSAGE.encode('utf-8'))

 

 

러 개의 클라이언트를 처리하는 서버 IO 구조

1. blocking vs. non-blocking

Blocking : 프로세스가 시스템을 호출 하고나서 결과가 반환되기까지 다음 처리로 넘어가지 않음

Non-blocking : 시스템을 호출한 직후에 프로그램으로 제어가 다시 돌아와서 시스템 호출의 종료를 기다리지 않고 다음 처리로 넘어갈 수 있음(IO 시간이 길다면) 

[소켓이 블로킹, 논블로킹 둘 중 어느것으로 작동될지 결정해야함 IO 시간이 길게되면 논블로킹이 효율적이다. ]

 

2. synchronous vs. asynchronous

Synchronous : 작업을 요청한 후 작업의 결과가 나올 때까지 기다린 후 처리

Asynchronous : 직전 시스템 호출의 종료가 발생하면 그에 따른 처리를 진행 (Android App)

 

=> 서버클라이언트를 만들때 이런 작동방식을 혼합해서 사용할 수 있다. 

여러 개의 클라이언트를 연결하는 소켓 프로그래밍

multiprocess 

: 클라이언트 동시 처리 위해 프로세스를 여러개 시행하는 것이다. 프로세스는 운영체제에서 굉장히 큰 자원을 사용하기 때문에 조금더 작은 단위 실행단위인 스레드를 이용할 수 있다 -> 멀티스레드
ex) fork, multi-process 관리, IPC 통신

 

multithread

: 메모리가 조금 사용되더라도 스레드를 이용해서 리소스를 적게 사용할 수 있는 방식. 
ex) Single process, 메모리 사용 증가, 쓰레드 관리

 

Select

: Select 로 소켓을 여러개를 만들고 소켓의 송수신 이벤트 발생했는지 모니터링을 계속해서 확인(싱글스레드로 처리 가능) 모니터링는 계속해야해서 대기하는 것에 따른 cpu 리소스가 증가하는 단점, 대규모로 여러 클라이언트 처리하는 기능 존재 
여러 Socket I/O 모니터링, single thread, event 처리, 대규모 동시접속/ 서버, CPU 증가, 대기

Async
 : 클라이언트 많이 처리 가능. 프로그래밍과 디버깅/테스트가 어려움

확장성, 빠름, 자원 효율성, 복잡한 코드, 어려운 디버깅/테스트

 

Multiprocess 예시

Process()

Multithread 예시

Thread()
IO연산이있을때효과
Join(): 새로 생성한 스레드 종료를 기다림

 

Select 

: 전통적으로 서버에서 Select 함수 많이 이용했었다. 

 

한편, WebSocket, Socket.io ?

우리는 프로그래밍할 때 프레임워크를 사용할 가능성이 높다. 웹소켓하고 우리가 방금 배운 소켓은 다르다. 소켓이긴 하지만 이름이 보여주는 것처럼 웹소켓은 웹에서의 소켓이고 그 중에 특별히 구현된 예제가 Socket.io 이다. 우리가 배운건 tcp/udp 단에서 만든 소켓이고 우리가 소켓을 짜게 되면 응용계층에서 소켓을 만드는 것이다. 이게 조금 다르기 때문에 이름이 비슷해도 구분해서 이해해야한다.

만약 웹 소켓이라고 하면 HTTP 위에 소켓이 구현되어있다고 보면 된다. 

ex) 배달의민족에서 실시간 통신 할 때는 그냥 소켓 x 웹소켓 o  ( RFC6455) / 왜냐면 실시간 양방향 통신이 HTTP 로는 어렵다. -> 별도의 라이브러리(웹 기반) 필요

  • L4(tcp/udp) vs. L7(응용계층)
  • Socket programming
    TCP, UDP, IP api를 이용한 응용 개발
  • WebSocket: RFC6455
    HTTP는 서버와 클라이언트 사이의 연결 X
    HTTP실시간 양방향 통신 구현에 어려움: HTTP polling, Stream /   HTML5 표준, HTTP 위에서
  • Socket.io   
  • 추상화: WebSocket, FlashSocket, AJAX Long Polling, Ajax Multi Part Streaming, Iframe, JSONP Polling Node.js 모듈

 

배달의 민족 주문 시 실시간 통신 구현 예제

http://woowabros.github.io/woowabros/2017/09/12/realtime-service.html

 

Node.js 에서 socket.IO를 이용한 실시간 응용 예

https://poiemaweb.com/nodejs-socketio

 

우리가 실제로 웹소켓 쓸때는 Node.js 모듈을 사용하게 됨

 

사례

PayPal, Netflix, Linkedin, Groupon, Naver, ...

Node.js
Chrome V8 JavaScript 엔진으로 만든 JavaScript 런타임 이벤트 기반, single thread

Node.js 인기이유
풀스택: 서버, 클라이언트를 JavaScript기반으로 개발 가능
JSON 지원: 데이터변환 부담 줄어듬
쉬운 비동기 프로그래밍: 고성능 서비스를 코딩하기 쉽게: async/await

성능: Naver (초당 5천건 24코어 서버 4)

 

 

Node.js(Express)와 Socket.io | PoiemaWeb

WebSocket, Socket.io를 사용한 실시간 채팅 애플리케이션

poiemaweb.com

 

728x90

+ Recent posts