2014-05-01 29 views
15

Từ những gì tôi hiểu struct addrinfo được sử dụng để chuẩn bị cấu trúc địa chỉ socket và struct sockaddr chứa thông tin địa chỉ socket. Nhưng điều đó thực sự có ý nghĩa gì? struct addrinfo chứa một con trỏ tới một struct sockaddr. Tại sao giữ chúng riêng biệt? Tại sao chúng ta không thể kết hợp tất cả mọi thứ trong sockaddr vào addr_info?Sự khác nhau giữa struct addrinfo và struct sockaddr

Tôi chỉ đoán ở đây nhưng lý do cho sự tách biệt của họ là tiết kiệm không gian khi đi qua các cấu trúc? Ví dụ trong lệnh bind(), tất cả những gì nó cần là số cổng và địa chỉ internet. Vì vậy, cả hai được nhóm trong một sockaddr struct. Vì vậy, chúng tôi chỉ có thể vượt qua cấu trúc nhỏ này thay vì addrinfo struct lớn hơn?

struct addrinfo { 
    int    ai_flags;  // AI_PASSIVE, AI_CANONNAME, etc. 
    int    ai_family; // AF_INET, AF_INET6, AF_UNSPEC 
    int    ai_socktype; // SOCK_STREAM, SOCK_DGRAM 
    int    ai_protocol; // use 0 for "any" 
    size_t   ai_addrlen; // size of ai_addr in bytes 
    struct sockaddr *ai_addr;  // struct sockaddr_in or _in6 
    char   *ai_canonname; // full canonical hostname 

    struct addrinfo *ai_next;  // linked list, next node 
}; 

struct sockaddr { 
    unsigned short sa_family; // address family, AF_xxx 
    char    sa_data[14]; // 14 bytes of protocol address 
}; 

Trả lời

12

struct addrinfo được trả về bởi getaddrinfo(), và chứa, trên thành công, một danh sách liên kết như vậy struct s cho một hostname và/hoặc dịch vụ cụ thể.

Thành viên ai_addr không thực sự là struct sockaddr, bởi vì struct chỉ đơn thuần là một thành phần chung chứa tất cả những người khác và được sử dụng để xác định loại cấu trúc nào bạn thực sự có. Tùy thuộc vào những gì bạn vượt qua để getaddrinfo() và chức năng đó phát hiện ra, ai_addr thực sự có thể là con trỏ đến struct sockaddr_in hoặc struct sockaddr_in6 hoặc bất kỳ điều gì khác tùy thuộc vào điều gì phù hợp với mục nhập địa chỉ cụ thể đó. Đây là một lý do chính đáng tại sao chúng được giữ "riêng biệt", vì thành viên đó có thể trỏ đến một trong các loại khác nhau của struct s, điều này không thể thực hiện được nếu bạn cố gắng mã hóa tất cả các thành viên thành struct addrinfo, khác nhau struct s có các thành viên khác nhau.

Đây có lẽ là cách dễ nhất để lấy thông tin này nếu bạn có tên máy chủ, nhưng đó không phải là cách duy nhất. Đối với kết nối IPv4, bạn chỉ có thể tự điền một cấu trúc struct sockaddr_in, nếu bạn muốn và bạn có dữ liệu để làm như vậy, và tránh đi qua rigamarole gọi getaddrinfo(), mà bạn có thể phải chờ đợi nếu nó cần phải đi ra ngoài vào internet để thu thập thông tin cho bạn. Bạn không phải sử dụng struct addrinfo chút nào.

+0

là getaddrinfo() cũng hữu ích hơn nếu bạn chỉ biết tên máy chủ chứ không phải địa chỉ IP của máy chủ? Bởi vì nó có vẻ lặp đi lặp lại nếu bạn là khách hàng (và bạn biết ip của máy chủ) và bạn gọi getaddrinfo và bạn gửi địa chỉ ip của máy chủ và getaddrinfo() trả về cấu trúc addrinfo với tất cả các chi tiết bạn đã biết? bình luận này chỉ cần nói lại những gì bạn nói .. xin lỗi – user68212

+0

'getaddrinfo()' đôi khi thuận tiện nếu bạn có địa chỉ IP trong một chuỗi * * - nói sau khi nó được nhập vào dòng lệnh. Bạn có thể phân tích nó cho chính mình và đưa nó vào định dạng tích phân 32 bit theo yêu cầu của 'struct sockaddr_in', nhưng đôi khi bạn có thể thấy dễ dàng hơn để cho' getaddrinfo() 'làm điều đó cho bạn. Nếu bạn đã có IP trong một định dạng, bạn có thể thả vào 'struct sockaddr_in', gọi' getaddrinfo() 'thường sẽ là vô nghĩa. –

Các vấn đề liên quan