네트워크 프로 그래 밍 에서 4 개의 중요 한 주소 데이터 구조

16110 단어 데이터 구조
1. IPv4: struct sockaddr_바이트
 1 struct sockaddr_in {  2      sa_family_t sin_family;             /* AF_INET */

 3      in_port_t sin_port;                 /* Port number. */

 4      struct in_addr sin_addr;            /* Internet address. */

 5 

 6      /* Pad to size of `struct sockaddr'. */

 7      unsigned char sin_zero[sizeof (struct sockaddr) -

 8                             sizeof (sa_family_t) -

 9                             sizeof (in_port_t) -

10                             sizeof (struct in_addr)]; 11 }; 12 typedef uint32_t in_addr_t; 13 struct in_addr { 14     in_addr_t s_addr;                    /* IPv4 address */

15 };

2. IPv6: struct sockaddr_바이트
 1 struct sockaddr_in6 {  2     sa_family_t sin6_family;    /* AF_INET6 */

 3     in_port_t sin6_port;        /* Transport layer port # */

 4     uint32_t sin6_flowinfo;     /* IPv6 flow information */

 5     struct in6_addr sin6_addr;  /* IPv6 address */

 6     uint32_t sin6_scope_id;     /* IPv6 scope-id */

 7 };  8 struct in6_addr {  9  union { 10         uint8_t u6_addr8[16]; 11         uint16_t u6_addr16[8]; 12         uint32_t u6_addr32[4]; 13  } in6_u; 14 

15     #define s6_addr                 in6_u.u6_addr8

16     #define s6_addr16               in6_u.u6_addr16

17     #define s6_addr32               in6_u.u6_addr32

18 };

3. 유 니 버 설 구조 체 1: struct sockaddr, 16 바이트
1 struct sockaddr { 2      sa_family_t sa_family;       /* Address family */

3      char sa_data[14];            /* protocol-specific address */

4 };

4. 통용 구조 체 2: struct sockaddrstorage, 128 바이트
 
 1 /* Structure large enough to hold any socket address 

 2 (with the historical exception of AF_UNIX). 128 bytes reserved.  */

 3 

 4 #if ULONG_MAX > 0xffffffff

 5 # define __ss_aligntype __uint64_t

 6 #else

 7 # define __ss_aligntype __uint32_t

 8 #endif

 9 #define _SS_SIZE        128

10 #define _SS_PADSIZE     (_SS_SIZE - (2 * sizeof (__ss_aligntype)))

11 

12 struct sockaddr_storage

13 {

14     sa_family_t ss_family;      /* Address family */

15     __ss_aligntype __ss_align;  /* Force desired alignment.  */

16     char __ss_padding[_SS_PADSIZE];

17 };

 
 
 
 
 
왜 통용 구조 체 가 있 고 왜 두 개의 통용 구조 체 가 있 습 니까?다음은 순 전 히 개인 적 인 견해 다.
네트워크 통신 에는 IPv 4, IPv 6, IPX, X. 25, AX. 25... (socket 함수 의 domain 매개 변 수 는 프로 토 콜 족 을 나타 낸다).네트워크 프로 그래 밍 에서 사용 되 지 않 는 것 은 어떤 프로 토 콜 입 니까? 같은 socket API 를 사용 합 니 다. 모든 프로 토 콜 은 네트워크 주소 의 구조 체 가 다 릅 니 다. 예 를 들 어 IPv 4 는 struct sockaddr 입 니 다.in, IPv 6 는 struct sockaddrin6. 따라서 네트워크 주 소 를 나타 내 는 모든 구조 체 를 하나의 통용 되 는 구조 체 로 추상 화해 야 한다. 추상 화 된 구조 체 는 바로 struct sockaddr 이다.(구체 적 인 협의의 주소 구조 와 통용 되 는 주소 구조의 관 계 는 대상 을 대상 으로 프로 그래 밍 하 는 대상 과 클래스 의 관계 와 유사 하 다. 나 는 대상 을 대상 으로 프로 그래 밍 하 는 것 을 배 운 적 이 없다. 다만 이 두 가지 사상 이 약간 유사 하 다 는 것 을 어렴풋이 느 낄 뿐이다)
struct sockaddr 와 관련 된 sock API 는 다음 과 같 습 니 다.
 1 /*application->kernel*/

 2 int bind   (int sockfd, struct sockaddr *my_addr, socklen_t addrlen);  3 

 4 int connect(int sockfd, const struct sockaddr *serv_addr,  5  socklen_t addrlen);  6 

 7 int sendto (int s, const void *msg, size_t len, int flags,  8             const struct sockaddr *to, socklen_t tolen);  9 

