인터넷과 소켓프로그래밍

소켓 개요 및 TCP 에코 서버

kang057 2024. 7. 26. 21:37

● IPC(interProcess Communications) Mechanism

=> 서로 다른 프로세스 간에 데이터를 교환하고 상호작용하는 방법을 말한다.

 

○ 파이프(Pipe)

=> 파이프는 두 프로세스 간의 단방향 또는 양방향 통신을 가능하게 하는 통로이다. 파이프에는 두 가지 종류가 있다.

 

1. 익명 파이프 (Anonymous Pipe)

- 개념: 익명 파이프는 부모 프로세스와 자식 프로세스 간에만 사용될 수 있는 단방향 통신 채널이다.

- 특징: 

   - 한 방향으로만 데이터가 흐릅니다.

   - 일반적으로 부모-자식 프로세스 간의 통신에 사용된다.

   - 익명 파이프는 파일  시스템에 나타나지 않으며, 메모리 상에서만 존재한다.

 

2. 명명된 파이프 (Named Pipe of FiFO)

- 개념: 명명된 파이프는 파일 시스템 상에 이름을 가지며, 서로 다른 프로세스 간의 통신에 사용될 수 있다.

- 특징:

   - 양방향 통신이 가능하다.

   - 파일 시스템에 나타나기 때문에 프로세스가 동시에 존재하지 않아도 데이터를 주고받을 수 있습니다.

   - 생성 시 'mkfifo' 명령어를 사용한다.

 

○ 소켓 (Socket)

=> 소켓은 네트워크 상에서 프로세스 간의 통신을 가능하게 하는 더 복잡한 통신 메커니즘이다. 로컬 시스템 내에서나 원격 시스템 간에 데이터를 주고받을 수 있다.

 

1. 스트림 소켓 (Stream Socket, TCP 소캣)

- 연결 지향적이며, 신뢰성 있는 데이터 전송을 보장한다.

- 데이터는 순서대로 전달되고, 손실되거나 중복되지 않는다.

- 사용 예시: 웹 브라우징, 이메일 전송

 

2. 데이터 그램 소켓 (Datagram Socket, UDP 소켓)

- 비연결 지향적이며, 신뢰성 있는 전송을 보장하지 않는다.

- 데이터는 순서에 상관없이 전달될 수 있으며, 손실될 수 있다.

- 사용 예시: 스트리밍, 온라인 게임

 

● SOCKET 인터페이스 - Application Process와 TCP간의 통신 수단

=> 소켓 인터페이스는 응용 프로그램이 네트워크를 통해 통신할 수 있게 하는 프로그래밍 인터페이스이다. 소켓을 통해 응용 프로그램은 TCP/IP 네트워크 상에서 데이터를 주고받을 수 있다. 소켓 인터페이스를 사용하면 응용 프로그램과 TCP 간의 통신이 원할하게 이루어지며, 주로 TCP 소켓을 사용하여 신뢰성 있는 데이터 전송을 구현한다.

 

○ 소켓 인터페이스의 기본 개념

=> 소켓은 네트워크 상에서 데이터를 송수신할 수 있는 끝점을 의미한다. 

 

1. 소켓 생성: 통신에 사용할 소켓을 생성

2. 주소 할당: 소캣에 IP 주소와 포트 번호를 할당

3. 연결: 클라이언트 소켓이 서버 소켓에 연결을 요청, 서버 소켓이 연결을 수락

4. 데이터 전송: 연결된 소켓 간에 데이터를 송수신이다.

5. 연결 종료: 통신이 완료되면 소켓을 닫는다.

 

● 소켓 함수 설명

socket() : 소켓 생성

 

○ TCP 기능

1. 접속 설정 요청

- connect() : 접속설정 요청

- bind() : 소켓에 이름 주기

- listen() : 접속설정 요청 대기 수

- accept() : 접속설정이 완료되면 알림 요청

 

2. 정확한 데이터 전송

- send() : 데이터 전송, 네트워크 소켓을 통한 데이터 전송에 특화

- recv() : 데이터 수신, 네트워크 소켓을 통해 데이터를 수신하는 데 특화

