TCP/IP 서버/클라 구조
Server/Winodw Network 2015. 8. 4. 17:58TCP/IP 서버/클라 동작 방식
1. 서버가 먼저 실행한다. 서버는 클라가 접속하기를 기다린다.(listen)
2. 클라가 서버에 접속(connect)하여 데이터를 보낸다.(send)
3. 서버는 클라의 접속을 수용하고(accept), 클라가 보낸 데이터를 받는다.(recv)
4. 서버는 처리한 데이터를 클라에게 보낸다.(send)
5. 클라는 서버가 보낸 데이터를 받아서(recv) 자신의 목적에 사용한다.
동작 원리
1. 서버는 소켓을 생성한 후에 클라이언트가 접속하기를 기다린다.
이때 사용하는 소켓은 특정포트번호(예를 들어 9000)와 결합(bind)되어서 이 포트번호로 접속하는 클라이언트만 수용할 수 있다.
2. 클라이언트가 접속한다. 이때 TCP 프로토콜 수준에서 연결 설정을 위한 패킷 교환이 이루어진다.
3. TCP 프로토콜 수준의 연결절차가 끝나면, 서버는 접속한 클라이언트와 통신할 수 있는 새로운 소켓을 생성한다.
- 서버가 클라이언트와 데이터를 주고받을 때는 이 소켓(새로만든 소켓)을 사용한다.
- 기존의 소켓(맨 처음 만들어진 소켓)은 새로운 클라이언트 접속을 수용하는 용도로 계속 사용한다.
서버는 제일 처음 소켓을 열고 그 소켓에 있는 포트번호를 이용해서 해당 포트번호에 들어오는
클라이언트만을 수용할 것이다.
그리고 클라이언트가 서버에 접속을 하고 TCP프로토콜 수준의 연결절차가 이루어 지는데,
이 과정이 끝나면 서버는 클라이언트와 통신할 수 있는 새로운 소켓을 하나 더 생성한다.
그리고 기존의 소켓은 새로운 클라이언트가 들어올 때 서버에 접속하려면 이 해당 기존소켓을
통해서 들어와야 하며, 이는 서버쪽에서 지정해 놓은 포트번호만이 가능하다는 의미가 된다.
그리고 이렇게 새롭게 연결된 클라이언트는 서버가 시작될 때, 생성된 소켓으로 들어가서
접속허락이 되면 다시 데이터 송수신을 위한 소켓을 한개 더 만들게 되는 것이다.
즉, 서버쪽에서 소켓은 클라이언트의 접속을 수용하는 유일한 소켓 하나와 클라이언트의 수만큼
소켓이 필요한 것이다.
Server 단계
1. 윈도우 소켓 초기화( 이거 해야지 소켓을 사용할 수 있다.)
2. 소켓생성( 클라이언트 수용을 위한 소켓을 만드는 것이다.) 서버의 구멍을 뚫는 것임
3. bind() : 해당 소켓을 수용할 IP와 포트 번호를 설정한다.
4. listen() : 3번으로 결합된 TCP 포트상태를 listening으로 바꿔준다.
- 클라이언트의 접속을 받아들일 수 있는 상태가 된 것이다.)
5. accept() : listen()이 완료되면 클라이언트 수용을 위한 소켓에 있는 데이터를 통해서
데이터 송수신을 위한 소켓을 리턴한다.
** TCP/IP를 이용하여 애플리케이션이 통신을 수행하기 위해선 다음과 같은 요소가 필요
- 프로토콜( 소켓을 생성할 때 결정)
- 지역 IP주소와 지역 포트 번호 (서버 또는 클라의 자신의 주소를 의미)
- 원격 IP주소와 원격 포트 번호( 서버 또는 클라가 통신하는 상대의 주소를 의미)
서버 함수
1. socket() 이용해서 소켓을 생성한다.
2. bind() 이용해서 지역 IP와 지역 포트 번호를 결정한다.
3. listen() 이용해서 TCP 상태를 LISTENING으로 변경한다.
4. accept() 이용해서 자신에 접속한 클라이언트와 통신할 수 있는 새로운 소켓을 생성한다.
여기서 원격 IP주소와 원격 포트 번호가 결정된다.
5. send(), recv() 등의 데이터 전송 함수 이용해서 클라와 통신한 후 , closesocket() 이용해서 소켓을 닫는다.
6. 새로 클라가 접속할때마다 4,5 반복한다.
// bind()
서버의 지역 IP주소와 지역 포트번호를 결정하는 역할을 한다.
int bind( SOCKET s, const struct sockaddr* name, int namelen)
s
클라이언트 접속을 수용할 목적으로 만든 소켓 (지역 IP와 포트 번호 결정되지 않은 상태이다,)
Name
소켓 주소 구조체(TCP/IP 인 경우 SOCKADDR_IN 타입) 변수를 지역 IP주소와 지역 포트번호로
초기화한 후, 이 변수의 주소값을 여기에 대입한다.
( 해당 소켓 s에 name의 정보를 대입한다. (const이므로 name의 데이터 바꿀 수 없다.))
namelen
소켓 주소 구조체 변수의 길이를 대입한다.
** 요약하자면 bind()는 name구조체의 해당 소켓을 연결하는 역할을 한다.
name구조체에는 포트 번호와 IP주소 그리고 AF_INET이 저장되어있고 , 이것을 소켓으로 붙여줌
이 함수를 호출하면 해당소켓에 name의 정보(포트 번호,IP,...)이 설정이 된다.
bind()는 다시말해서 클라이언트의 수용 용도로 지정되는 소켓의 정보를 만드는 함수이다.
bind() 성공시 0을 return 하고 실패시 SOCKET_ERROR을 리턴한다.
// listen
listen() 함수는 소켓과 결합된 TCP 포트 상태를 LISTENING으로 바꾸는 역할을 한다.
이는 클라이언트 접속을 받아들일 수 있는 상태가 됨을 의미한다.
int listen( SOCKET s, int backlog )
s
클라이언트 접속을 수용할 목적으로 만든 소켓으로, bind()함수에 의해 지역 IP와
지역 포트 번호가 설정된 상태이다.
backlog
서버가 당장 처리하지 않아도 접속 가능한 클라이언트의 개수이다.
클라이언트의 접속 정보는 연결 큐(connection queue)에 저장되며, backlog는 이 연결 큐의
길이를 나타낸다고 볼 수 있다.
하부 프로토콜에서 지원 가능한 최대값을 사용하려면 SOMAXCONN 값을 대입한다.
// accept()
accept() 함수는 서버에 접속한 클라이언트와 통신할 수 있도록 새로운 소켓을 생성하여
리턴하는 역할을 한다.
또한 접속한 클라이언트의 IP주소와 포트 번호(서버 입장에서는 원격 IP주소와 원격 포트번호,
클라이언트 입장에서는 지역 IP주소와 지역 포트 번호)를 알려준다.
** 여기에 접속했다는 사실은 TCP 프로토콜 수준에서 연결설정이 성공적이라는 것을 알려준다.
SOCKET accept( SOCKET s, struct sockaddr* addr, int *addrlen );
s
클라이언트 접속을 수용할 목적으로 만든 소켓이다.
addr
소켓 주소 구조체 변수를 정의한 후, 이 변수의 주소값을 여기에 대입한다.
accept() 함수는 addr이 가리키는 메모리 영역을 클라이언트의 IP주소와 포트 번호로 채워 넣는다.
addrlen
정수형 변수를 addr이 가리키는 메모리 영역의 크기로 초기화한 후, 이 변수의 주소값을 여기에 대입한다. accept() 함수가 리턴하면, 정수형 변수는 addrlen은 함수가 초기화한 메모리 크기값(바이트 단위)를 가진다.
** 클라이언트의 IP주소와 포트 번호를 알 필요가 없다면 addr과 addrlen에 NULL을 사용한다.
접속한 클라이언트가 없을 경우에 accept() 함수는 서버를 대기 상태로 만든다.
클라이언트가 접속하면 서버는 깨어나고 accept() 함수는 비로소 리턴하게 된다.
'Server > Winodw Network' 카테고리의 다른 글
브로드캐스팅 (0) | 2015.08.08 |
---|---|
클라이언트 함수 (0) | 2015.08.07 |
도메인 이름 시스템과 이름 변환 함수 (0) | 2015.08.04 |
IP 주소 변환 (0) | 2015.08.04 |
바이트 정렬 함수 (0) | 2015.07.20 |