소켓과 select를 이용한 멀티플렉싱 서버 구축하기

1. 소켓 이해하기

전화를 걸기 위해서는 ‘단연코’ 전화기가 필요하다. 전화기는 멀리 떨어져 있는 두 사람이 대화할 수 있도록 만들어주는 매개체이다. 소켓은 전화기처럼 멀리 떨어져 있는 두 개의 호스트(host)를 연결해주는 매개체 역할을 한다.

1
2
3
4
#include <sys/types.h>
#include <sys/socket.h>

int socket(int domain, int type, int protocol);

우리는 누군가에게 걸려오는 전화를 받게 된다. 그리고 전화를 받으면 ‘여보세요’라는 응답을 주게 된다. 그렇다면, 전화기(소켓)을 만든 이후에 무엇이 더 필요할까? 당연히 전화번호가 필요하다. 그래야 누가 나한테 전화를 할 수 있기 때문이다. 그렇다면, 전화번호를 우리의 전화기에 할당시켜야 하는 것처럼, 소켓에도 일종의 ‘전화번호’가 필요하다. 소켓에서 전화번호의 역할을 하는 것은 바로 IP 주소이며, bind 함수를 이용하여 소켓에 주소를 할당할 수 있다.

1
2
3
#include <sys/socket.h>

int bind(int sockfd, struct sockaddr *myaddr, int addrlen);

이제 전화를 받을 준비가 끝났다. 하지만, 전화가 케이블에 연결되어 있지 않으면 소용이 없다. 즉, 전화선을 연결시키고 전화를 받을 상태를 만들어주어야 한다. 마찬가지로 소켓도 연결 가능한 상태가 되도록 대기를 시켜주어야 하는데, listen 함수를 이용하여 연결 요청이 가능하도록 만들어줄 수 있다.

1
2
3
#include <sys/socket.h>

int listen(int sockfd, int backlog);

자, 이제 전화벨이 울린다. 통화를 하기 위해서는 통화버튼을 눌러야 한다. 즉 누군가 대화를 요청했을 때 이것을 수락해야 한다는 뜻인데 소켓 역시 누군가가 데이터를 주고받기 위해 대화(연결)를 요청했을 때 그 요청을 수락할 수 있어야 한다. 이것을 accept 함수가 수행하게 된다.

1
2
3
#include <sys/socket.h>

int accept(int sockfd, struct sockaddr *addr, int *addrlen);
자세히 보기

멀티태스킹과 식사하는 철학자 문제

https://namu.wiki/w/%EC%8B%9D%EC%82%AC%ED%95%98%EB%8A%94%20%EC%B2%A0%ED%95%99%EC%9E%90%20%EB%AC%B8%EC%A0%9C

n명의 철학자가 스파게티를 먹고 있다고 가정한다.

철학자들은 잠자기, 먹기, 생각하기 셋 중 한 번에 하나만 할 수 있고 모든 철학자가 스파게티를 먹어야 한다.

식사하는 중에는 무조건 두 개의 포크를 사용해야 한다.

포크의 개수는 철학자의 인원수와 같으며, 포크는 각각의 철학자 사이에 놓이게 된다.

이 때 만약에 모든 철학자들이 동시에 자신의 왼쪽 포크를 잡게 된다면, 자기 오른쪽의 포크가 사용 가능해질 때까지 기다려야 하는데,

모든 철학자들이 기다리는 상태에 놓이게 된다.

이렇게 아무것도 진행할 수 없는 상태를 교착(deadlock)상태라고 한다.

멀티태스킹이 가능한 멀티쓰레드 환경일 때

사용자 레벨에서 Semaphore나 Mutex를 이용하여 한 쓰레드가 동작중일 때 다른 쓰레드가 CPU를 잡지 못하게 만들면 교착상태를 방지할 수 있다.

자세히 보기