반응형
네트워크 프로그래밍 기본 지식
네트워크 프로그래밍 = 소켓 프로그래밍
서버 소켓 (Server) = 리스닝 소켓 (Listening)
함수 | 기능 | 예시 (통화) |
---|---|---|
socket() | 소켓 생성 | 전화기 장만 |
bind() | 소켓의 주소정보(IP, PORT) 할당 | 전화번호 부여 |
listen() | 연결요청이 가능한 상태로 변경 | 전화기의 케이블 연결. 전화를 받을 수 있는 상태 |
accept() | 연결요청에 대한 수락 | 수화기를 드는것 |
클라이언트 소켓 (Client)
함수 | 기능 | 예시 (통화) |
---|---|---|
socket() | 소켓 생성 | 전화기 장만 |
connect() | 연결요청을 진행 | 전화를 건다 |
프로토콜 (Protocol)
- 컴퓨터 상호간의 대화에 필요한 통신 규약
#include <sys/socket.h>
int socket(int domain, int type, int protocol);
// 성공 시 파일 디스크립터, 실패 시 -1 반환
- 프로토콜 체계 (Protocol Family) : 생성되는 소켓이 사용할 프로토콜의 부류정보 전달
- 프로토콜 체계 범위 내에서 프로토콜 (3번째 인자) 선택
이름 프로토콜 체계 (Protocol Family) PF_INET IPv4 인터넷 프로토콜 체계 PF_INET6 IPv6 인터넷 프로토콜 체계 PF_LOCAL 로컬 통신을 위한 UNIX 프로토콜 체계 PF_PACKET Low Level 소켓을 위한 프로토콜 체계 PF_IPX IPX 노벨 프로토콜 체계
- 소켓 타입 (Type)
- 소켓의 데이터 전송 방식
연결지향형 소켓 (SOCK_STREAM) : 신뢰성 있는 순차적인 바이트 기반의 연결지향 데이터 전송 방식의 소켓 비 연결지향형 소켓 (SOCK_DGRAM) : 신뢰성과 순차적 데이터 전송을 보장하지 않는, 고속의 데이터 전송을 목적으로 하는 소켓 특징 - 중간에 데이터가 소멸되지 않고 목적지로 전송된다 - 전송 순서대로 데이터가 수신된다 - 전송되는는 데이터의 경계 (Boundary)가 존재하지 않는다 - 전송된 순서에 상관없이 가장 빠른 전송을 지향한다 - 전송된 데이터는 손실의 우려가 있고, 파손의 우려가 있다. - 전송되는 데이터의 경계 (Boundary)가 존재한다 - 한번에 전송할 수 있는 데이터의 크기가 제한된다. 세부 - 내부적으로 버퍼 (buffer, 바이트 배열)을 지니고 있음 → 배열의 용량을 초과하지 않는 한 데이터가 채워진 후에 한번의 read 함수호출을 통해 데이터 전부를 읽어들일 수 있음/한번의 write 함수호출을 통해 전송된 데이터 전부를 여러 번의 read 함수 호출을 통해 읽어들일 수 있음 → read 함수의 호출횟수와 write 함수의 호출횟수는 큰 의미를 갖지 못함 (데이터의 경계가 존재하지 않음) → 자신과 연결된 상태 소켓의 상태를 파악해가면서 데이터 전송 - 연결지향형 소켓에 비햐 데이터의 전송속도가 빠름 연결 소켓 대 소켓의 연결은 반드시 1 대 1이어야 한다. 연결이라는 개념이 존재하지 않음
- 프로토콜
- 하나의 프로토콜 체계 안에 데이터의 전송방식이 동일한 프로토콜이 둘 이상 존재하는 경우 대비 → 프로토콜 정보를 구체화하기 위함
- PF_INET + 연결지향형 ⇒ IPPROTO_TCP - TCP 소켓 하나
- PF_INET + 비 연결지향형 ⇒ IPPROTO_UDP - UDP 소켓 하나
인터넷 주소 (Internet Address)
- IP (Internet Protocol) : 인터넷상에서 데이터를 송수신할 목적으로 컴퓨터에게 부여하는 값
- PORT : 프로그램상에서 생성되는 소켓을 구분하기 위해 소켓에 부여되는 번호
- 하나의 운영체제 내에서 소켓을 구분하는 목적으로 사용
- 하나의 운영체제 내에서 동일한 PORT 번호를 둘 이상의 소켓에 할당할 수 없다.
- 범위 (2B) : 0~65,535
- 0 ~ 1023 : well-known Port → 특정 프로그램에 할당하기로 예약
- PORT 번호는 중복이 불가능하지만, TCP 소켓과 UDP 소켓은 PORT 번호를 공유하지 않기 때문에 중복되어도 상관없음
- IP 주소체계
- 네트워크 주소 (네트워크 ID) : 네트워크의 구분을 위한 IP주소의 일부
- 호스트 주소 (호스트 ID)
구분 1B 1B 1B 1B 비고 클래스 A : 0~127 (0) 네트워크 ID 호스트 ID 호스트 ID 호스트 ID 클래스 B : 128~191 (10) 네트워크 ID 네트워크 ID 호스트 ID 호스트 ID 클래스 C : 192~223 (110) 네트워크 ID 네트워크 ID 네트워크 ID 호스트 ID 클래스 D : 224~239 (1110) 네트워크 ID 네트워크 ID 네트워크 ID 네트워크 ID 멀티캐스트 클래스 E : 240~255 (1111) - - - - 예약되어있는 주소체계
- NIC (네트워크 인터페이스 카드) : 데이터 송수신 장치
- IP는 데이터를 NIC을 통해 컴퓨터 내부로 전송
- 컴퓨터 내부에로 전송된 데이터를 소켓에 적절히 분배하는 작업은 운영체제가 담당
주소표현
IPv4 주소표현
struct sockaddr_in
{
sa_faily_t sin_family; // 주소체계 (Address Family)
uint16_t sin_port; // 16비트 TCP/UDP PORT 번호
struct in_addr sin_addr; // 32비트 IP 주소
char sin_zero[8]; // 사용되지 않음
};
struct in_addr
{
in_addr_t s_addr; // 32비트 IPv4 인터넷 주소
};
struct sockaddr
{
sa_family_t sin_family; // 주소체계 (Address Family)
char sa_data[14]; // 주소정보 : Port (2B) + IP (4B) + Zero (8B)
}
- 맴버 sin_family
주소체계 (Address Family) 의미 AF_INET IPv4 인터넷 프로토콜에 적용하는 주소체계 AF_INET6 IPv6 인터넷 프로토콜에 적용하는 주소체계 AF_LOCAL 로컬 통신을 위한 유닉스 프로토콜의 주소체계
- 맴버 sin_port : 16비트 포트 번호 저장 (네트워크 바이트 순서)
- 맴버 sin_addr : 32비트 IP주소정보 저장 (네트워크 바이트 순서)
- 맴버 sin_zero : 의미 X. 반드시 0으로 채워야 함
- sockaddr_in 구조체 맴버를 앞서 설명한대로 채우면, 형변환을 통해서 sockaddr 구조체 변수에 넣게됨
- 구조체 sockaddr에서는 주소체계 정보를 구조체 맴버 sin_family에 저장할 것을 요구
네트워크 바이스 순서
- CPU에 따라서 4바이트 정수 1을 메모리 공간에 저장하는 방식이 달라질 수 있음 ← 호스트 바이트 순서 (Host Byte Order)
- 네트워크를 통해서 데이터를 전송할 때에는 통일된 기준으로 데이터를 전송하기로 약속 → 네트워크 바이트 순서 (Network Byte Order) = 빅 엔디안
- 네트워크상으로 데이터를 전송할 때에는 데이터의 배열을 빅 엔디안 기준으로 변경해서 송수신하기로 약속
바이트 순서(Ordar)
- 빅 엔디안 (Big Endian) : 상위 바이트의 값을 작은 번지수에 저장하는 방식
- 최상위 바이트가 먼저 저장
0x20번지 0x21번지 0x22번지 0x23번지 0x12 0x34 0x56 0x78
- 리틀 엔디안 (Little Endian) : 상위 바이트 값을 큰 번지수에 저장하는 방식
- 최하위 바이트가 먼저 저장
0x20번지 0x21번지 0x22번지 0x23번지 0x78 0x56 0x34 0x12
바이트 순서의 변환 (Endian Conversions)
unsigned short htons (unsigned short);
unsigned short ntohs (unsigned short);
unsigned long htonl (unsigned long);
unsigned long ntohl (unsigned long);
인터넷 주소 변환
#include <arpa/inet.h>
// 문자열 (127.0.0.1) -> 32비트 정수
in_addr_t inet_addr(const char* string); // 32비트 정수값 or INADDR_NONE
int inet_aton(const char* string, struct in_addr* addr);
char* inet_ntoa(int addr);
INADDR_ANY
- 소켓이 동작하는 컴퓨터의 IP주소가 자동으로 할당됨
- 컴퓨터 내에 두 개 이상의 IP를 할당 받아서 사용하는 경우 (Multi-homed 컴퓨터 ex. 라우터) 할당 받은 IP중 어떤 주소를 통해서 데이터가 들어오더라도 PORT번호만 일치하면 수신할 수 있게 됨
→ 서버 프로그램 구현에 많이 선호되는 방법
- IP주소는 컴퓨터가 장착되어 있는 NIC (랜카드)의 개수만큼 부여가 가능 → 어느 IP주소로 들어오는 데이터를 수신할 지 결정가능
[참고자료]
- 열혈 TCP/IP 소켓 프로그래밍 - 윤성우
반응형
'Study > 네트워크 프로그래밍' 카테고리의 다른 글
TCP (0) | 2022.02.23 |
---|---|
[책 추천] 네트워크 기초 지식을 그림으로 알려주는 <모두의 네트워크> (0) | 2020.05.11 |
댓글