소켓 인터페이스는네트워크어플리케이션을 만들기 위한
Unix I/O 함수들과 함께 사용되는함수들의 집합

소켓은 인터넷 주소와 16비트 정수 포트로 구성된
소켓 주소를 address : port로 나타내고 연결의 종단점이다.
클라이언트의 소켓 주소 내의 포트는 클라이언트가 연결 요청할 때 커널이 자동으로 할당한다
리눅스 커널의 관점에서는 소켓은 통신을 위한 끝점
Unix 프로그램 관점에서는 소켓은 해당 식별자를 가지는 열린 파일

인터넷 소켓 주소는 위의 그림(11.13)과 같이 sockaddr_in 타입의 16바이트 구조체에 저장
각 필드 sin_family(AF_INET), sin_port(16비트 포트번호), sin_addr(32비트 IP주소),
IP주소와 포트번호는 항상 네트워크 바이트(빅 엔디안) 순서로 저장
connect(), bind(), accept()는 프로토콜에 특화된 소켓 주소 구조체를 가리키는 포인터를 필요
소켓 인터페이스를 설계한 사람들이 당면한 문제는 어떻게 이 함수들을 정의해서
어떤 종류의 소켓 주소 구조체라도 받아 들일 수 있도록 하는가 였다.
오늘날 우리는 포괄적인 void * 포인터를 사용한다.
이 문제에 대한 해결책으로 소켓 함수를 원천 sockaddr 구조체로의 포인터를 기대하도록 하고
그 후에 어플리케이션이 프로토콜에 특화된 구조체로의 모든 포인터를
일반적인(Generic) 구조체로 캐스팅하도록 정의 하였다.
typedef struct sockaddr SA; // 일반적인 sockaddr 구조체
sockaddr_in 구조체를 일반적인 sockaddr 구조체로 캐스팅할 필요가 있을 때마다 이 타입 사용
1) socket 함수 : 클라이언트와 서버는 소켓 식별자 생성하기 위해서 사용
2) connect 함수 : 클라이언트가 서버와 연결을 수립하기 위해 사용
3) bind 함수 : sockaddr 구조체 addr에 있는 서버의 소켓 주소를 소켓 식별자 sockfd와 연결
4) listen 함수 : 기본적으로 커널은 socket함수가 만든 식별자는
한 연결의 클라이언트 쪽 끝에서 존재하는 능동소켓에 대응
서버는 listen 함수를 호출해서 이 식별자를 클라이언트 대신에 서버가 사용하게 될 것이라고 알려줌
sockfd를 능동 소켓에서 listenfd 듣기 소켓으로 변환
backlog인자는 커널이 요청들을 거절하기 전에 큐에 저장해야 하는 연결의 수에 대한 정보 제공
5) accept 함수 : 클라이언트로부터의 연결 요청이 듣기 식별자(listenfd)에 도달하기를 기다린다.
addr 내에 클라이언트 소켓 주소를 채우고 Unix I/O 함수들을 사용해서
클라이언트와 통신하기 위해 사용될 수 있는 연결식별자(connfd) 리턴한다.
듣기 식별자는 클라이언트의 연결 요청의 끝점, 서버가 살아있는 동안 존재
연결 식별자는 클라이언트와 서버 사이에 성립된(established) 연결의 끝점
서버가 연결 요청을 수락할 때마다 생성, 서비스하는 동안에만 존재
리눅스는
getaddrinfo와getnameinfo라고 하는 강력한 함수들을 제공
소켓 인터페이스를 사용하는데 필요한 함수들의 인자나 구조체의 필드에 직접 전달
이진 소켓 주소 구조체들과 호스트이름, 호스트주소, 서비스이름, 포트번호들 사이에 앞뒤로 변환해준다.
특정 IP 프로토콜의 버전에 의존하지 않는네트워크 프로그램 작성 가능하게 함
int getaddrinfo(const char *host, // host와 service중에 주소로 변환하고 싶지 않으면 NULL
const char *service, // 대신 host와 service중 1개만
const struct addrinfo *hints, // 선택적으로 사용하는 인자
struct addrinfo **result); // 연결되면 함수는 0을 리턴, 실패하면 0이 아닌 에러코드를 반환
void freeaddrinfo(struct addrinfo *result); // 연결되면 메모리 누수를 피하기 위해 연결리스트 result를 삭제
const char *gai_strerror(int errcode); // 에러코드를 반환시 에러 메시지를 문자열로 변환
host 인자는 도메인 이름이거나 숫자 주소service 인자는 서비스이름(ex: http)이거나 십진수 포트번호host 인자나 service인자의 이름을 주소로 변환하고 싶지 않을 때 NULL로 설정이 가능둘중에 하나는 명시 되어야 한다.hints 인자를 사용시 보다 상세한 제어를 제공하는 addrinfo 구조체다ai_flag, ai_family, ai_socktype, ai_protocol 4개의 필드만 설정memset을 이용하여 전체 구조체를 0 또는 NULL 설정getaddrinfo는 기본적으로 구조체를 생성할 때 ai_flag를 제외한 모든 필드를 채워준다소켓 주소 구조체를 가르키는addrinfo 구조체의 연결 리스트를 가르키는 result를 출력한다struct addrinfo {
/* hints 인자가 전달될 때 상위 4개의 필드만 설정, 다른 필드는 0 또는 NULL 설정 */
int ai_flags; /* Hints argument flags */
int ai_family; /* IPv4(AF_INET) 또는 IPv6(AF_INET6) 주소로 제한 */
int ai_socktype; /* SOCK_STREAM 설정 시 */
int ai_protocol; /* Third arg to socket function */
size_t ai_addrlen; /* 소켓 구조체의 크기를 알려줌 */
char *ai_canonname; /* 정식 호스트네임, Canonical hostname */
struct sockaddr *ai_addr; /* 소켓 주소 구조체를 가르킨다 */
struct addrinfo *ai_next; /* 다음 addrinfo 구조체를 가리킨다 */
};
AI_ADDRCONFIG : 연결을 사용하려고 하면 추천
getaddrinfo가 로컬 호스트가 IPv4(IPv6)로 설정된 경우에만 IPv4(IPv6) 주소를 리턴
AI_CANONNAME : 기본적으로 ai_canonname 필드는 NULL 이다.
이 플래그가 설정되면 host의 공식이름으로의 리스트에서 첫번째 addrinfo 구조체에서의
ai_canonname 필드를 가리키도록 지시
AI_NUMERICSERV : 해당 플래그 사용시 service인자가 포트번호여야 한다.
AI_PASSIVE : getaddrinfo는 클라이언트가 connect를 호출할 때 활성화된 소켓으로 이용할 수 있는 소켓 주소를 리턴하게 해준다. host 인자는 NULL 이고 결과로 얻는 것은 소켓 주소 구조체에서 주소 필드는 와일드 카드 주소가 된다.
커널에게 이 서버는 자신의 호스트들에게 들어오는 모든 IP 주소로의 요청들을 수락할 것이라고 알려준다.
ai_socktype 를 SOCK_STREAM 설정 시 리스트가 각 고유의 주소에 대해
자신의 소켓 주소가 연결의 끝점으로 사용될 수 있는 최대 한 개의 addrinfo 구조체로 제한
int getnameinfo(const struct sockaddr *sa, socklen_t salen,
char *host, size_t hostlen,
char *service, size_t servlen, int flags);
소켓 주소 구조체를 대응되는 호스트, 서비스이름 스트링으로 변환한다sa 인자는 salen 바이트 길이의 소켓 주소 구조체를host 인자는 hostlen 바이트 길이의 버퍼로service 인자는 servlen 바이트 길이의 버퍼를 가르킨다.호스트와 서비스 이름 스트링으로 변환하고host와 service 버퍼로 복사NI_NUMERICHOST : host에서 숫자주소 스트링을 리턴도메인 이름을 리턴NI_NUMBERICSERV : 이것을 세팅하면 etc/services 경로의 탐색과정을 생략하고 포트번호를 리턴기본적으로 getnameinfo는 etc/services를 찾아가서 가능하면 포트번호 대신 서비스 이름을 리턴