10 /*kernel->application*/

11 int  accept     (int s, struct sockaddr *addr, socklen_t *addrlen); 12 

13 int  recvfrom   (int s,  void  *buf, size_t len, int flags, 14                  struct sockaddr *from, socklen_t *fromlen); 15 

16 int  getpeername(int s, struct sockaddr *name, socklen_t *namelen); 17 int  getsockname(int s, struct sockaddr *name, socklen_t *namelen);

그런데 왜 struct sockaddrstorage 라 는 유 니 버 설 구조 체 는?
    일반적인 주소 데이터 구조 로 서 그 크기 는 모든 구체 적 인 프로 토 콜 주소 구조 크기 의 최대 값 이 어야 합 니 다. 그러나 size of (struct sockaddr) = 16, size of (struct sockaddr in6) = 28, 분명히 struct sockaddr 라 는 통용 되 는 데이터 구조 hold 는 IPv 6 를 유지 하지 못 하기 때문에 struct sockaddrstorage 라 는 새로운 구 조 는 하늘 을 가로 질 러 나 왔 습 니 다. 크기 는 128 바이트 이 므 로 현재 프로 토 콜 의 주소 구 조 를 담 을 수 있 을 것 입 니 다.
다양한 프로 토 콜 과 관련 된 네트워크 프로 그래 밍 에서 struct sockaddrstorage 라 는 구조 체 는 통신 주 소 를 표시 하고 socket API 를 호출 할 때 struct sockaddrstorage 강제 형식 은 struct sockaddr 로 변환 되 고 주소 길 이 는 size of (struct sockaddr storage) 입 니 다.예:
1 struct sockaddr_storage addr; 2 /*

3      4 */

5 sendto (s, *msg, len, flags, (struct sockaddr *)&addr, sizeof(struct sockaddr_storage));

API 에 있 는 struct sockaddr 를 struct sockaddr 로 직접 바 꾸 지 않 는 이 유 를 물 어 볼 수도 있 습 니 다.storage?매번 쓸 때마다 유형 전환 을 강요 하 는 게 얼마나 귀 찮 은 데.
하나의 API 정의 후 인 자 는 바 꿀 수 없습니다. 그렇지 않 으 면 오래된 코드 가 실 행 될 수 없습니다.
처음부터 struct sockaddr 의 크기 를 크게 정의 하지 않 았 느 냐 는 질문 도 있 을 것 이다.
struct sockaddr 를 정의 할 때 IPv 4 시대 에 struct sockaddr 를 정의 하 는 사람 은 미래 에 IPv 6 의 탄생 을 예상 하지 못 했 기 때문에 struct sockaddr 를 struct sockaddr 와in 같은 크기.
IPv 4/IPv 6 혼합 프로 그래 밍 예시:
 1 struct sockaddr_storage addr;  2 memset(&addr, 0, sizeof(struct sockaddr_storage));  3 if (isIPv6 == TRUE)  4 {  5     struct sockaddr_in6 *addr_v6 = (struct sockaddr_in6 *)&addr;  6     addr_v6->sin6_family = AF_INET6;  7     addr_v6->sin6_port = 1234;  8     inet_pton(AF_INET6, “2001:3211::1”, &(addr_v6->sin6_addr));  9 } 10 else

11 { 12     struct sockaddr_in *addr_v4 = (struct sockaddr_in *)&addr; 13     addr_v4->sin_family = AF_INET; 14     addr_v4->sin_port = 1234; 15     inet_aton(“192.168.1.228”, &(addr_v4->sin_addr)); 16 } 17 

18 sendto(sock, buf, len, 0, (struct sockaddr *)&addr, sizeof(struct sockaddr_storage));

좋은 웹페이지 즐겨찾기