TCP/IP 프로토콜 스택
- 인터넷 기반의 데이터 송수신을 목적으로 설계된 스택
- 큰 문제를 작게 나눠서 계층화 한 결과
- 데이터 송수신의 과정을 5개의 영역으로 계층화 한 결과
- 각 스택 별 영역을 전문화하고 표준화 함
- 7계층으로 세분화가 되며, 5계층으로도 표현함
APPLICATION 계층
TCP 계층 UDP 계층IP계층 LINK 계층 물리계층
물리&링크 계층의 기능 및 역할
- 물리적인 영역의 표준화 결과
- 기존 Layer1, Layer2 프로토콜 그대로 적용
- LAN, WAN, MAN과 같은 물리적인 네트워크 표준 관련 프로토콜이 정의된 영역
- 아래의 그림과 같은 물리적인 연결의 표준이 된다.
IP 계층의 기능 및 역할
- IP는 Internet protocol을 의미함
- 경로의 설정과 관련이 있는 프로토콜
TCP/UDP 계층
TCP 계층의 기능 및 역할
- 실제 데이터의 송수신과 관련 있는 계층
- 그래서 전송 계층이라고도 함
- TCP는 데이터의 전송을 보장하는 프로토콜(신뢰성 있는 프로토콜), UDP는 보장하지 않는 프로토콜
- TCP는 신뢰성을 보장(ack 사용)하기 때문에 UDP에 비해 복잡한 프로토콜이다.
APPLICATION 계층
프로그래머에 의해서 완성되는 APPLICATION 계층
응용프로그램의 프로토콜을 구성하는 계층
소켓을 기반으로 완성하는 프로토콜을 의미함
소켓을 생성하면, 앞서 보인 LINK, IP, TCP/UDP 계층에 대한 내용은 감춰진다.
그러니 응용 프로그래머는 APPLICATION 계층의 완성에 집중하게 된다.
TCP 서버의 기본적인 함수호출 순서
bind 함수까지 호출이 되면 주소가 할당된 소켓을 얻게된다. 따라서 listen 함수의 호출을 통해서 연결요청이 가능한 상태가 되어야 한다.
#include <sys/type.h>
int listen(int sokck, int backlog);
// 성공 시 0, 실패 시 -1 반환
// sock : 연결요청 대기상태에 두고자 하는 소켓의 파일 디스크립터 전달, 이 함수로 전달된 디스크립터의 소켓이 서버 소켓(리스닝 소켓)이 된다.
// backlog : 연결요청 대기 큐의 크기정보 전달, 5가 전달되면 큐의 크기가 5가 되어 클라이언트의 연결요청을 5개까지 대기시킬 수 있다.
연결요청도 일종의 데이터 전송이므로 연결요청을 받아들이기 위해서도 하나의 소켓이 필요하다. 이 소켓을 가리켜 서버소켓 또는 리스닝 소켓이라 한다. listen 함수의 호출은 소켓을 리스닝 소켓이 되게 한다.
클라이언트의 연결요청 수락
#include <sys/socket.h>
int accept(int sock, struct sockaddr * addr, socklen_t * addrlen);
// 성공 시 생성된 소켓의 파일 디스크립터, 실패 시 -1 반환
// sock : 서버 소켓의 파일 디스크립터 전달
// addr : 연결요청 한 클라이언트의 주소정보를 담을 변수의 주소 값 전달, 함수호출이 완료되면 인자로 전달된 주소의 변수에는 클라이언트의 주소정보가 채워진다.
// addrlen : 두 번째 매개변수 addr에 전달된 주소의 변수 크기를 바이트 단위로 전달, 단 크기정보를 변수에 저장한 다음에 변수의 주소 값을 전달한다. 그리고 함수호출이 완료되면 크기정보로 채워져 있던 변수에는 클라이언트의 주소정보 길이가 바이트 단위로 계산되어 채워진다.
연결요청 정보를 참조하여 클라이언트 소켓과의 통신을 위한 별도의 소켓을 추가로 하나 더 생성한다. 그리고 이렇게 생성된 소켓을 대상으로 데이터의 송수신이 진행된다.
TCP 클라이언트의 기본적인 함수호출 순서
#include <sys/socket.h>
int connect(int sock, const struct sockaddr * servaddr, socklen_t addrlen);
// 성공 시 0, 실패 시 -1 반환
// sock : 클라이언트 소켓의 파일 디스크립터 전달
// servaddr : 연결요청 한 클라이언트의 주소정보를 담을 변수의 주소 값 전달, 함수호출이 완료되면 인자로 전달된 주소의 변수에는 클라이언트의 주소정보가 채워진다.
// addrlen : 두 번째 매개변수 servaddr에 전달된 주소의 변수 크기를 바이트 단위로 전달, 단, 크기정보를 변수에 저장한 다음에 변수의 주소 값을 전달한다. 그리고 함수호출이 완료되면 크기정보로 채워져 있던 변수에는 클라이언트의 주소정보 길이가 바이트 단위로 계산되어 채워진다.
socket() (소켓생성) -> connect() (연결요청) -> read()/write() (데이터 송수신) -> close() (연결종료)
클라이언트의 경우 소켓을 생성하고, 이 소켓을 대상으로 연결의 요청을 위해서 connect 함수를 호출하는 것이 전부이다. 그리고 connect 함수를 호출할 때 연결할 서버의 주소 정보도 함께 전달한다. connect() 호출전에 서버 주소는 구조체에 미리 채워져 있어야 한다.
클라이언트 소켓의 바인딩 시점은?
- 클라이언트는 언제 바인딩을 하는가?
- 클라이언트도 소켓을 생성하므로 IP와 포트주소를 소켓에 할당해야 한다.
- 묵시적 바인딩 vs 명시적 바인딩
- 서버는 명시적 바인딩(bind() 함수 사용)
- 클라이언트는 묵시적 바인딩
- 바인딩 시점은?
- 언제? : connect() 함수가 호출되기 직전에
- 어디서? : OS (시스템 커널에서)
- 어떻게? : 호스트에서 IP를 찾고, 포트는 임의로 선택해서 할당
서버, 클라이언트의 함수호출 관계
서버의 listen 함수 호출 이후에야 클라이언트의 connect 함수호출이 유효하다.
'TCP&IP' 카테고리의 다른 글
[C#] 소켓 통신시 Byte -> String 에서 널(\0)문자 제거하기 (0) | 2021.11.23 |
---|