30/09/2018, 23:43
Giúp giải thích code C phần socket
Trong 2 hàm sau:
bind(socket,(struct sockaddr *)&server , sizeof(server));
hoặc
connect(socket,(struct sockaddr *)&client , sizeof(client))
struct sockaddr_in server hoặc struct sockadd_in client khi cast về struct sockaddr * thì thông tin Port number được đưa vào 2 hàm trên như thế nào ?
Hay việc này diễn ra ở đoạn nào khác? Mình thấy trong 2 tiến trình bind hoặc connect , truct sockaddr_in` không được sử dụng trực tiếp vào hàm nào?
Bài liên quan





Trước hết mình xem qua các struct này được định nghĩa thế nào.
Đạt có đánh dấu số lượng byte theo sau mỗi member của struct.
Như vậy, mình thấy được
struct sockaddr_inbao gồm 2 bytes đầu tiên làsin_family, có thể hiểu là header, và 14 bytes tiếp theo là data.Bây giờ mình xem qua
struct sockaddrỞ đây mình thấy struct này cũng có 2 bytes đầu tiên là
sa_familytương đương với 2 bytes đầu tiên củastruct sockaddr_inlàsin_family. Hai bytes này để phân loại socket thuộc về họ gì, ví dụ như:IF_INETlà IPv4IF_INET6là IPv6Tiếp theo, ta thấy
struct sockaddrcó 14 bytes kiểu char là một mảng. Một kỹ thuật hay được dùng trong network programming là dùng một array bytes để chứa dữ liệu(data). Khi ta caststruct sockaddr_in, bất kể client hay server, hoặcstruct sockaddr_in6, dành cho IPv6, về dạngstruct sockaddrthìchar sa_data[14]. Khi muốn sử dụng chỉ cần gọi cáichar sa_data[14]ra ép kiểu là lấy được mọi giá trị ta cần nhưsin_port,sin_addr. Để ý ở đây,struct sockaddr_incóchar sin_zero[8], đây là phần thừa, không sử dụng. Người ta chỉ khai báo như vậy để phần data của struct này có độ dài giống nhưstruct sockaddr_in6mà thôi. Phần này không dùng trong IPv4.Vậy làm sao có thể đọc được sin_port và sin_addr từ sa_data
Cách đơn giản nhất là trong hàm
bindvàconnect, ta ép kiểustruct sockaddrngược vềstruct sockaddr_in.Vậy mấu chốt của ép kiểu không phải là cấu trúc dữ liệu, hay type ( vd: struct, int, char…) mà là length?
Rất cảm ơn bác.
Có thể hiểu như vậy Ta có một chuỗi bytes. Đọc như thế nào, hiểu như thế nào là dựa vào struct mà mình ép xuống.
Ví dụ có chuỗi 4 bytes. Nếu ép về int, có nghĩa đó là 1 số nguyên 4 bytes. Nếu ép về char, thì đây là một chuỗi văn bản có 4 bytes (hoặc 3 bytes dữ liệu, 1 byte kết thúc chuỗi.)
Lý do cho sự tồn tại của
struct sockaddrlà gì? tại saoconnectvàbindko dùng luônstruct sockaddr_in?Trong C, em chưa thấy
struct sockaddrdùng với mục đích declaration mà chỉ dùng để cast, nếu thực sự cần nó tại sao không ẩn vào trong các hàm?Lý do cho sự tồn tài của
struct sockaddrlà API. Một API phải có một interface rõ ràng, kiểu dữ liệu truyền vào cụ thể.Hàm
bindvàconnectcó thể nhận vào IPv4 hoặc IPv6 hoặc kiểu Network Address khác. Vậy ta cần phải chọn một kiểu struct làm chuẩn.struct sockaddrlà kiểu dữ liệu chuẩn cho APIbindvàconnect.Tuy nhiên,
struct sockaddrcó kích thước bằng vớistruct sockaddr_in, nhưng nhỏ hơnstruct sockaddr_in6và nhỏ hơnstruct sockaddr_un. Thế nên ta cần thêm một giá trị nữa là length. Dựa vào length, ở đây làsizeof(server), ta sẽ biết là struct truyền vào có kích thước bao nhiêu. Hoặc có thể sử dụng membersa_familyđể biết loại network address là gì để ép kiểu trở lại kiểu ban đầu.hay quá ^^ cám ơn ad ^^