소켓 프로그래밍 개념

ParkJeongBin·2023년 12월 3일

network

목록 보기
2/6

소켓은 컴퓨터 네트워크에서 프로세스 간 통신을 가능하게 하는 인터페이스

소켓의 종류

소켓은 크게 두 가지로 구분하는데, 같은 호스트에서 프로세스 사이에 통신할 때 사용하는 유닉스 도메인 소켓과 인터넷을 통해 다른 호스트와 통신할 때 사용하는 인터넷 소켓이 있다.

  • AF_UNIX : 유닉스 도메인 소켓
  • AF_INET : 인터넷 소켓

소켓의 통신 방식

TCP/IP 프로토콜의 전송 계층에서 사용하는 프로토콜에는 TCP와 UDP가 있다.
소켓을 이용할 때도 하부 프로토콜로 TCP를 사용할 것인지 UDP를 사용할 것인지 지정해야 한다.

  • SOCK_STREAM : TCP 사용
  • SOCK_DGRAM : UDP 사용

따라서 소켓을 이용할 때는 소켓의 종류와 통신 방식에 따라 네 가지 통신 유형이 나타난다.

  • AF_UNIX - SOCK_STREAM (유닉스 도메인 소켓 - TCP 사용)
  • AF_UNIX - SOCK_DGRAM (유닉스 도메인 소켓 - UDP 사용)
  • AF_INET - SOCK STREAM (인터넷 소켓 - TCP 사용)
  • AF_INET - SOCK_DGRAM (인터넷 소켓 - UDP 사용)


소켓 주소 구조체

소켓을 이용한 프로그래밍에서는 소켓의 종류와 IP 주소, 포트 번호 등을 지정하기 위한 구조체를 사용한다.

유닉스 도메인 소켓의 주소 구조체

sockaddr_un 구조체는 sys/un.h 파일에 정의되어 있다.
sockaddr_un 구조체에는 주소 페밀리명과 경로명이 항목으로 들어있다.

struct sockaddr_un {
	__kernel_sa_family_t sun_family;				// AF_UNIX
    char				 sun_path[UNIX_PATH_MAX] 	// 경로명

인터넷 소켓의 주소 구조체

주소 페밀리명과 포트 번호, IP 주소가 구조체 항목으로 들어 있다.

  • 주소 패밀리명은 네트워크 프로그래밍에서 사용되는 주소 체계를 식별하는 값 ( AF_INET, AF_INET6, AF_UNIX ... )
struct sockaddr_in {
	__kernel_sa_family_t sin_family;	// 주소 패밀리명
    __be16				 sin_port;		// 포트 번호
    struct in_addr		 sin_addr;		// 인터넷 주소
};

struct in_addr {
	__be32 				 s_addr;		// 32비트 주소


바이트 순서 함수

컴퓨터에서 정수를 저장하는 방식은 두 가지이다.
각각 바이트를 순서대로 저장하는 빅 엔디언과 거꾸로 저장하는 리틀 엔디언이다.

빅 엔디언 방식은 메모리의 낮은 주소에 정수의 첫 바이트를 위치시킨다.

  • ex) 0x1234 -> 0x12, 0x34의 순서로 저장

리틀 엔디언 방식은 메모리의 높은 주소에 정수의 첫 바이트를 위치시킨다.

  • ex) 0x1234 -> 0x34, 0x12의 순서로 저장

TCP/IP에서는 데이터를 전송할 때 빅 엔디언을 사용한다.
이를 네트워크 바이트 순서 (NBO, Network Byte Order)라고 한다.
반면 호스트에서 사용하는 바이트 순서는
호스트 바이트 순서 (HBO, Host Byte Order)라고 한다.

시스템에서 통신을 통해 데이터를 내보낼 때는 HBO에서 NBO로 데이터순서를 바꿔서 전송하고, 데이터를 받으면 NBO에서 HBO로 변환 후 처리해야 한다.

#include <arpa/inet.h>

uint32_t htonl(uint32_t hostlong);		// 호스트 바이트 순서로 저장된 값
uint16_t hrons(uint16_t hostshort);		// 호스트 바이트 순서로 저장된 값
uint32_t ntohl(uint32_t netlong);		// 네트워크 바이트 순서로 저장된 값
uint16_t ntohs(uint16_t netshort);		// 네트워크 바이트 순서로 저장된 값
  • htonl() 함수는 32비트 HBO를 32비트 NBO로 변환
  • htons() 함수는 16비트 HBO를 16비트 NBO로 변환
  • ntohl() 함수는 32비트 NBO를 32비트 HBO로 변환
  • ntohs() 함수는 16비트 NBO를 16비트 HBO로 변환


IP 주소 변환 함수

IP 주소는 192.168.100.1 과 같이 점 ( . ) 으로 구분되는 형태이다.
이진값과 문자영로 표시되는 IP 주소를 서로 변환할 수 있는 함수를 제공한다.

문자열 IP 주소를 숫자로 변환 : inet_addr(3)

#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

in_addr_t inet_addr(const char *cp);

*cp : 문자열 형태의 IP 주소

구조체 IP 주소를 문자열로 변환 : inet_ntoa(3)

#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

char *inet_ntoa(const struct in_addr in);

in : in_addr 구조체 형태의 ip 주소
inet_ntoa() 함수는 IP 주소를 in_addr 구조체 형태로 받아 점으로 구분된 문자열로 리턴



소켓 인터페이스 함수의 종류

소켓도 특수 파일의 하나
소켓을 이용해 네트워크 프로그래밍을 할때는 소켓을 생성해 IP 주소와 연결한 후 서버와 클라이언트가 연결되면 소켓을 통해 읽고 쓰면 됨

소켓 인터페이스 함수의 종류

소켓을 이용해 네트워크 프로그래밍을 할 때 필요한 함수

  • socket() : 소켓 파일 기술자 생성
  • bind() : 소켓 파일의 기술자를 지정된 IP 주소 / 포트 번호와 결합
  • listen() : 클라이언트의 연결 요청 대기
  • connect() : 클라이언트가 서버에 접속 요청
  • accept() : 클라이언트의 연결 요청 수락
  • send() : 데이터 송신 (SOCK_STREAM)
  • recv() : 데이터 수신 (SOCK_STREAM)
  • sendto() : 데이터 송신 (SOCK_DGRAM)
  • recvfrom() : 데이터 수신 (SOCK_DGRAM)
  • close() : 소켓 파일 기술자 종료

이 중에서 bind, listen, accept 함수는 서버 측에서만 사용하고, connect 함수는 클라이언트 측에서만 사용한다.
나머지 함수는 클라이언트에서 모두 사용한다.


다음에는 직접 소켓 프로그래밍을 해보며 이해를 높여보겠습니다.

profile
My dream is White-Hat

0개의 댓글