프로토콜(Protocol)이란 무엇인가?
멀리 떨어져있는 두 사람이 대화를 주고받기 위해선 한 사람이 전화를 통해 대화를 시도하면. 다른 사람도 전화를 통해서 대화를 해야한다. 편지를 쓰면 안되기 때문에 두 사람의 대화 방식은 전화가 된다.
이 두사람이 대화에 사용한 프로토콜은 전화라고 볼 수 있다.
이렇듯 프로토콜은 대화에 필요한 통신규약이라고 볼 수 있다.
즉 "컴퓨터 상호간의 대화에 필요한 통신규약"
소켓의 생성
#include <sys/socket.h>
int socket(int domain, int type, int protocol);
성공시 파일 디스크립터, 실패시 -1 반환
domain : 소켓이 사용할 프로토콜 체계 정보 전달
type: 소켓의 데이터 전송방식에 대한 정보 전달
protocol: 두 컴퓨터간 통신에 사용되는 프로토콜 정보 전달
프로토콜 체계
PF_INET : IPv4 인터넷 프로토콜 체계 (가장 많이 씀)
PF_INET6 : IPv6 인터넷 프로토콜 체계
소켓의 타입
소켓의 타입이란 소켓의 데이터 전송방식 이 정보들을 soket함수의 두 번째 인자로 전달해야한다.
소켓의 타입1: 연결지향형 소켓(SOCK_STREAM)
- 중간에 데이터 소멸되지 않는다.
- 전송 순서대로 데이터가 수신된다.
- 데이터의 경계가 존재하지 않는다.
- 소켓 대 소켓의 연결은 반드시 1대1의 구조
소켓의 타입 2: 비연결지향형 소켓(SOCK_DGRAM)의 데이터 전송특성 : UDP 소켓
- 전송순서 상관없이 빠른 속도의 전송을 지향
- 데이터 손실 및 파손의 우려가 있다.
- 데이터의 경계가 존재한다.
- 한 번에 전송할 수 있는 데이터의 크기가 제한된다.
데이터 경계
- TCP 소켓
전송되는 데이터의 경계(boundary)가 존재하지 않음
데이터 전송 횟수와 수신 횟수가 일치하지 않음
1회 최대 전송 크기인 MTU (Maximum Transmission Unit)만큼 전송됨
Ethernet : 1500 byte - UDP 소켓
전송되는 데이터의 경계(boundary)가 존재함
데이터 전송 횟수와 수신 횟수가 일치해야 함
프로토콜의 최종 선택 !
// IPv4 인터넷 프로토콜 체계에서 동작하는 연결지향형 데이터 전송 소켓
int tcp_socket = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
// IPv4 인터넷 프로토콜 체계에서 동작하는 비 연결지향형 데이터 전송 소켓
int udp_socket = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
- 첫 번째, 두 번째 인자로 전달된 정보를 통해서 소켓의 프로토콜이 사실상 결정되기 때문에 세 번째 인자로 0을 전달해도 된다 !
#include <해더정보는 동일이니 생략>
void error_handling(char *message);
int main(int argc, char* argv[])
{
int sock;
struct sockaddr_in serv_addr;
char message[30];
int str_len=0;
int idx=0, read_len=0;
if(argc!=3){
printf("Usage : %s <IP> <port>\n", argv[0]);
exit(1);
}
sock=socket(PF_INET, SOCK_STREAM, 0);
if(sock == -1)
error_handling("socket() error");
memset(&serv_addr, 0, sizeof(serv_addr));
serv_addr.sin_family=AF_INET;
serv_addr.sin_addr.s_addr=inet_addr(argv[1]);
serv_addr.sin_port=htons(atoi(argv[2]));
if(connect(sock, (struct sockaddr*)&serv_addr, sizeof(serv_addr))==-1)
error_handling("connect() error!");
while(read_len=read(sock, &message[idx++], 1))
{
if(read_len==-1)
error_handling("read() error!");
str_len+=read_len;
}
printf("Message from server: %s \n", message);
printf("Function read call count: %d \n", str_len);
close(sock);
return 0;
}
void error_handling(char *message)
{
fputs(message, stderr);
fputc('\n', stderr);
exit(1);
}
sock=socket(PF_INET, SOCK_STREAM, 0);
-> TCP 소켓을 생성, 첫 번째 인자와 두 번째 인자로 각각 PF_INET, SOCK_STREAM가 전달되면 세 번째 인자인 IPPOTO_TCP는 생략가능
while(read_len=read(sock, &message[idx++], 1))
{
if(read_len==-1)
error_handling("read() error!");
str_len+=read_len;
}
-> whole문 안에서 read 함수를 반복 호출하는 중이다. 중요한 것은 이 함수가 호출될 때마다 1바이트씩 데이터를 읽어 들인다는 점!
만약 read 함수가 0을 반환하면 이는 거짓이니 while 문을 빠져나간다.
str_len+=read_len;
-> 이 문장이 실행될 때 변수 read_len에 저장되어 있는 값은 항상 1 왜냐하면 while문에서 1바이트씩 데이터를 읽고 있기 때문
즉 while문을 빠져나간 이후에 str_len에는 읽어 들인 바이트 수가 저장.
'스터디 > TCP 와 IP' 카테고리의 다른 글
6. 소켓의 우아한 연결 종료 (0) | 2024.09.03 |
---|---|
5. TCP 기반 서버/ 클라이언트 2 (0) | 2024.09.03 |
4. TCP 기반 서버/ 클라이언트 1 (0) | 2024.09.03 |
3. 주소체계와 데이터 정렬 (1) | 2024.09.03 |
1. 네크워크 프로그래밍과 소켓의 이해 (0) | 2024.09.02 |