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_in
bao 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_family
tương đương với 2 bytes đầu tiên củastruct sockaddr_in
làsin_family
. Hai bytes này để phân loại socket thuộc về họ gì, ví dụ như:IF_INET
là IPv4IF_INET6
là IPv6Tiếp theo, ta thấy
struct sockaddr
có 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 sockaddr
thì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_in
có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_in6
mà 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
bind
vàconnect
, ta ép kiểustruct sockaddr
ngượ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 sockaddr
là gì? tại saoconnect
vàbind
ko dùng luônstruct sockaddr_in
?Trong C, em chưa thấy
struct sockaddr
dù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 sockaddr
là 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
bind
vàconnect
có 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 sockaddr
là kiểu dữ liệu chuẩn cho APIbind
vàconnect
.Tuy nhiên,
struct sockaddr
có kích thước bằng vớistruct sockaddr_in
, nhưng nhỏ hơnstruct sockaddr_in6
và 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 ^^