프로토콜의 이해와 소켓의 생성

프로토콜이란?

 - 개념적으로 약속의 의미를 담고 있다.

 - 컴퓨터 상호 간의 데이터 송수싱네 필요한 통신 규약.

 - 소켓을 생성할 때 기본적인 프로토콜을 지정해야한다.


#include <sys/socket.h>


int socket(int domain, int type, int protocol); 

-> 성공시 파일 디스크립터, 실패 시 -1 반환 

 - domain 소켓이 사용할 프로토콜 체계(Protocol Family) 정보 전달.

 - type 소켓의 데이터 전송방식에 대한 정보 전달.

 - protocol 두 컴퓨터 간 통신에 사용되는 프로토콜 정보 전달.


프로토콜 체계(Protocol Family)

프로토콜 체계

 - 프로토콜도 그 종류에 따라서 부류가 나뉘는데, 그 부류를 가리켜 프로토콜 체계라 한다.

 - 프로토콜의 체계 PF_INET은 IPv4인터넷 프로토콜 체계를 의미한다. 우리는 이를 기반으로 소켓 프로그래밍을 학습한다.

이름 

프로토콜 체계(Protocol Family) 

PF_INET 

IPv4 인터넷 프로토콜 체계 

PF_INET6 

IPv6 인터넷 프로토콜 체계 

PF_LOCAL 

로컬 통신을 위한 UNIX 프로토콜 체계 

PF_PACKET 

Low Level 소켓을 위한 프로토콜 체계 

PF_IPX 

IPX 노벨 프로토콜 체계 


소켓의 타입(Type)

소켓의 타입

 - 데이터 전송방식을 의미함.

 - 소켓이 생성될 때 소켓의 타입도 결정되어야 한다.


프로토콜 체계 PF_INET의 대표적인 소켓 타입 둘

 - 연결 지향형 소켓 타입

 - 비 연결 지향형 소켓 타입.


연결지향형 소켓(SOCK_STREAM)의 데이터 전송 특성

 - 중간에 데이터 소멸되지 않는다.

 - 전송 순서대로 데이터가 수신된다.

 - 데이터의 경계가 존재하지 않는다.

 - 소켓 대 소켓의 연결은 반드시 1대 1의 구조.


비 연결지향형 소켓(SOCK_DGRAM)의 데이터 전송특성

 - 전송순서 상관없이 빠른 속도의 전송을 지향

 - 데이터 손실 및 파손의 우려있다.

 - 데이터의 경계가 존재한다.

 - 한번에 전송할 수 있는 데이터의 크기가 제한된다.


프로토콜의 최종 선택

TCP 소켓

int tcp_socket= socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); 


UDP 


int udp_socket= socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);


-> 첫 번째, 두번재 인자로 전달된 정보를 통해서 소켓의 프로토콜이 사실상 결정 되기 때문에 세번재 인자로 0을 전달해도된다.



tcp_server.c

#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 serv_sock;

int clnt_sock;


struct sockaddr_in serv_addr;

struct sockaddr_in clnt_addr;

socklen_t clnt_addr_size;


char message[]="Hello World!";

if(argc!=2){

printf("Usage : %s <port>\n", argv[0]);

exit(1);

}

serv_sock=socket(PF_INET, SOCK_STREAM, 0);

if(serv_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=htonl(INADDR_ANY);

serv_addr.sin_port=htons(atoi(argv[1]));

if(bind(serv_sock, (struct sockaddr*) &serv_addr, sizeof(serv_addr))==-1)

error_handling("bind() error"); 

if(listen(serv_sock, 5)==-1)

error_handling("listen() error");

clnt_addr_size=sizeof(clnt_addr);  

clnt_sock=accept(serv_sock, (struct sockaddr*)&clnt_addr,&clnt_addr_size);

if(clnt_sock==-1)

error_handling("accept() error");  

write(clnt_sock, message, sizeof(message));

close(clnt_sock);

close(serv_sock);

return 0;

}


void error_handling(char *message)

{

fputs(message, stderr);

fputc('\n', stderr);

exit(1);

}



tcp_client.c

#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);

}



블로그 이미지

잉비니

,