linux網絡編程

socket概念

  • 在Linux中的網絡編程是通過socket接口來進行的。socket是一種特殊的I/O接口,它也是一種文件描述符。它是一種常用的進程之間通信機制,通過它不僅能實現本地機器上的進程之間的通信,而且通過網絡能夠在不同機器上的進程之間進行通信。
  • 每一個socket都用一個半相關描述{協(xié)議、本地地址、本地端口}來表示;
  • 一個完整的套接字則用一個相關描述{協(xié)議、本地地址、本地端口、遠程地址、遠程端口}來表示。
  • socket也有一個類似于打開文件的函數調用,該函數返回一個整型的socket描述符,隨后的連接建立、數據傳輸等操作都是通過socket來實現的。
  • socket類型
    (1)流式socket(SOCK_STREAM)
    流式套接字提供可靠的、面向連接的通信流;它用于TCP協(xié)議,從而保證了數據傳輸的正確性和順序性。
    (2)數據報socket(SOCK_DGRAM)
    數據報套接字定義了一種無連接的服務,數據通過相互獨立的報文進行傳輸,是無序的,并且不保證是可靠、無差錯的。它使用數據報協(xié)議UDP。
    (3)原始socket
    原始套接字允許對底層協(xié)議如IP或ICMP進行直接訪問,它功能強大但使用較為不便,主要用于一些協(xié)議的開發(fā)。
  • socket信息數據結構
struct sockaddr 
{
    unsigned short sa_family; /*地址族*/
    char sa_data[14]; /*14字節(jié)的協(xié)議地址,包含該socket的IP地址和端口號。*/
};

struct sockaddr_in 
{
    short int sa_family; /*地址族*/
    unsigned short int sin_port; /*端口號*/
    struct in_addr sin_addr; /*IP地址*/
    unsigned char sin_zero[8]; /*填充0 以保持與struct sockaddr同樣大小*/
}

struct socketaddr_in : struct sockaddr是通用的套接字地址;
struct sockaddr_in則是internet環(huán)境下套接字的地址形式



數據存儲優(yōu)先順序的轉換

  • 計算機數據存儲有兩種字節(jié)優(yōu)先順序:高位字節(jié)優(yōu)先(稱為大端模式)和低位字節(jié)優(yōu)先(稱為小端模式)。
  • Internet上數據以高位字節(jié)優(yōu)先順序在網絡上傳輸;計算機中通常使用低位字節(jié)優(yōu)先存儲數據
  • 因此需要對這兩個字節(jié)存儲優(yōu)先順序進行相互轉化。函數:htons()、ntohs()、htonl()和ntohl(),分別實現網絡字節(jié)序和主機字節(jié)序的轉化,h代表host,n代表network,s代表short,l代表long。通常16位的端口號用s代表,而IP地址用l來代表。


地址格式轉換

  • 通常用戶在表達地址時采用的是點分十進制表示的數值(或者是以冒號分開的十進制IPv6地址),而在通常使用的socket編程中所使用的則是二進制值,這就需要將這兩個數值進行轉換。這里在IPv4中用到的函數有inet_aton()、inet_addr()和inet_ntoa(),而IPv4和IPv6兼容的函數有inet_pton()和inet_ntop()。進制值。


  • inet_pton()和inet_ntop()函數中p和n分別代表表達(presentation)和數值(numeric)。地址的表達格式通常是ASCII字符串,數值格式則是存放到套接字地址結構的二進制值。
  • inet_ntop
    原型:
    const char *inet_ntop(int af, const void *src, char *dst, socklen_t cnt);
    參數說明:
    af:IPv4或IPv6協(xié)議選擇,分別設置成AF_INET或AF_INET6。
    src:要轉化的地址
    dst:轉化后的值
    socklen_t cnt:他是所指向緩存區(qū)dst的大小,避免溢出,如果緩存區(qū)太小無法存儲地址的值,則返回一個空指針。
    返回值:成功返回字符串的首地址,錯誤返回NULL;
  • inet_addr
    功能:將一個點分十進制的IP轉換成一個長整數型數(u_long類型)
    原型:in_addr_t inet_addr(const char *cp);
    參數:字符串,一個點分十進制的IP地址

名字地址轉換

  • 通常,人們在使用過程中都不愿意記憶冗長的IP地址,尤其到IPv6時,地址長度多達128位,那時就更加不可能一次次記憶那么長的IP地址了。因此,使用主機名將會是很好的選擇。

  • 在Linux中,同樣有一些函數可以實現主機名和地址的轉化,最為常見的有gethostbyname()、gethostbyaddr()和getaddrinfo()等,它們都可以實現IPv4和IPv6的地址和主機名之間的轉化。其中gethostbyname()是將主機名轉化為IP地址,gethostbyaddr()則是逆操作,是將IP地址轉化為主機名,另外getaddrinfo()還能實現自動識別IPv4地址和IPv6地址。




    addrinfo結構體常見選項值


  • 主要數據結構

struct hostent
{
    char *h_name;/*正式主機名*/
    char **h_aliases;/*主機別名*/
    int h_addrtype;/*地址類型,可設置,不設置就默認為AF_INET*/
    int h_length;/*地址字節(jié)長度,可設置4或6,不設就默認為4*/
    char **h_addr_list;/*指向IPv4或IPv6的地址指針數組*/
}
struct addrinfo
{
    int ai_flags;/*AI_PASSIVE, AI_CANONNAME;*/
    int ai_family;/*地址族*/
    int ai_socktype;/*socket類型*/
    int ai_protocol;/*協(xié)議類型*/
    size_t ai_addrlen;/*地址字節(jié)長度*/
    char *ai_canonname;/*主機名*/
    struct sockaddr *ai_addr;/*socket結構體*/
    struct addrinfo *ai_next;/*下一個指針鏈表*/
}
?著作權歸作者所有,轉載或內容合作請聯系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容