struct sockaddr_in
{
sa_family_t sin_family;
uint16_t sin_port;
struct in_addr sin_addr;
char sin_zero(8);
};
struct in_addr
{
in_addr_t s_addr;
};
아래 값 중 하나를 넣어주면 된다.
- AF_INET : IPv4에 적용
- AF_INET6 : IPv6에 적용
- AF_LOCAL : 로컬 통신을 위한 유닉스 프로토콜 주소체계
16비트 포트 번호를 '네트워크 바이트 순서대로' 저장한다.
32비트 IP 주소정보를 저장한다. 역시 '네트워크 바이트 순서대로' 저장한다.
별 의미 없다. sockaddr_in과 sockaddr의 크기를 맞추기 위해 존재하는 필드인데, 0으로 채워주기만 하면 된다.
TCP/IP 시리즈 첫 번째 글의 예제에서 다음과 같은 문장을 본 적 있는가?(없다면 되돌아가서 보고 오자)
bind(svr_sock, (struct sockaddr*)&svr_addr, sizeof(svr_addr));
보면, bind() 함수는 두 번째 인자로 struct sockaddr*형 인자를 요구하고 있음을 알 수 있다. 그런데 굳이 왜 sockaddr 구조체의 포인터가 아닌 sockaddr_in 구조체의 포인터를 형변환하여 넣어주는 것일까? 이유는 간단하다. sockaddr보다 sockaddr_in이 사용하기 더 편리하기 때문이다. sockaddr의 선언을 보자.
struct sockaddr
{
sa_family_t sin_family;
char sa_data[14];
}
sockaddr 구조체의 sa_data 멤버에는 IP 주소 + 포트번호가 하나로 묶여서 저장되어야 한다. 이는 매우 불편하기 때문에, 비교적 쉽게 사용할 수 있도록 sockaddr_in 구조체를 새로 정의한 것이다.
IP 주소가 하나인 컴퓨터에서는 현재 컴퓨터의 IP주소를 소켓에 할당하도록 하며, Multi-homed(IP가 2개 이상)인 경우 어떤 IP로 데이터가 들어오든지 포트 번호만 맞으면 해당 포트로 데이터를 전달해주도록 하는 상수이다. 주로 서버측에서 사용된다. 사용법은 아래와 같다.
struct sockaddr_in addr;
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = htonl(INADDR_ANY);
addr_sin_port = htons(4000);