Home » socket

socket

Asyncio를 사용한 비동기 소켓 통신

이 블로그에서는 파이썬으로 소켓 통신을 구현하는 몇 가지 방법을 이미 살펴본 바 있습니다. 원시 소켓인 socket.socket을 사용하는 방법zmq의 REQ-REP 패턴을 사용한 방법이 있었고, 다중 접속을 허용하도록 스레드를 통해 처리하거나, 셀렉터를 사용하여 단일 스레드에서 멀티플렉싱하는 방법도 알아보았습니다. 이번 글에서는 asyncio에서는 과연 소켓 통신을 어떤식으로 구현하는지 살펴보고 역시나 간단한 비동기 다중 접속 에코 서버를 구현하는 과정을 함께 살펴보겠습니다.

더 보기 »Asyncio를 사용한 비동기 소켓 통신

Selector를 사용한 소켓 멀티플렉싱

소켓을 사용하여 간단한 서버를 만들 때에는 서버 소켓을 생성하고, 이를 특정한 네트워크 포트에 바인드한 다음, listen() 메소드를 사용해서 해당 포트로 들어올 수 있는 접속 대기열의 크기를 지정합니다. 그런 다음 해당 소켓의 accept() 메소드를 사용해서 클라이언트 소켓을 생성하고, 이 클라이언트 소켓을 통해 클라이언트가 보낸 요청을 읽고, 그에 대한 응답을 보내게 됩니다.

서버 소켓은 클라이언트가 접속할 때마다 ‘서버가 사용하는 클라이언트 소켓’을 따로 생성하고 실제 통신은 두 클라이언트 소켓 사이의 peer-to-peer 방식의 대화가 됩니다. 따라서 하나의 서버 소켓은 여러 클라이언트의 접속을 받을 수 있습니다.

만약 다중 접속을 허용하는 소켓 서버를 파이썬에서 구현한다면 가장 쉬운 방법은 스레드를 사용하는 것입니다. 클라이언트 소켓을 인자로 받는 핸들러 함수를 하나 작성하고, 서버 소켓의 accept() 메소드가 리턴하는 시점에 핸들러 함수에게 클라이언트 소켓을 주고 새로운 스레드에서 작동하도록 시작해주면 됩니다.

여기까지의 작동 모델은 ‘동기식 소켓’을 사용합니다. 동기식 소켓은 send(), recv(), accept() 등의 동작이 모두 블럭되는 소켓입니다. 따라서 스레드가 소켓의 입출력을 기다리는 동안에는 다른 일을 할 수가 없습니다. 그래서 서버 소켓과 클라이언트 소켓들이 동시에 작동할 수 없으니 스레드를 사용하는 것이겠죠.

소켓 라이브러리는 이와 다른 비동기 소켓을 지원하고 있습니다. 비동기 소켓은 소켓을 바인딩하기 전에 sock.setblocking(False)를 명시해서 블록킹 모드를 논블록킹으로 변경해줍니다. 이렇게 만들어진 비동기 소켓을 소켓 API만으로 사용할 수는 없습니다. Python How To 문서는 select.select() 를 사용할 것을 추천합니다만, 이는 문서가 오래되었음을 감안해야 하며 실제 파이썬 공식문서는 보다 고수준으로 설계되어 사용하기 쉬운 selectors 모듈을 쓸 것을 추천하고 있습니다.

이 글에서는 selectors 모듈을 사용하여, 단일 스레드에서 하나의 소켓 서버가 여러 클라이언트의 요청을 처리하는 멀티플렉싱을 어떻게 구현하는지 소개하며, 셀렉터 사용 방법에 대해서 살펴보겠습니다.

더 보기 »Selector를 사용한 소켓 멀티플렉싱

여러 스레드의 시작 시점을 맞추기 – Barrier

Barrier는 동시성 프로그래밍에서 사용되는 동기화 수단 중 하나로 여러 워커(스레드)들을 특정한 시점까지 기다리게 한 후 한꺼번에 함께 시작하도록 해준다. 비슷한  방식의 동기화 프리미티브로 이벤트(Event)가 있는데, 이벤트는 재개 시점을 판단하는 제 3의 스레드가 재개를 위한 시그널을 set해주어야 한다. 배리어는 그와 달리 정원을 채우면 출발하는 버스처럼, 미리 정해진 개수만큼의 스레드가 배리어 아래에 모이면 자동으로 해제되어, 함께 시작하게 해준다.

더 보기 »여러 스레드의 시작 시점을 맞추기 – Barrier

ZMQ의 기본 개념들

일전에 간단하게 ZMQ(Zero MQ)에 대한 내용을 간단히 정리해본 바 있는데, 이 때는 소켓에 대한 내용을 살펴보다가 흘러흘러 닿은 부분이라 제대로 설명하지 못하고 공식문서에 나오는 예제를 그대로 옮기는 수준이었다.  ZMQ는 소켓 프로그래밍 API를 대체할 수 있는 정말 괜찮은 라이브러리라는 생각이 들어서 활용할 폭이 넓다고 판단됐다. 다만 용어나 개념에 대한 약간의 선행지식이 필요한 부분이 있다. 오늘은 ZMQ에서 사용되는 기본적인 개념에 대해서 알아보고, ZMQ를 통해서 간단한 에코서버와 클라이언트로 소켓통신을 구현하는 방법에 대해 살펴보도록 하겠다. 그리고 ZMQ를 사용하면 전통적인 소켓 접속을 구현하는 것보다 얼마나… 더 보기 »ZMQ의 기본 개념들

스레드를 이용한 데몬 만들기 – Python

이 블로그를 통해서 파이썬에서의 병렬처리에 대해서는 명시적으로 threading.Thread 대신에 concurrent.futures 에서 제공하는 API를 사용할 것을 여러 차례 권장해 왔다. 여기서 주목할 것은 바로 “병렬처리”라는 조건이다. 즉 concurrent.futures의 API는 일련의 데이터에 대해서 동일한 처리를 하려할 때, 이 “동일한 처리”를 여러 스레드 혹은 프로세스로 나눠서 동시에 진행하는 상황에 어울리는 기능이다. 하지만 실제 상황에서는 동시에 서로 다른 작업이 진행되어야 하는 경우가 존재한다.주로 메인 스레드와 백그라운드 스레드 (혹은 작업 스레드)에서 하는 일이 서로 다른 경우에 이러한 패턴이 필요할 수 있다. 이번 글에서는 파이썬의 threading… 더 보기 »스레드를 이용한 데몬 만들기 – Python

파이썬 소켓 연결 사용법

네트워크 프로그래밍 분야에서 소켓은 연결된 네트워크의 양 끝단을 추상화 시킨 개념이며, 컴퓨터의 관점에서는 네트워크로 통하는 컴퓨터의 외부와 컴퓨터 내부의 프로그램을 이어주는 인터페이스이다. 소켓의 개념에 대해서 이 글에서 모두 소상히 설명할 수는 없고, 네트워크를 통해서 바이트스트림을 주고 받을 수 있는 창구라 보면 된다. 다만 단순히 프로그램의 내부와 외부를 잇는 표준 입출력과는 달리 소켓은 네트워크의 반대편이 어디인지에 대한 정보를 가지고 있다. 즉 우리가 택배를 보낼 때 박스에 물건을 넣고 받는 사람 주소를 쓰는 것과 비슷하게 소켓은 어디로 보내지는 창구라는 것이 명시된 택배 상자 같은 것이다.

더 보기 »파이썬 소켓 연결 사용법