서버의 생성 -------------------------------------------------------------------------------------------------------


단계 1 SOCKET socket(_In_  int af,_In_  int type,_In_  int protocol); 서버의 소켓을 생성한다 -----------------------


단계 2 int bind(_In_  SOCKET s, _In_  const struct sockaddr *name, _In_  int namelen); 소켓에 주소를할당 ----------


여기까지는 앞서 자세히 설명했던 내용이다. 다음부터가 실제 서버의 기능을 실행해주는 함수이다.


단계 3 int listen(_In_ SOCKET s, _In_ int backlog ); 클라이언트의 연결 요청을 받아줄 소켓을 할당한다 -----------------

int listen(

  _In_  SOCKET s, -> 클라이언트의 연결 요청을 받아줄 소켓인자나 파일 디스크럽터 호출.

  _In_  int backlog -> 연결 요청을 최대 몇명까지 대기하며 받아줄지에 대한 인자 값 (연결요청은 Queue로 처리된다)

);

listen 함수는 연결 요청을 대기해주는 함수이다. 단순하게 이야기 한다면 다음과 같다.

클라이언트가 서버에 연결을 원한다면 어떠한 신호를 서버에 보낸다고 생각해보자 이는 소켓과 소켓의 통신이라고 볼수 있다.

그를 위해서 하나의 소켓을 연결을 요청하는 클라이언트의 메세지를 받기위한 함수로 할당하는 것을 의미한다.

즉 매표소의 직원으로 손님이 오면 손님에게 표를 나눠주는 역할을 하는 소켓을 할당하는 함수이다.


* 여기에서 두번째 backlog는 동시에 연결요청이 왔을때 몇명까지 한번에 처리할 것인지 그 개수를 정하는 함수이다. 일반적으로 이 함수는 번잡한 서버일 경우 15정도의 인자를 준다고 한다.

* 이 함수를 통해서 클라이언트들은 Queue(자료구조를 생각하면 된다)에 의해서 줄을 서게된다. 그리고 한명한명씩 처리가된 클라이언트들이 실제적으로 서버에 입장을 하게 된다고 생각하면 편하다.


SOCKET accept( _In_ SOCKET s, _Out_ struct sockaddr *addr, _Inout_ int *addrlen ); 접속한 클라이언트의 담당 소켓 생성 --

SOCKET accept( 

 _In_     SOCKET s, -> 접속승인된 클라이언트를 담당할 파일디스크럽터나 소켓을 생성 

 _Out_    struct sockaddr *addr, -> 연결 요청된 클라이언트의 주소 정보를 담을 구조체 

 _Inout_  int *addrlen -> 두번째 매개변수 addr에 전달된 주소의 변수 크기를 바이트 단위로 전달하는 함수

                                  함수호출이 완료되면 크기정보로 채워져 있던 변수에 클라이언트의 주소정보가 바이트단위로 계산되어 채워진다. 

);


 일단 소켓과 소켓의 데이터송수신은 1vs1이라고 생각하자 listen함수의 소켓은 문지기라고 설명했다. 매표소 직원이 가계안에 들어온 손님의 서빙이나 기타잡무까지 같이 처리하려면 너무 바쁠 것이다. 이 가계는 손님이 들어오면 담당직원을 한명씩 붙여주는 구조이다.

  accept함수는 서버에 입장한 클라이언트와 직접적으로 데이터송수신을 할 소켓을 생성해주는 함수이다. 이 새로 생성된 소켓을 통해서 클라이언트와 실질적인 데이터 송수신을 하게 된다.

여기까지가 서버의 생성과 클라이언트의 접속을 허용하고 클라이언트를 받아들이는 서버의 생성단계였다. 이후 본격적인 데이터 송수신과 read write (리눅스)혹은 rend recv 함수를 통한 데이터 송수신은 추후 다시 다룬다.


클라이언트의 생성 -------------------------------------------------------------------------------------------------

단계 1 SOCKET socket(_In_ int af,_In_ int type,_In_ int protocol); 클라이언트의 소켓을 생성한다 -----------------


단계 2 int connect(_In_  SOCKET s, _In_  const struct sockaddr *name, _In_  int namelen); ------------------------

int connect(

_In_ SOCKET s, -> 클라이언트 소켓의 파일디스크립터나 소켓 전달. _In_ const struct sockaddr *name, 연결요청 할 서버의 주소정보를 담은 변수의 주소 값 전달. _In_ int namelen sockaddr에 전달된 주소의 변수 크기를 바이트 단위로 전달 );


listen함수에 대해서 기억한다면 listen함수는 클라이언트의 연결신호를 기다린다고 했다. 바로 이 함수가 클라이언트에 연결신호를 보내주는 함수이다. 일단 이 함수가 호출되면 다음의 상황이 와야 함수의 종료루틴이 호출된다.

1. 서버가 연결요청을 허락해주거나.

2. 네트워크 단절 등 오류상황이 발생하여 연결요청이 중단되거나.


* 클라이언트는 Bind함수를 이용할 필요가 없나?

서버를 구현하면서 반드시 거쳤던 과정 중 하나가 서버 소켓에 IP와 PORT를 할당하는 것이었다. connect함수는 자동으로 클라이언트의 소켓에 IP와 PORT가 할당된다. 따라서 클라이언트 프로그램을 구현할때는 BIND 함수를 명시적으로 호출할 필요가 없다.



연결의 과정 생성 ---------------------------------------------------------------------------------------------------

위의 그림을 보면 서버와 클라이언트의 생성 과정과 그 사이에 대한 이해가 될것이다. 서버가 생성되고 listen함수에 의해서 대기 상태에 들어가야 클라이언트가 connect함수를 통해서 연결이 가능해지는 구조가 눈에 보일 것이다.

Posted by JJOREG