Live hot, Think cool

 

소켓프로그래밍은 응용프로그램을 만들기 위해 접해야할 네트워크 프로그래밍의 기본이다.

기본이라는 말은 네트워크를 하거나 응용프로그램을 하는 사람이라면 당연 알아야된다는 말이다.

(전에 여러번 다루었었지만, 요즘 공학 소울이 많이 무뎌진것같아서 이런글을 포스팅해본다.)

 

소켓은 세션으로 이해해도 무관하다.

TCP/IP, UDP/IP 프로토콜은 클라이언트/서버 모델을 사용하는데

물리적계층-데이터링크계층-네트워크계층-전송계층-세션계층-표현계층-응용프로그램계층 으로

OSI7계층이 나뉘고

물리적계층-데이터링크계층-네트워크계층-응용프로그램계층으로

네트워크 4계층이 나뉘는데

 

소켓프로그램은 세션계층으로 볼수있다.

 

전송계층은 TCP, UDP

네트워크계층은 대표적으로 IP 프로토콜, ARP

데이터링크계층은 대표적으로 이더넷 프로토콜

물리적계층은 시리얼통신(RS232)등 통신표준으로 볼수있다. 

 

여기에 응용계층으로 HTTP, TELNET, SNMP, DNS, XMPP, SSL, SSH, SMTP, RIP, FTP 등

ICT를 하는 사람이라면 무엇하나라도 접하고 다루었을만한 친숙한 응용프로그램들이 있다.

 

이 TCP, IP 뿐만 아니라 다양한 응용프로그램들을 다루기위한 네트워크의 시작이

 

소켓프로그래밍이라 할 수 있다.

 

(네트워크계층, 데이터링크계층을 다루려면 커널을 다루어보자.)

 

일단, 소켓프로그램의 구조는 서버/클라이언트 모델을 따르는데 구현은 아래의 사진과 같다.

 

 

 

 

다음은 C로 간단히 구현한 서버측 프로그램이다.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.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 i;
int serv_sock;
int clnt_sock;
struct sockaddr_in serv_addr;
struct sockaddr_in clnt_addr;
int clnt_addr_size;
char message[256];
int ending = 0;
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; //Internet protocol

serv_addr.sin_addr.s_addr = htonl(INADDR_ANY); //Ip address
serv_addr.sin_port = htons(atoi(argv[1])); //Port
if(bind(serv_sock, (struct socketaddr*) &serv_addr, sizeof(serv_addr)) == -1) // 소켓에 주소 할당
error_handling("bind() error");
if(listen(serv_sock, 5) == -1) //listen stat 돌입
error_handling("listen() error");
clnt_addr_size = sizeof(clnt_addr);
while(!ending)
{
clnt_sock=accept(serv_sock, (struct sockaddr*) &clnt_addr, &clnt_addr_size); //연결 요
청이 들어오면 수락
if(clnt_sock == -1)
error_handling("accept() error");
scanf("%s", message);
write(clnt_sock, message, sizeof(message)); //전송할 데이터 쓰기, 이곳에 클라이언트에 보낼 데이터를 넣으면된다.
if(message[0] == 0x1b) ending = 1;
}
close(clnt_sock);
return 0;
}
void error_handling(char *message)
{
fputs(message, stderr);
fputc('₩n', stderr);
exit(1);
}

 

 

다음은 클라이언트측 프로그램이다.

#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;
int ending = 0;
if(argc!=3)
{
printf("Usage : %s <IP> <port>₩n", argv[0]);
exit(1);
}
while(!ending)
{
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");
str_len = read(sock, message, sizeof(message) -1); //데이터 수신, 서버에서 받은메시지를 가지고 서비스를 제공한다.
if(str_len == -1)
error_handling("read() error!");
message[str_len] = 0;

printf("Message from server : %s ₩n", message);
if(message[0] == 0x1b) ending = 1;
close(sock); //연결 종료
}
return 0;
}
void error_handling(char *message)
{
fputs(message, stderr);
fputc('₩n', stderr);
exit(1);
}

 

위 예제로 비쥬얼스튜디어나, 이클립스 등으로 컴파일링해서 구현해본다면..

당신은 진정한 프로그래머 소울을 가진 사람이라 생각된다.