- 리눅스 커널 관점 : 통신을 위한 끝점
: 두 호스트를 연결해주는 통로 (클라이언트 소켓 - 서버 소켓)
- Unix 프로그램의 관점 : 해당 식별자를 가지는 열린 파일
네트워크 응용을 만들기 위한 Unix I/O 함수들과 함께 사용되는 함수들의 집합
/* IP socket address structure */
struct sockaddr_in {
uint 16_t sin_family; // AF_INET ( =IPv4 )
uint 16_t sin_port; // 포트 번호( 16bit )
struct in_addr sin_addr; // IP 주소 ( 32bit ) = IPv4
unsigned char sin_zero[8];
}
/* Generic socket address stucture (for connet, bind, and accept) */
struct sockaddr {
uint 16_t sin_family; // 프로토콜
char ss_data[14]; // IP 주소
}
socket 식별자 생성
- 만약 소켓을 끝점을 만들고 싶다면, 하드코드된 인자로 socket 함수 호출
clinentfd = Socket(AF_INET, SOCKET_STREAM, 0)
#include <sys/types.h>
#include <sys/socket.h>
int socket (int domain, int type, int protocol);
Returns: nonnegative descriptor if OK, -1 on error
domain
: address family(주소 체계) 지정
type
: 소켓의 유형
ex) SOCKET_STREAM
(연결지향소켓, TCP) , SOCK_DGRAM
(비연결 지향 소켓, UDP)
protocol
: 프로토콜 지정
0
을 사용해 address family와 소켓 유형에 맞는 기본 프로토콜을 선택0
혹은 IPPROTO_TCP
서버의 주소 정보를 가지고 있는
addr
를 사용해 서버의IP
와port
를
이전에 생성한 소켓의 파일 디스크립터(sockfd
)와bind
한다.
#include <sys/socket.h>
int bind (int sockfd, const struct sockaddr *addr, socklen_t addrlen);
Returns: nonnegative descriptor if OK, -1 on error
🤔❓addrlen
로 함수에게 구조체의 크기를 알려주는 이유
1) 주소 패밀리(AF_INET, AF_INET6 등)에 따라 구조체의 크기가 달라질 수 있다.
2) 버퍼 오버플오우와 같은 보안 문제 방지
- addr 구조체보다 큰 크기를 addrlen에 설정해 함수가 addr 구조체의 범위를 벗어나는 것을 방지
등등...
서버 소켓(
sockfd
)을 특정 포트에서 연결 요청을 대기하기 위한 상태로 설정
- backlog : 대기 큐의 최대 길이를 지정클라이언트의 연결 요청을 대기하고
대기 큐가 가득 차면 추가 연결 요청은 거부
#include <sys/socket.h>
int listen (int sockfd, int backlog);
Returns: nonnegative descriptor if OK, -1 on error
이전에 생성한 클라이언트 소켓의 파일 디스크립터(
clientfd
)와
서버의 주소 정보를 가지고 있는addr
를 사용해 서버에connect
을 시도
#include <sys/socket.h>
// 클라이언트 소켓
int connect (int clientfd, const struct sockaddr *addr, socklen_t addrlen);
Returns: 0 if OK, -1 on error
- 클라이언트로부터 연결 요청이 듣기 식별자 listenfd 에 도달하기를 기다리기
- 그 후
addr
내의 클라이언트의 소켓 주소를 채우기- Unix I/O 함수들을 사용해 클라이언트와 통신하기 위해 사용될 수 있는 연결식별자(
confd
) 리턴
= 새로운 file descriptor 할당
#include <sys/socket.h>
int accept (int listenfd, const struct sockaddr *addr, socklen_t addrlen);
Returns: nonnegative descriptor if OK, -1 on error