- write() : 데이터 전송, 파일 디스크립터를 통해 범용적으로 데이터를 쓰는 데 사용

- read() : 데이터 수신, 파일 디스크립터를 통해 범용적으로 데이터를 읽어오는 데 사용

 

3. 접속해제 요청

- close() : 접속해제 요청

 

- select() : 어떤 소켓에 이벤트 도착했는지 기다림

 

● 헤더 파일

- 프로그램의 헤더 부분에 있음

- 확장자는 header를 뜻하는 .h로 끝남

- 운영체제를 설치할 때 자동으로 설치됨

  ○ 위치 : /usr/include

  ○ 다른 패키지를 설치할 때 포함될 수도 있음

  ○ 프로그램 작성자가 만들어도 됨

- C 프로그램을 위해 유용한 변수, 함수, 구조체, 상수값 등을 제공하기 위한 목적

 

● stdio.h

=> Standard Input/Output 관련 헤더파일

     ○ 표준입력(standard input) : 키보드 입력

        - scanf()

 

     ○ 표준출력(standard output) : 모니터 출력

         - printf()

 

● string.h.

=> string과 memory와 관련된 함수를 모아둔것

 

- memcpy() : 한 메모리 블록에서 다른 메모리 블록으로 데이터를 복사하는 데 사용. 'memcpy()'는 데이터가 겹치지 않는 경우에 사

- memset() : 메모리의 특정 영역을 지정한 값으로 설정하는데 사용

- bcopy() : 한 메모리 영역에서 다른 메모리 영역을 데이터를 복사하는 데 사용
- bzero() : 지정된 메모리 영역을 0으로 설정하는 데 사용된다.

etc..

 

● stdlib.h

=> 메모리 할당, 프로세스 제어, 정렬, 기타 유틸리티 함수들이 포함되어 있습니다.

 

- WAIT_INT() => wait() 시 상태 값

- #define EXIT_FAILURE 1 : C 프로그램에서 종료 상태를 나타내기 위해 사용하는 매크로이다. 프로그램이 비정상적으로 종료되었음을 나타내는 데 사용한다.

- #define EXIT_SUCCESS 0 : C 프로그램에서 종료 상태를 나타내기 위해 사용하는 매크로이다. 프로그램이 정상적으로 종료되었음을 나타내는 데 사용한다.

- #define RAND_MAX 2147483647

- atoi() : 일반적으로 문자열을 정수형 데이터로 변환하는 간단한 방법을 제공

- malloc() : 동적 메모리를 할당하는 데 사용되는 표준 라이브러리 함

etc..

 

● <sys/types.h> == "/usr/include/sys/types.h"

=> C프로그래밍에서 데이터 유형 및 상수의 정의를 제공하는 표준 헤더파일이다. 이 파일은 다양한 시스템에서 데이터 유형의 정의와 시스템 관련 상수를 제공하며, 시스템 프로그래밍에서 중요한 역할을 한다.

 

● <sys/socket.h>, <netinet/in.h> : 나중에

 

● struct sockaddr_in

- #include <netinet/in.h>에 정의됨

#include <netinet/in.h>

struct sockaddr_in {
    unsigned short int sin_family;   // 주소 체계 (AF_INET)
    uint16_t sin_port;               // 포트 번호
    struct in_addr sin_addr;         // IP 주소
    unsigned char sin_zero[8];       // 패딩 (구조체 크기를 맞추기 위해 사용)
};

 

● 소켓 생성 - socket()

- 스트림 소켓 생

- socket(소켓 패밀리, 소켓 종류, 하위계층프로토콜)

- sockfd : 생성된 소켓 디스크립터(식별자)

if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
    printf("server: can't open stream socket");
    exit(0);
}
printf("New Socket Created : %d\n", sockfd);

 

● socket(AF_INET, SOCK_STREAM, 0)

□ AF_INET

  ○ 상대방 AP와 통신하기 위한 조건

     - 동일 주소체계, 동일 프로토콜, 네트워크 식별, 호스트 식별, 호스트내 AP 식별

     - 동일한 인터넷 주소체계와 인터넷 프로토콜을 이용하기 위한 소켓 생성

       - Address Family(AF_INET) = Protocol Family (PF_INET)

       - IP 주소 강의에서 설명하였음

 

