네트워크 프로그래밍이란 ?
- 소켓을 가지고 프로그래밍하기 때문에 소켓 프로그래밍이라고도 한다.
- 네트워크로 연결된 둘 이상의 컴퓨터 사이에서의 데이터를 통신하는 프로그램
소켓이란 ?
- 네트워크(인터넷)의 연결 도구
- 운영체제에서 제공이 되며 프로그래머는 데이터 송수신에 대한 HW, SW에 대해 세부적인 신경을 쓰지 않아도 된다.
소켓은 간단히 말하면 전화기와 비교 할 수 있다.
중요한 점은 전화를 거는 용도의 소켓과 전화를 받는 용도의 소켓의 생성방법에는 차이가 있다.
#inlcude <sys/socket.h>
int socket(int domain, int type, int protocol);
// 성공 시 파일 디스크럽터, 실패시 -1 반환
소켓의 생성은 전화기를 사는 것과 같은 행동
전화기에 전화번호가 있듯이 소켓에도 주소 정보가 할당된다.
소켓의 주소 정보는 IP와 PORT 번호로 구성이 된다.
#include <sys/socket.h>
int bind(int sockfd, struct sockaddr *myaddr, socklen_t addrlen);
// 성공 시 파일 디스크럽터, 실패시 -1 반환
// sockfd - 파일 디스크럽터
연결 요청이 가능한 상태란 무엇인가 ?
소켓은 양방소통이 되는 휴대폰과 다르게 보내는 소켓과 받는 소켓이 나뉘어 진다.
연결 요청이 가능한 상태의 소켓이란 걸려오는 전화를 받을 수 있는 상태로 비유할 수 있다.
전화를 거는 용도의 소켓은 해당 상태가 필요 없다.
걸려오는 전화를 받을 용도의 소켓에서 필요한 상태이다.
#include <sys/socket.h>
int listen(int sockfd, int backlog);
//성공 시 0 반환, 실패 시 -1 반환
소켓에 할당된 IP와 PORT 번호로 연결요청이 가능한 상태가 된다.
연결 요청을 수락하는 상태
걸려오는 전화에 대해서 수락의 의미로 수화기를 드는 것에 비유할 수 있다.
연결 요청이 수락되어야 데이터의 송수신이 가능.
수락된 이후에는 데이터의 양방향 송수신이 가능하다.
#include <sys/socket.h>
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
// 성공 시 파일 디스크럽터, 실패 시 -1 반환
// accept 함수 호출 이후에는 데이터의 송수신이 가능하다.
// 단, 연결 요청이 있을 때에만 accept 함수가 반환을 한다.
// 해당 함수가 실행되고 나면 연결 요청이 가능한 상태로 변경된다.
정리하기
1. 소켓의 생성 - socket()
2. IP와 PORT 번호 할당 - bind()
3. 연결 요청 가능 상태로 변경 - listen()
4. 연결 요청에 대한 수락 - accept()
#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[]="2020118198, LeeSeokhwan";
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);
}
#include <sys/socket.h>
int connect(int sockfd, struct sockaddr *serv_addr, sockeln_t addrlen);
// 성공 시 0, 실패 시 -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=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);
}
- 저 수준 파일 입출력
ANSI의 표준 함수가 아닌 운영체제가 제공하는 함수 기반의 파일 입출력
표준이 아니기 때문에 OS에 대한 호환성이 없다.
리눅스는 소켓도 파일로 간주하기 때문에 저 수준 파일 입출력 함수를 기반으로 소켓 기반의 데이터 송수신이 가능하다.

- 파일 디스크립터
운영체제가 만든 파일(그리고 소켓)을 구분하기 위한 일종의 숫자
저 수준 파일 입출력 함수는 입출력을 목적으로 파일 디스크립터를 요구한다.
저 수준 파일 입출력 함수에게 소켓의 파일 디스크럽터를 전달하면, 소켓을 대상으로 입출력을 진행한다.

Git : https://github.com/im2sh/Socket_Programming/tree/main/lab01
출처 : 윤성우의 열혈 TCP/IP 소켓 프로그래밍