2013-03-25 23 views
9

Tôi googled nó và một số người nói "Để giữ cùng kích thước với struct sockaddr". Nhưng Kernel sẽ không sử dụng trực tiếp sockaddr (phải không?). Khi sử dụng nó. hạt nhân sẽ đưa nó trở lại với nó. Vậy tại sao không cần đệm?Tại sao không cần đệm trong sockaddr_in?

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

struct sockaddr_in { 
    short   sin_family; // e.g. AF_INET, AF_INET6 
    unsigned short sin_port;  // e.g. htons(3490) 
    struct in_addr sin_addr;  // see struct in_addr, below 
    char    sin_zero[8]; // zero this if you want to 
}; 

struct in_addr { 
    unsigned long s_addr;   // load with inet_pton() 
}; 
+0

Với tuyên bố từ chối trách nhiệm rằng tôi hoàn toàn không biết các vùng biển đã biết: Có thể là endiannes không? –

+0

@ G.Stoynev Tôi không biết ... 16 byte sắp xếp? – louxiu

+0

nó được mở rộng ở đây ...... http: //silviocesare.wordpress.com/2007/10/22/setting-sin_zero-to-0-in-struct-sockaddr_in/ –

Trả lời

7

Càng hai mảnh có liên quan của thông tin tôi có thể tìm được

Nói về một đoạn mã mà không không rõ ràng các byte

Đây là lỗi. Tôi thấy nó xảy ra dịp. Lỗi này có thể gây ra hành vi không xác định trong các ứng dụng.

Tiếp theo với một số explications

Hầu hết các mã thuần không sử dụng sockaddr_in, nó sử dụng sockaddr. Khi bạn sử dụng một hàm như sendto, bạn phải sử dụng một cách rõ ràng sockaddr_in hoặc bất kỳ địa chỉ nào bạn đang sử dụng, để sockaddr. sockaddr_in có cùng kích thước với sockaddr, nhưng bên trong kích thước thì giống nhau vì một chút hack.

Hack đó là sin_zero. Thực sự chiều dài của dữ liệu hữu ích trong sockaddr_in ngắn hơn sockaddr. Nhưng sự khác biệt là đệm trong sockaddr_in bằng cách sử dụng một bộ đệm nhỏ; bộ đệm đó là sin_zero.

và cuối cùng, một thông tin có thể được tìm thấy ở những nơi khác nhau

Trên một số kiến ​​trúc, nó sẽ không gây ra bất kỳ vấn đề không thanh toán bù trừ sin_zero. Nhưng trên các kiến ​​trúc khác, nó có thể. Yêu cầu của nó theo đặc điểm kỹ thuật để xóa sin_zero, vì vậy bạn phải làm điều này nếu bạn dự định mã của bạn bị lỗi miễn phí ngay bây giờ và trong tương lai.

trả lời câu hỏi

lý do tại sao chúng ta cần đệm 8 byte này?

và câu trả lời

Unix lập trình mạng chương 3.2 nói rằng, "Các POSIX đặc điểm kỹ thuật đòi hỏi chỉ có ba thành viên trong cấu trúc:. Sin_family, sin_addr, và sin_port Có thể chấp nhận cho một POSIX triển khai hoàn toàn để xác định cấu trúc bổ sung thành viên và điều này là bình thường đối với cấu trúc cấu trúc kết nối Internet. Hầu như tất cả triển khai thêm thành viên sin_zero để tất cả cấu trúc địa chỉsocket có kích thước tối thiểu 16 byte. "

Nó giống như cấu trúc đệm, có thể được dành riêng cho các trường bổ sung trong tương lai .Bạn sẽ không bao giờ sử dụng nó, giống như bình luận.

phù hợp với liên kết đầu tiên. Xoá bỏ các byte nói với người nhận "những byte không được sử dụng trên mặt của chúng tôi".

0

Cấu trúc đệm xảy ra vì các thành viên của cấu trúc phải xuất hiện ở ranh giới byte correect, để đạt được điều này trình biên dịch đặt vào byte đệm (hoặc bit nếu bit trường đang được sử dụng) để cấu trúc thành viên xuất hiện ở vị trí chính xác . Ngoài ra kích thước của cấu trúc phải như vậy mà trong một mảng của các cấu trúc tất cả các cấu trúc được căn chỉnh chính xác trong bộ nhớ.

Vì vậy, có thể cần thiết để bỏ qua rò rỉ bộ nhớ.

2

Vì struct sockaddr_in cần phải được đúc thành struct sockaddr, nó phải được giữ nguyên kích thước, sin_zero là một thành viên không được sử dụng với mục đích duy nhất là pad cấu trúc đến 16 byte (kích thước của sock_addr). Kích thước đệm này có thể khác nhau tùy thuộc vào họ địa chỉ. Ví dụ;

struct sockaddr_in { 
    short int sin_family;  // Address family, AF_INET 
    unsigned short int sin_port;  // Port number 
    struct in_addr sin_addr;  // Internet address 
    unsigned char sin_zero[8];  // For padding, to make it same size as struct sockaddr 
}; 

Bây giờ có những gia đình Xerox NS trong đó có các thành viên struct khác nhau:

struct sockaddr_ns { 
    u_short sns_family;  // Address family, AF_NS 
    struct ns_addr sns_addr;  // the 12-byte XNS address 
    char sns_zero[2];  // unused except for padding 
}; 
0

struct sockaddr là, phiên bản đầy đủ trừu tượng của cấu trúc này chỉ với gia đình. struct sockaddr_in là phiên bản IPv4 của cấu trúc này. Nó chỉ sử dụng 8 byte đầu tiên. struct sockaddr_in6 là phiên bản IPv6 của cấu trúc này và lớn hơn. Phần đệm cho phép các cấu trúc nhỏ hơn để phù hợp với sự thay đổi lớn nhất của cấu trúc này, do đó bộ đệm không bị giảm kích thước.

Khi bạn đang chuyển địa chỉ đến một hàm hoặc gọi hệ thống, các byte thừa không thực sự cần thiết. Nhưng lấy một địa chỉ, bạn cung cấp một địa chỉ cấu trúc cho các kết quả. Cấu trúc đó cần phải là lớn nhất trong tất cả các biến thể có thể có. Phải không - hãy tưởng tượng bạn đã cung cấp một phiên bản IPv4, nhưng đã trở lại một địa chỉ IPv6 - sau đó kết quả sẽ vượt quá cấu trúc và làm hỏng bất kỳ cửa tiếp theo nào trong bộ nhớ.

Để tránh tham nhũng bộ nhớ này, hầu hết các chức năng liên quan đều lấy kích thước cấu trúc làm tham số. Nhưng bây giờ, khi bạn vượt qua phiên bản IPv4 đó và kích thước quá nhỏ của nó, bạn kết thúc với một phiên bản IPv6 không được điền đầy đủ của cấu trúc. Nhìn vào gia đình, bạn có thể thấy nó là IPv6. Nhưng nếu bạn đưa cấu trúc vào IPv6 và cố gắng sử dụng nó, nội dung sẽ sai vì cấu trúc quá nhỏ để chứa đầy đủ, dữ liệu hợp lệ.

Việc đệm cấu trúc nhỏ hơn tránh các lỗi này và tránh mọi sự cố bảo mật tiềm ẩn có liên quan.

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