클라이언트 함수
Server/Winodw Network 2015. 8. 7. 18:20클라이언트 동작 원리
1. socket()으로 소켓 생성
2. connet() 서버에 접속
3. send(), recv() 데이터 전송 함수 이용해서 서버와 통신을 수행하고 closesocket() 으로 닫음
connect()
클라이언트가 서버에 접속하여 TCP 프로토콜 수준의 연결이 이루어지도록 한다.
name
- 소켓 주소 구조체 변수를 서버 주소(원격 IP 주소와 원격 포트 번호)로 초기화한 후, 이 변수의
주소값을 여기에 대입한다.
namelen
- 소켓 주소 구조체 변수의 길이(바이트 단위)를 대입한다.
클라이언트는 서버와 달리 bind()를 호출하지 않는다.
bind()함수를 호출하지 않은 상태에서 connect()를 호출하면 운영체제는 자동으로
지역 IP와 지역 포트 번호를 설정한다.
이때 자동으로 할당되는 포트 번호는 운영체제에 따라서 다를 수 있으므로 윈도우의 경우에는
1024 ~ 5000 범위 중에 하나가 할당된다.
데이터 전송 함수
- 데이터 전송 함수는 크게 데이터를 보내는 함수, 데이터를 받는 함수로 구분할 수 있다.
- 가장 기본이 되는 함수는 send(), recv()가 있다.
소켓 데이터 구조체
송신 버퍼(send buffer)
- 데이터를 전송하기 전에 임시로 저장해두는 영역
수신 버퍼(receive buffer)
- 받은 데이터를 애플리케이션이 처리하기 전까지 임시로 저장해두는 영역
송신 버퍼, 수신 버퍼를 통틀어서 소켓 버퍼(socket buffer)라고 부른다.
데이터 전송 함수를 사용할 때는 하부 프로토콜의 특성을 알고 있어야 한다.
TCP 프로토콜은 애플리케이션이 보낸 데이터의 경계를 구분하지 않는다는 특징이 있다.
예를 들어서 클라가 100,200,300의 데이터를 차례로 보낸다면, 서버가 100,200,300바이트 데이터의 경계를 구분하지 못하고 350,250바이트 데이터를 읽을 수 있다.
따라서 TCP 서버/클라를 작성할 때 데이터 경계 구분을 위한 상호 약속이 필요하고,
이를 애플리케이션 수준에서 처리해야 한다.
send()
애플리케이션 데이터를 송신 버퍼에 복사함으로써 궁극적으로 하부 프로토콜(ex.TCP/IP)에 의해서 데이터가 전송되도록 한다.
send()함수는 데이터 복사가 성공적으로 이루어지면 곧바로 리턴하므로 send() 성공했다고 실제 데이터가 전송이 완료되는 것은 아니다.
s
- 통신할 대상과 연결된(connected) 소켓이다.
buf
- 보낼 데이터를 담고 있는 애플리케이션 버퍼의 주소.
len
- 보낼 데이터 크기(바이트 단위)
flags
- send() 함수의 동작을 바꾸는 옵션
- 대부분 0을 사용하며, 드물게 MSG_DONTROUTE, MSG_OOB를 사용하는 경우가 있다.
send() 첫번째 인자로 사용한 소켓의 특성에 따라서 다음과 같이 두 종류의 성공적인 리턴을 할 수 있다.
1. 블로킹(blocking) 소켓
- 지금까지 생성한 모든 소켓은 블로킹 소켓이다.
- 블로킹 소켓에 대해 send() 함수를 호출할 때, 송신 버퍼의 여유공간이 send()함수의 세번째 인자인 len보다 작을 경우 해당 프로세스는 대기 상태(wait state)가 된다.
- 송신버퍼에 충분한 공간이 생기면, 프로세스는 깨어나고, len크기만큼 데이터 복사가 이루어지고 send()함수가 리턴된다.
- 위와 같은 경우 send()함수의 리턴값은 len과 같게 된다..
2. 넌블로킹(Nonblocking) 소켓
- ioctlsocket() 이용하면 블로킹 소켓을 넌블로킹 소켓으로 바꿀 수 있다.
- 넌블로킹 소켓에 대해 send()를 호출하면, 송신 버퍼의 여유 공간만큼 데이터를 복사한 후,
실제 복사한 데이터 바이트 수를 리턴한다.
- 이 경우 send() 함수의 리턴값은 최소 1, 최대 len이 된다.
recv()
- 수신 버퍼에 도착한 데이터를 애플리케이션 버퍼로 복사하는 역할을 한다.
s
- 통신할 대상과 연결된 소켓이다.
buf
- 받은 데이터를 저장할 애플리케이션 버퍼의 주소이다.
len
- 수신 버퍼로부터 복사할 최대 데이터 크기(바이트 단위)이다.
- 이 값은 buf가 가리키는 버퍼의 크기보다 크지 않아야 한다.
flags
- recv() 함수의 동작을 바꾸는 옵션
- 대부분 0을 사용
- 드물게 MSG_PEEK과 MSG_OOB를 사용하는 경우가 있다.
recv()의 성공적인 리턴 경우
- 수신 버퍼에 데이터가 도달한 경우
recv()의 세번째 인자인 len보다 크지 않은 범위 내에서 가능한 많은 데이터를 애플리케이션 버퍼로 복사한다.
이 경우에 복사한 바이트 수가 리턴되며, 가능한 최대 리턴값은 len이 된다.
- 접속이 정상 종료된 경우
상대 애플리케이션이 closesocket()으로 접속 종료하면
TCP 프로토콜 수준에서 접속 종료를 위한 패킷 교환 절차가 이루어진다.
이 경우에 recv()는 0을 리턴한다.
recv() 함수의 리턴값이 0인 경우를 정상 종료(normal close = graceful close) 라 부른다.
recv() 함수 사용할 때 주의점
- 세번째 인자인 len으로 지정한 크기보다 작은 데이터가 애플리케이션 버퍼로 복사될 수 있다는 사실이다. ** 이것은 TCP가 메세지 경계를 구분하지 않는다는 특성에 기인한 것이다.
따라서 자신이 받을 데이터의 크기를 미리 알고 있다면 이 크기만큼 받을 때까지 recv함수를 여러 번 호출해야 한다..
'Server > Winodw Network' 카테고리의 다른 글
recvn() (0) | 2015.08.10 |
---|---|
브로드캐스팅 (0) | 2015.08.08 |
TCP/IP 서버/클라 구조 (0) | 2015.08.04 |
도메인 이름 시스템과 이름 변환 함수 (0) | 2015.08.04 |
IP 주소 변환 (0) | 2015.08.04 |