A가 신호를 보내면 B가 알아들으면 됨.
단방향, 양방향, ...
신호에 대한 의미를 약속한 것이 프로토콜이다.
중요한 것은 통신하기 위한 물리적인 경로이 필요하다(랜선, 와이파이,..)
A - B
A가 B에게 통신신호(패킷)을 보냈는데 B에게 잘 받았는지 확인받는 절차까지 포함한 프로토콜이다. 따라서 안정성, 신뢰성이 높다. BUT 속도가 느릴 수 있다. 요즘은 대부분 TCP를 사용한다.
TCP 통신이란 네트워크 통신에서 데이터를 신뢰성 있게 전달하기 위해 사용되는 연결 지향형 통신 프로토콜입니다.
인터넷 프로토콜(IP)과 함께 TCP/IP 스택의 핵심 구성 요소로, 웹 브라우징, 파일 전송, 이메일 등 다양한 네트워크 애플리케이션에서 사용됩니다.
A - B
A가 B에게 패킷을 던지고 확인절차는 없다. 안정성이 낮지만, 속도는 빠르다. 게임, 영화 실시간 스트리밍할 때 주로 사용한다.
Socket : 네트워크 통신의 끝점(Endpoint)으로, 두 장치(프로세스)가 데이터를 주고받기 위해 사용하는 인터페이스입니다. 소켓은 운영 체제와 네트워크 간의 중간다리 역할을 하며, 프로그램이 네트워크를 통해 데이터를 송수신할 수 있도록 도와줍니다.
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <pthread.h>
#include <> // 표준 라이브러리
#include "" // 사용자 정의 라이브러리
#define CLNT_MAX 10
int g_clnt_socks[CLNT_MAX];
int g_clnt_count=0;
int main(int argc, char ** argv){
int serv_sock;
int clnt_sock;
struct sockaddr_in clnt_addr;
int clnt_addr_size;
struct sockaddr_in serv_addr;
serv_sock = socket(PF_INET,SOCK_STREAM,0);
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
serv_addr.sin_port=htons(7989);
if(bind(serv_sock,(struct sockaddr *)&serv_addr,sizeof(serv_addr))==-1){
printf("bind error\n");
}
위 코드를 설명하면,
serv_sock 이란 IPv4와 TCP를 사용하는 빈 소켓을 만들어주고,
위 정보를 bind 해준다. = 생성한 소켓과 설정한 주소를 연결한다.
bind() 은 소켓을 특정 IP 주소와 포트 번호에 바인딩하여 서버가 클라이언트 요청을 수신할 준비를 한다.
bind()의 반환값:
성공 시 0 반환.
실패 시 -1 반환하며, 에러 원인은 errno로 확인 가능하다.
운영체제에서 데이터를 저장하는 방식이 다양하다. 그렇기 때문에 네트워크통신을 하기위해서는 네트워크 오더를 따라야 한다.

#define AF_INET 2 // IPv4
#define AF_INET6 23 // IPv6
*IPv4
ex) 127.36.95.2
주로 IPv4 를 많이 씀
PF_INET 으로도 사용가능하다. 프로토콜을 설정할 땐 PF_INET을 사용하고, 주소를 설정할 땐 AF_INET을 사용한다.
*IPv6
경우의 수를 따져보니까 ip가 모자라서 IPv6를 만듦
근데 왜 잘 안쓰냐? 공유기의 등장으로 인해 v6가 필요없게 된다.
A 공유기가 대표 IP를 받고 많은 기기를 연결할 수 있게 되어서 v4로도 문제가 없게 된다.
+유동 IP개념
#define SOCK_STREAM 1 //스트림, TCP 프로토콜의 전송방식
#define SOCK_DGRAM 2 //데이터그램, UDP 프로토콜의 전송방식
#define SOCK_RAW 3 //RAW 소켓, 가공하지 않은 소켓
#define IPPROTO_TCP 6 //TCP 프로토콜
#define IPPROTO_UDP 17 //UDP 프로토콜
#define IPPROTO_RAW 255 //RAW
protocol 인자는 사용할 프로토콜을 명시적으로 지정할 수 있도록 되어 있지만, 대부분의 경우 명시할 필요가 없다.
0을 전달하면, domain과 type에 따라 기본값이 자동으로 선택됩니다.
예를 들어:
if(listen(serv_sock,5)== -1){
printf("listen error\n");
}

listen() 함수는 소켓을 수신 대기 상태로 전환하며, 서버가 클라이언트의 연결 요청을 받을 준비를 한다.
backlog는 연결 요청 대기열의 최대 길이를 지정하는 인자이다.
즉, 동시에 처리되지 않고 대기 상태에 들어갈 수 있는 클라이언트 연결 요청의 수를 정의하고, 요청 대기열이 가득 차면 추가 연결 요청은 처리되지 않고 거부된다.
char buff[200];
int recv_len=0;
while(1){
clnt_addr_size = sizeof(clnt_addr);
clnt_sock = accept(serv_sock,(struct sockaddr *)&clnt_addr,&clnt_addr_size);
g_clnt_socks[g_clnt_count++] = clnt_sock;

서버 소켓(serv_sock)에서 클라이언트 연결 요청을 수락한다.
반환값 clnt_sock는 새로 생성된 클라이언트와의 통신 소켓입니다.
clnt_addr에는 연결된 클라이언트의 IP 주소와 포트 번호 정보가 저장됩니다.
while(1){
recv_len =read(clnt_sock, buff,200);
printf("recv : ");
for(int i=0;i<recv_len;i++){
printf("%02X",(unsigned char)buff[i]); }
printf("\n");
}
}
}
클라이언트로부터 데이터를 읽는 무한 루프이다.
read() 함수:
clnt_sock에서 데이터를 읽어 buff에 저장한다.
최대 200바이트 읽어오고, 읽은 데이터 수를 반환하여 recv_len 에 저장한다. 이는 출력을 하기 위함이다.
읽은 데이터의 바이트 수를 반환하며, 이를 recv_len에 저장합니다.
read() 반환값:
클라이언트로부터 읽어온 데이터를 16진수(HEX)로 출력합니다.
이번 강에서는 대충구현해서 실행한것만 보여주고 다음 강의에서 제대로 설명할 예정
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <pthread.h>
#define BUFFSIZE 200
#define NAMESIZE 20
char message[BUFFSIZE];
int main(int argc, int **argv){
int sock;
struct sockaddr_in serv_addr;
pthread_t snd_thread, rcv_thread;
void* thread_result;
sock=socket(PF_INET, SOCK_STREAM,0);
if(sock==-1)
printf("socket() error");
memset(&serv_addr,0,sizeof(serv_addr));
serv_addr.sin_family=AF_INET;
serv_addr.sin_addr.s_addr=inet_addr("127.0.0.1");
serv_addr.sin_port=htons(7989);
if(connect(sock,(struct sockaddr *)&serv_addr,sizeof(serv_addr))==1)
printf("connet() error");
unsigned char msg[100] = {0x01,2,3,4,5,6,1,2,3,4,3,0x03};
while(1){
printf("send: ");
write(sock,msg,12);
sleep(1);
}
close(sock);
return 0;
}
$ gcc -o server server.c
$ ./server
서버실행중
gcc -o clnt clnt.c
$ ./clnt

클라이언트에서 데이터를 읽어와 무한루프로 실행한다.