2012-02-16 11 views
14

Tôi có thể thấy lý do tại sao nó hữu ích khi đúc sockaddr đến sockaddr_in, nhưng tôi không hiểu làm thế nào điều này là có thể. Từ những gì tôi đã đọc, chúng có cùng kích thước và sockaddr_in được thêm vào với sin_zero để làm cho nó có cùng kích thước. Tôi muốn biết làm thế nào trình biên dịch biết nơi để lấy thông tin từ sockaddr_in nếu nó được bố trí khác nhau để sockaddr.Tại sao chúng ta có thể bỏ sockaddr vào sockaddr_in

Trả lời

16

Có thể vì bạn thường truyền con trỏ chứ không phải cấu trúc. Bạn làm những gì trong ngôn ngữ tự nhiên có nghĩa là "hãy xử lý con trỏ này đến một số socket structure làm con trỏ đến một số internet socket structure thay thế". Trình biên dịch không có vấn đề gì để giải thích lại con trỏ.

Dưới đây là mô tả chi tiết được đưa lên từ nhận xét:

Một sockaddr là 16 byte trong kích thước - hai byte đầu tiên là sa_family, và 14 byte còn lại là những sa_data đó là dữ liệu tùy ý. A sockaddr_in cũng có kích thước 16 byte - 2 byte đầu tiên là sin_family (luôn là AF_INET), 2 byte tiếp theo là sin_port, 4 byte tiếp theo là sin_addr (địa chỉ IP) và 8 byte cuối cùng là sin_zero không được sử dụng trong IPv4 và chỉ được cung cấp để đảm bảo 16 byte. Bằng cách này, trước hết bạn có thể xem sockaddr.sa_family và nếu đó là AF_INET thì hãy giải thích toàn bộ sockaddr dưới dạng sockaddr_in.

A sockaddr_in không được lưu trữ bên trong trường sockaddr.sa_data. Toàn bộ sockaddr là toàn bộ sockaddr_in (khi sockaddr.sa_familyAF_INET, tức là). Nếu bạn lấy một con trỏ sockaddr* và bỏ nó vào một con trỏ sockaddr_in*, sau đó:

  • sockaddr.sa_familysockaddr_in.sin_family
  • byte 0-1 của sockaddr.sa_datasockaddr_in.sin_port
  • byte 2-5 là sockaddr_in.sin_addr
  • byte 6 -13 là sockaddr_in.sin_zero.
+0

Có vẻ lạ vì biến được cho là lưu trữ địa chỉ trong sockaddr là sa_data là char [14], nhưng sockaddr_in sử dụng dấu ngắn chưa được ký. Tôi giả định rằng trình biên dịch sẽ đọc số byte chưa ký đầu tiên từ char [14] và làm cho địa chỉ đó, và phần còn lại của char [14] là dữ liệu được gửi đi? Ngoài ra, nếu tôi thêm kích thước của hai cấu trúc, chúng có vẻ không giống kích thước. sin_zero có vẻ quá lớn. Tôi chỉ tring để có được những gì đang xảy ra ở đây! –

+11

Một 'sockaddr' có kích thước 16 byte - hai byte đầu tiên là' sa_family' và 14 byte còn lại là 'sa_data' là dữ liệu tùy ý. Một 'sockaddr_in' cũng có kích thước 16 byte - 2 byte đầu tiên là' sin_family' (luôn là 'AF_INET'), 2 byte tiếp theo là' sin_port', 4 byte tiếp theo là 'sin_addr' (địa chỉ IP) và 8 byte cuối cùng là 'sin_zero' không được sử dụng trong IPv4 và chỉ được cung cấp để đảm bảo 16 byte. Bằng cách này, bạn có thể nhìn vào 'sockaddr.sa_family' trước tiên, và nếu nó là' AF_INET' thì giải thích toàn bộ 'sockaddr' là' sockaddr_in'. –

+6

Một 'sockaddr_in' không được lưu trữ bên trong trường' sockaddr.sa_data'. Toàn bộ 'sockaddr' ** là ** toàn bộ' sockaddr_in' (khi 'sockaddr.sa_family' là' AF_INET', nghĩa là). Nếu bạn lấy một con trỏ 'sockaddr *' và đưa nó vào một con trỏ 'sockaddr_in *', 'sockaddr.sa_family' là' sockaddr_in.sin_family', byte 0-1 của 'sockaddr.sa_data' là' sockaddr_in.sin_port', bytes 2-5 là 'sockaddr_in.sin_addr' và byte 6-13 là' sockaddr_in.sin_zero'. –