Linux socket編程:地址及轉換

1. 網(wǎng)絡字節(jié)序與主機字節(jié)序

1.1 主機字節(jié)序()

CPU的字節(jié)順序類型,

  • 小端,little endian;
  • 大端,big endian;

1.2 網(wǎng)絡字節(jié)序

TCP/IP中規(guī)定好的一種數(shù)據(jù)表示格式,它與具體使用的CPU類型和操作系統(tǒng)類型無關;網(wǎng)絡字節(jié)序固定的采用大端終結的方式

1.3 字節(jié)序轉換函數(shù)

  • htons:主機序 -> 網(wǎng)絡序,處理unsigned short類型;
  • htonl:主機序 -> 網(wǎng)絡序,處理unsigned long類型;
  • ntohs:網(wǎng)絡序 -> 主機序, 處理unsigned short類型;
  • ntohl:網(wǎng)絡序 -> 主機序,處理unsigned long類型;

2. Socket地址結構

2.1 sockaddr結構體

定義如下,這個結構體會作為bind、connect、recvfrom、sendto等函數(shù)的輸入地址參數(shù)結構體,

struct sockaddr {
    sa_family_t sa_family;
    char        sa_data[14];
}

這里的sa_data包含了地址+端口號

2.2 sockaddr_in結構體

struct sockaddr_in {
    sa_family_t    sin_family; /* address family: AF_INET */
    in_port_t      sin_port;   /* port in network byte order */
    struct in_addr sin_addr;   /* internet address */
};

/* Internet address. */
struct in_addr {
    uint32_t       s_addr;     /* address in network byte order */
};

這個結構體的大小和sockaddr結構體的大小一致,可以互相轉換;
在網(wǎng)絡編程中我們會對sockaddr_in的結構體進行操作賦值,使用這個結構體建立地址信息;然后強制類型轉換成sockaddr并傳遞給調用函數(shù),

struct sockaddr_in servaddr;

bzero( (void *)&servaddr, sizeof(servaddr) );
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl( INADDR_ANY );
servaddr.sin_port = htons(MY_PORT_NUM);

sctp_bindx( sock_fd, (struct sockaddr *)&servaddr, addr_count,  SCTP_BINDX_ADD_ADDR)
  • 使用htonl和htons進行字節(jié)序轉換;
  • 強制類型轉換sockaddr_in到sockaddr作為bind的輸入?yún)?shù);

3. 轉換函數(shù)

3.1 inet_ntop函數(shù)

函數(shù)把一個網(wǎng)絡字節(jié)序的二進制的IP地址轉換成一個ASCII類型的IP,定義如下,

#include <arpa/inet.h>
const char *inet_ntop(int af, const void *src, char *dst, socklen_t size);
  • af 代表地址族,比如說AF_NET或者AF_INET6;
  • 這個函數(shù)把src地址轉換結果保存到dst指向的buffer中;比如說IPv4的時候把一個in_addr的結構體轉換成“ddd. ddd. ddd. ddd”的IP地址結構;

3.2 inet_pton函數(shù)

這個函數(shù)的功能和inet_ntop函數(shù)恰好相反,

 #include <arpa/inet.h>

 int inet_pton(int af, const char *src, void *dst);

轉換的網(wǎng)絡序的二進制IP會寫入dst指向的內存中;這個函數(shù)可以用來把一個IP字符串轉換并賦值給地址結構體;
來看一個簡單的例子,

struct sockaddr_in sa;
char ip[20];
inet_pton(AF_INET, "172.0.0.1", &(sa.sin_addr));
printf("[inet_pton]: IP addr --> binary: %x\n", sa.sin_addr);

inet_ntop(AF_INET, &(sa.sin_addr), ip, 20);
printf("[inet_ntop]: binary --> IP address: %s\n", ip);

打印出來的信息如下,

  1. 結果是以16進制打印的,網(wǎng)絡字節(jié)序是大端終結;對打印結果拆解一下就是,01 - 00 - 00 - ac;每個小數(shù)點隔開的數(shù)字都以一個字節(jié)存儲,比如說AC就是172的16進制表示;
inet_pton: IP addr --> binary: 10000ac
  1. 恢復成字符串IP地址
[inet_ntop]: binary --> IP address: 172.0.0.1

3.3 inet_addr函數(shù)

把一個小數(shù)點分隔的IP轉換成一個網(wǎng)絡字節(jié)序的長整型的數(shù)(u_long)

in_addr_t inet_addr(const char *cp);

舉個簡單的例子

printf("[inet_addr]: IP addr --> binary: %x\n", inet_addr("172.0.0.1"))

打印結果

[inet_addr]: IP addr --> binary: 10000ac
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

  • 1.1 網(wǎng)絡常識 1)網(wǎng)絡的7層網(wǎng)絡協(xié)議 ISO按照邏輯劃分出來7層網(wǎng)絡協(xié)議 應用層:和應用程序打交道的,進行數(shù)據(jù)...
    vera姐姐閱讀 531評論 0 1
  • 研究IPv6 socket編程原因: Supporting IPv6 in iOS 9 WWDC2015蘋果宣布在...
    li大鵬閱讀 7,643評論 7 15
  • 大綱 一.Socket簡介 二.BSD Socket編程準備 1.地址 2.端口 3.網(wǎng)絡字節(jié)序 4.半相關與全相...
    VD2012閱讀 2,706評論 0 5
  • 簡介 Socket理論 Socket工作流程 核心函數(shù)講解 服務的如何獲取客戶端的信息 字符串ip和網(wǎng)絡二進制的轉...
    第八區(qū)閱讀 4,094評論 0 4
  • 來答一下。 為了幫大家創(chuàng)造更多使用日語的語言環(huán)境,更新了很多萌萌噠app工具和網(wǎng)站喔~ 下拉下拉下拉↓↓↓↓↓↓↓...
    恒變閱讀 820評論 6 34

友情鏈接更多精彩內容