2.1 socket & protocol
protocol: 규약
family: 체계
socket( )
#include <sys.socket.h>
int socket(int domain, int type, int protocol)
// 성공시 디스크립터 반환, 실패시 -1 반환
// domain : 소켓이 사용할 프로토콜 체계(Protocol Family) 정보 전달
// type : 소켕의 데이터 정보 전달 방식
// protocol : 두 컴퓨터 간에 통신에 사용되는 프로토콜 정보 전달
int domain
프로토콜 체계(Protocol Family) 이름 | 정의 |
PF_INET | IPv4인터넷 프로토콜 |
PF_INET6 | IPv6인터넷 프로토콜 |
PF_LOCAL | LOCAL 통신을 위한 UNIX 프로토콜 |
PF_PACKET | Low level socket을 위한 인터페이스 |
PF_IPX | IPX 노벨 프로토콜 |
* PF = Packet Family
* INET = InterNET
프로토콜 패밀리는 소켓을 생성할 때 , 소켓이 사용될 환경을 고려해 지정한다
유닉스 계열의 시스템 내부의 프로세스들끼리 통신을 하기 위해서도 사용된다.
int type
1. 소켓의 타입이란, 소켓의 데이터 전송 방식이다.
프로토콜 체계가 정해지더라도, 전송방식까지 결정되는 것은 아니다.
예로, PF_INET 프로토콜에서도 둘 이상의 전송방식이 존재한다.
2. SOCK_STREAM : 연결 지향형 소켓
1:1 연결
순자척 전송
한번의 전송 실행에서, 먼저 보내진 데이터보다 뒤에 보내진 데이터가 일찍 도착 할 수 없다.
(여러 전송 실행에서는 인터넷 망에서 도착 순서를 보장하지 못한다)
수신받는 소켓의 상태를 체크하여 데이터 손실이 거의 발생하지 않는다.
3. SOCK_DGRAM : 비 연결 지향형 소켓
순서 상관없이 가장 빠른 전송
데이터 손실의 우려
데이터의 Boundary가 존재
int protocol
두 컴퓨터간 통신에 사용되는 프로토콜 정보 전달
일반적으로 0으로 입력해도 가능하다.
하지만 하나의 프로토콜 체계에서, 동일한 전송방식을 가진 프로토콜이 둘 이상 존재하는 경우에 명시한다,
TCP 소켓
PF_INET, IPv4 인터넷 프로토콜 체계에서 동작하는
SOCK_STREAM, 연결 지향형 데이터 전송 소켓
위 두가지 조건을 만족하는 프로토콜을 IPPROTO_TCP 하나다.
int tcp_socket=socket(PF_INET , SOCK_STREAM , IPPROTO_TCP);
UDP 소켓
PF_INET, IPv4 인터넷 프로토콜 체계에서 동작하는
SOCK_DGRAM, 비연결 지향형 데이터 전송 소켓
위 두가지 조건을 만족하는 프로토콜을 IPPROTO_UDP 하나다.
int udp_socket=socket(PF_INET , SOCK_DGRAM , IPPROTO_UDP);
TCP 소켓 테스트
TCP 소켓의 연결 특성 파악을 위해 이전 예제를 수정한다.
hello_server.c → tcp_server.c 변경사항 없음
hello_client.c → tcp_clinet.c read 함수의 호출방식 변경
"전송되는 데이터의 경계(Boundary)가 존재하지 않는다." 를 확인하기 위해 송신, 수신 횟수를 불일치 시킨다.
Server 에서 write(전송)의 호출 횟수는 1번이다. 반면, Client의 Socket Buffer 에 담긴 "Hello World!"를 1바이트씩 13회 읽어들인다.
출처 & 참고
1. 윤성우 열혈 TCP IP 소켓 프로그래밍 Ch. 02
코드
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/types.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){
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);
}