kakasoo

[TCP/IP] IO 멀티 플렉싱 기반의 서버, 클라이언트 본문

프로그래밍/네트워크

[TCP/IP] IO 멀티 플렉싱 기반의 서버, 클라이언트

카카수(kakasoo) 2020. 7. 18. 16:18
반응형

 

 

 

server와 client는 서로 이렇게 입출력을 주고 받는다, 물론 main이 되는 server가 있긴 하겠지만, 이런 입출력은 반드시 server와 client간의 것이 아니니, client끼리도 입출력을 주고받을 수는 있긴 하겠다, 그러니 그림을 다시 그려보자.

 

 

 

 

 

 

 

좌측처럼 그리면 모든 대상이 정보를 주고 받을 수 있을 것이다.

하지만 필요한 socket의 수가 매우 많아질 것이고, 당연히 연결도 빈번해지니 전체 시스템이 느려질 수 밖에 없다.

그러니까 새로이, 우측 같은 그림으로 다시 그려보자.

 

이런 형태로 그리게 된다면, 각 선의 길이도 (개수를 의미) 줄고 입출력의 숫자도 절반으로 줄어들게 된다.

멀리플렉싱 기반의 서버라는 것은 위의 그림과 같은 형태를 의미하는데, 엄밀히 표현하면, 서버에 멀티플렉싱 기술을 도입하여 필요한 프로세스의 수를 줄일 수 있다는 것을 의미한다.

원래대로면, 소켓이 accept할 때마다, 서버는 데이터 송수신을 위한 socket을 생성하는데, 그렇다면 10명의 client에 대하여 10개의 소켓이 생성되야 마땅한 일이다.

하지만 이 그림에서 보여지는 프로세스의 수는 단 1개다, 하나가 모든 걸 처리하기 때문이다.

(멀티 프로세스는 위처럼 소켓을 여러 개 구현하는 것이다, 어쨌든 서버 하나로 동시적인 일을 처리할 순 있다.)

마찬가지로 클라이언트도 동일한 방식으로 구현할 수 있다.

 

select 함수의 이해와 서버의 구현

select 함수를 사용하면 여러 개의 파일 디스크립터 (소켓)을 모아놓고, 동시에 관찰하는 것이 가능하다.

여기서 관찰 대상을 event 라고 하고, event가 발생했다고도 표현하는데,

select 함수의 event들은 각각, 수신한 데이터를 지니고 있는 소켓의 존재 유무, 블로킹되지 않고 데이터의 전송이 가능한 소켓의 유무, 예외 상황이 발생한 소켓의 유무를 의미한다.

저자는 select 함수가 매우 복잡하니, 주의깊게 보라고 하는데, 일단 함수의 호출 과정을 보도록 하자.

 

1) 파일 디스크립터의 설정 -> 검사의 범위 지정 -> 타임아웃의 설정

2) select 함수의 호출

3) 호출 결과 확인

함수를 호출하기 전에 준비해야 하는 것들이 있는데, 이것들에 대해서 세부적으로 보도록 하자.

 

파일 디스크립터의 설정

파일 디스크립터의 관찰은 곧 소켓의 관찰이다, 애초에 윈도우에서는 파일 디스크립터 대신 소켓이라는 말로 구분한다. 어쨌거나, 본론으로 가면, 관찰을 한다는 것은 파일 디스크립터들을 한 데 모아 놓았다고 볼 수 있다. 모을 때에는 다시 수신, 전송, 예외라는 상황을 구분하여 모아야 한다.

즉, 세 가지 갈래로 나눠서 모아놔야 한다는 뜻이다.

 

모여진 파일 디스크립터들은 하나의 배열 안에서, 0 또는 1을 값을 가지는데, 이 bit가 0을 가지면 관찰의 대상이 아니며, 1을 가지면 관찰 중인 대상이라는 의미를 가진다. 이러한 값을 직접 접근해서 매기는 것은 아니고, 관련 함수들이 존재한다.

 

  • FD_ZERO(fd_set* fdset) // 인자로 전달된 주소의 fd_set형 변수의 모든 비트를 0으로 초기화한다.
  • FD_SET(int fd, fd_set* fdset) // 매개변수로 전달된 fdset에 전달된 소켓 정보 fd를 등록한다.
  • FD_CLR(int fd, fd_set* fdset) // 매개변수로 전달된 fdset에 전달된 소켓 정보 fd를 삭제한다. 
  • FD_ISSET(int fd, fd_set* fdset) // 매개변수로 전달된 fdset에 전달된 소켓 정보 fd가 이미 있으면 양수를 반환한다.

검사(관찰)의 범위 지정과 타임아웃의 설정

  • int select( int maxfd, fd_set* readset, fd_set* writeset, fd_set* exceptset, const struct timeval* timeout);
  • maxfd // 검사 대상이 되는 파일 디스크립터의 수
  • readset // 수신된 데이터의 존재 여부에 관심있는 파일 디스크립터의 정보를 모두 등록해서 변수 주소 값 전달
  • writeset // 블로킹 없는 데이터의 전송 가능 여부를 readset과 같이 매개 변수로 전달
  • exceptset // 예외 상황의 발생 여부에 관심이 있는 파일 디스크립터 정보를 모두 등록해서 전달
  • timeout // 무한정 블로킹 상태에 빠지는 것을 방지하고자 timeout 설정
  • 반환 값 // 오류 시에는 -1을 반환하고, 타임아웃에 의한 반환에는 0, 관찰 대상의 변화 발생 시에는 양수 반환.

마지막으로 반환 값이 양수인 경우에는, 변화가 발생한 파일 디스크립터의 수를 의미한다.

 

이제 파일 디스크립터의 관찰 범위와, select 함수의 타임아웃 시간만 결정하면 된다.

 

반응형