堅持每天學習,堅持寫部落格。
二月份加油
套接字位址結構
通用套接字資料結構
實際使用的套接字資料結構
結構sockaddr和結構sockaddr_in的關系
使用者層和核心層交換過程
向核心傳入資料的互動過程
核心傳出資料的互動過程
套接字程式設計需要指定套接字的位址作為參數,不同的協定族有不同的位址結構定義方式。這些位址結構通常以sockaddr_開頭,每一個協定族有一個唯一的字尾,例如對于以太網,其結構名稱為sockaddr_in。
通用的套接字位址類型的定義如下,它可以在不同協定族之間進行強制轉換。‘
上述結構中協定族成員變量sa_family的類型為sa_family_t,其實這個類型是unsigned short類型,是以成員變量sa_family的長度為16個位元組。
在網絡程式設計中所使用的函數中幾乎所有的套接字函數都用這個結構作為參數,例如bind()函數的原型為:
但是使用結構struct sockaddr不友善進行設定,在以太網中,一般采結構struct sockaddr_in進行設定,這個結構的定義如下:
結構struct sockaddr_in的成員in_addr用于表示IP位址,這個結構的定義如下:
結構struct sockaddr和結構struct sockaddr_in是一個同樣大小的結構,其對應關系參見圖
struct sockaddr_in中的成員含義如下所述。
sin_len:無符号字元類型,表示結構struct sockaddr_in的長度,為16.
sin_family:無符号字元類型,通常設定為與socket()函數的domain一緻,例如AF_INET。
sin_port:無符号short類型,表示端口号,網絡位元組序
sin_addr:struct in_addr類型,其成員s_addr為無符号32位數,每8位表示IP位址的一個段,網絡位元組序。
sin_zero[8]:char類型,保留。
由于結構struct sockaddr和結構struct sockaddr_in的大小是完全一緻的,是以進行位址結構設定時,通常的方法是利用結構struct sockaddr_in進行設定,然後強制轉換位結構struct sockaddr類型。因為這兩個結構大小是完全一緻的,是以進行這樣的轉換不會有副作用。
套接字參數中有部分參數是需要使用者傳入的,這些參數用來與Linux核心進行通信,例如指向位址結構的指針。通常是采用記憶體複制的方法進行。例如bind()函數需要傳入位址結構struct sockaddr *my_addr和my_addr指向參數的長度。
向核心傳入資料的函數有send()、bind()等,從核心得到資料的函數有accept()、recv()等。傳入的過程如圖所示,bind()函數向核心中傳入的參數有套接字位址結構和結構的長度兩個結構有關的參數。
參數addlen表示位址結構的長度,參數my_addr是指向位址結構的指針。調用函數bind()的時候,位址結構通過記憶體複制的方式将其中的内容分複制到核心,位址結構長度通過傳值的方式傳入核心,核心按照使用者傳入的位址結構長度來複制套接字位址結構的内容。
從核心向使用者空間傳遞參數的過程則相反,傳出的過程如圖所示,通過位址結構的長度和套接字位址結構指針來進行位址結構參數的傳出操作。通常是兩個參數完成傳出操作的功能,一個表示位址長度的參數,另一個表示套接字位址結構位址的指針。
傳出過程與傳入過程的參數不同的是,表示位址結構長度的參數在傳入過程中是傳值,而在傳出過程中是通過傳址完成的。核心按照使用者傳入的位址結構長度進行套接字位址結構資料的複制,将核心中的位址結構資料複制到使用者傳入的位址結構指針中。