□ SOCK_STREAM

  ○ 소켓의 종류

    - 연결성 소켓 (Stream socket)

    - 비연결성 소켓 (Datagram socket)

    - 로 소켓 (RAW socket)

    - 패킷 소켓

 

□ 하위계층 프로토콜

  ○ 0 : 디폴트 프로토콜

 

● 소켓의 종류

- <bits/socket.h>에 정의되어 있다.

 

○ Stream Socket (스트림 소켓)

   - 연결성 소켓

   - 하위계층으로 TCP와 같은 연결후 신뢰성 있는 데이터 전송 프로토콜 사용

   - 데이터는 물 흐르듯이 연속적으로 도착

   - SOCK_STREAM

 

○ Datagram Socket (데이터그램 소켓)

    - 비연결성 소켓

    - 하위계층으로 UDP와 같이 연결없이 즉시 데이터 전송 프로토콜 사용

    - 데이터는 일반편지와 같이 독립적임

    - SOCK_DGRAM

 

○ Raw Socket

   - 응용 프로세스는 TCP, UDP와 같은 계층 4를 거치지 않고 계층 3 프로토콜을 이용하여 통신

   - 하위계층으로 IP 사용

   - SOCK_RAW

 

○ Packet Socket

   - 응용 프로세스는 계층 2에 해당하는 이더넷과 같이 네트워크 카드를 직접 이용할 때 사용

   - SOCK_PACKET

 

● 소켓 정의

□ TCP나 UDP와 같은 트랜스포트 계층을 이용하는 API

   - IPC mechanism

   - 1982년 BSD 유닉스 4.1에서 소개

   - Windows는 Winsock으로 제공

   - Java는 Netswork 관련 클래스 제공

   - Python에서는 socket 등 다양한 클래스 제공

 

● 소켓 번호 (1)

○ 유닉스는 모든 파일, 장치등을 파일로 취급

   - 파일 드스크립터, 키보드, 모니터, 하드웨어 장치, 소켓 등

○ 소켓 디스크립터

   - 소켓을 개설하여 얻는 파일 디스크립터

   - 데이터를 송수신할 때 사용

 

● 소켓번호 (2)

○ 응용 프로그램과 소켓 그리고 TCP/IP의 관계

 

- 연결형 서비스 : 데이터 전송 전에 송신자와 수신자 간의 연결을 설정하고, 데이터가 전송된 후 연결을 해제하는 방식. 신뢰성 있는 데이터 전송을 보장한다.

 

- 비연결형 서비스 : 송신자와 수신자 간의 연결을 설정하지 않고 데이터를 전송하는 방식. 데이터 전송의 신뢰성을 보장하지 않으며, 데이터가 중간에 손실될 수 있다.

 

● 소켓에 유일한 이름 짓고 출생신고서에 작성

/*
 * 생성된 소켓에 인터넷에서 유일한 이름 정하기
 * 이름은 Family, IP주소, Port 번호
 * Family : 같은 표준간에 통신
 * IP주소 : 인터넷에 연결된 호스트의 유일한 식별자
 * Port 번호 : 호스트에서 유일한 서버 프로그램 식별자
*/

bzero((char *) &serv_addr, sizeof(serv_addr));

/* serv_addr에 Family, IP주소, Port 번호 저장 */
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = htonl(INADDR_ANT);
serv_addr.sin_port = htonl(atoi(argv[1]));

 

struct sockaddr_in = 출생신고서

 

● bind() - 출생신고

clilen = sizeof(cli_addr);
servlen = sizeof(serv_addr);

/*
 * 소켓에 유일한 이름 지정(등록) : 운영체제가 알고 있음
 * 이름 : Family, IP주소, Port 번호
 */
 
 if (bind(sockfd, (struct sockaddr *) &serv_addr, servlen) < 0( {
	printf("server: can't bind local address");
    	ecit(2);
}

 

 

● listen() - 동시 접속설정 요청 대기 수

/* 소켓에 접속설정을 요청하는 클라이언트 대기 가능 수 설정 */
listen(sockfd, 5):