모든 내용은 [윤성우 저, "열혈강의 TCP/IP 소켓 프로그래밍", 오렌지미디어] 를 기반으로 제 나름대로 이해하여 정리한 것입니다. 다소 부정확한 내용이 있을수도 있으니 이를 유념하고 봐주세요!
# 프로토콜이란?
- 대화에 필요한 통신규약
- 컴퓨터 상호간의 대화에 필요한 통신규약
- 서로 데이터를 주고받기 위해 정의해놓은 약속
# 소켓의 생성
#include <sys/socket.h>
int socket(int domain, int type, int protocol);
// -> 성공시 파일 디스크립터, 실패시 -1 반환
- domain : 소켓이 사용할 프로토콜 체계(Protocol Family) 정보 전달
- type : 소켓의 데이터 전송방식에 대한 정보 전달
- protocol : 두 컴퓨터간 통신에 사용되는 프로토콜 정보 전달
# 프로토콜 체계란?
- 소켓이 통신에 사용하는 프로토콜의 부류는 다양함
- 따라서, 소켓 생성시 사용할 프로토콜의 부류정보를 전달해야함(socket 함수의 첫번째 인자로 전달함)
- 이러한 부류정보를 "프로토콜 체계"라고 함
이름 | 프로토콜 체계(Protocol Family) |
PF_INET | IPv4 인터넷 프로토콜 체계 |
PF_INET6 | IPv6 인터넷 프로토콜 체계 |
PF_LOCAL | 로컬 통신을 위한 UNIX 프로토콜 체계 |
PF_PACKET | Low Level 소켓을 위한 프로토콜 체계 |
PF_IPX | IPX 노벨 프로토콜 체계 |
[표 : 헤더파일 sys/socket.h 에 선언되어있는 프로토콜 체계]
- 실제 소켓이 사용할 최종 프로토콜 정보는 socket 함수의 세번째 인자로 전달하는데,
socket 함수의 첫번째 인자인 프로토콜 체계 범위 내에서 세번째 인자를 결정해야 함
# 소켓의 타입
- 소켓의 데이터 전송방식을 의미
- socket 함수의 두번째 인자로 전달함
- 프로토콜 체계에도 둘 이상의 데이터 전송방식이 존재하기 때문에,
이것을 통해 명확하게 결정해주어야 함
# 대표적 데이터 전송방식
1) 연결지향형 소켓(SOCK_STREAM) : "신뢰성 있는 순차적인 바이트 기반의 연결지향 데이터 전송 방식의 소켓"
- 중간에 데이터가 소멸되지 않고 목적지로 전송됨
- 전송 순서대로 데이터가 수신됨
- 전송되는 데이터의 경계가 존재하지 않음 -> read, write 함수 호출횟수가 큰 의미를 가지지 않음
- 자신과 연결된 상대 소켓의 상태를 파악해가며 데이터를 전송함
(수신소켓의 입력버퍼가 꽉찬 경우에, 송신소켓은 데이터 전송을 멈춤)
(데이터가 제대로 전송되지 않으면, 송신소켓은 데이터를 재전송함)
- 소켓에 존재하는 버퍼가 꽉차는 경우에도 데이터는 소멸하지 않음
- 소켓 대 소켓의 연결은 반드시 1:1
2) 비연결지향형 소켓(SOCK_DGRAM) : "신뢰성과 순차적 데이터 전송을 보장하지 않는,
고속의 데이터 전송을 목적으로 하는 소켓"
- 전송된 순서에 상관없이 가장 빠른 전송을 지향함
- 전송된 데이터는 손실의 우려가 있고, 파손의 우려가 있음
- 전송되는 데이터의 경계가 존재함 -> read, write 함수 호출횟수가 서로 동일해야 함
- 한번에 전송할 수 있는 데이터의 크기가 제한됨
- 연결지향형 소켓과 다르게 연결이라는 개념이 존재하지 않음
# 프로토콜의 최종 선택(socket 함수의 세번째 인자)
- 대부분의 경우는 세번째 인자로 0을 넘겨주어도 무방
- 그러나, "하나의 프로토콜 체계(socket의 첫번째 인자) 안에 데이터의 전송방식(socket이 두번째 인자)이
동일한 프로토콜이 둘 이상 존재하는 경우"에는 반드시 필요
# TCP socket : "IPv4 인터넷 프로토콜 체계에서 동작하는 연결지향형 데이터 전송 소켓"
int tcp_socket=socket(PF_INET,SOCK_STREAM,IPPROTO_TCP);
# UDP socket : "IPv4 인터넷 프로토콜 체계에서 동작하는 비연결지향형 데이터 전송 소켓"
int udp_socket=socket(PF_INET,SOCK_DGRAM,IPPROTO_UDP);
# 연결지향형 소켓인 TCP 소켓의 예시(소스코드)
- 전송되는 데이터의 경계가 존재하지 않으므로, 이를 확인하기 위해
read, write 함수 호출횟수를 일부러 다르게 구현
- 서버 : 데이터 전체를 write 함수를 한번 호출하여 모두 전달
- 클라이언트 : read 함수를 여러번 호출하여 데이터 전체를 수신
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>
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) // 인자로 실행파일명/(서버의)IP/(서버의)Port번호 를 전달받아야 함
{
printf("Usage : %s <IP> <port>\n",argv[0]);
exit(EXIT_FAILURE);
}
sock=socket(PF_INET,SOCK_STREAM,0); // TCP 클라이언트소켓 생성
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]));
// 클라이언트소켓이 주소정보를 토대로 서버소켓에게 연결요청
// 이때, 클라이언트소켓의 주소정보가 할당됨
// IP는 호스트IP로, Port번호는 임의로.
if(connect(sock,(struct sockaddr*)&serv_addr, sizeof(serv_addr))==-1)
error_handling("connect() error!");
// read 함수를 통해 서버소켓에서 보내는 데이터를
// 1바이트씩 읽어들임
while(read_len=read(sock,&message[idx++],1))
{
if(read_len==-1) // read 함수가 -1을 반환하면 오류
error_handling("read() error!");
str_len+=read_len; // 총 읽어들인 데이터 바이트수를 계산
// (1바이트씩 읽었으므로 read 함수 호출 횟수를 의미하기도 함)
}
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(EXIT_FAILURE);
}
# 윈도우 운영체제의 socket 함수
#include <winsock2.h>
SOCKET socket(int af, int type, int protocol);
// -> 성공시 소켓 핸들, 실패시 INVALID_SOCKET 반환
- 전달하는 인자의 종류와 의미가 리눅스의 socket 함수와 완전히 동일
- 반환형만 조금 차이가 있는데, 이는 정수로 표현되는 소켓의 핸들값을 저장하기 위해
윈도우에서 정의된 자료형의 이름(SOCKET)
- INVALID_SOCKET의 값은 오류발생을 알리는 하나의 상수로, 이 값은 -1로 정의되어 있음
[출처] : 윤성우 저, "열혈강의 TCP/IP 소켓 프로그래밍", 오렌지미디어
'Programming > 열혈 TCP, IP 소켓 프로그래밍(저자 윤성우)' 카테고리의 다른 글
Ch 03. 주소체계와 데이터 정렬 (0) | 2020.08.05 |
---|---|
Ch 02. 내용 확인문제 (0) | 2020.08.04 |
표준 파일 입출력 함수(고수준 파일 입출력 함수) (0) | 2020.07.30 |
Ch 01. 내용 확인문제 (0) | 2020.07.28 |
Ch 01. 네트워크 프로그래밍과 소켓의 이해 (0) | 2020.07.28 |