網絡通信之大小端、字節序轉換函數

在上篇文章中我們提到了UDP,TCP有關函數,並知道了一個重要的結構體struct sockaddr。想要實現通信首先要知道通信端的地址,所以首先了解一下IPv4套接字地址結構體。

//IPv4 套接字地址結構體,用來存放地址信息
struct sockaddr_in    //此結構體大小是16字節
{
    sa_family_t sin_family;  //2 字節 協議族(AF_INET、AF_INET6、PF_PACKET)
    in_port_t sin_port;      //2 字節 端口
    struct in_addr sin_addr; //4 字節 地址
    char sin_zero[8]         //8 字節  必須爲0
};
struct in_addr
{
    in_addr_t s_addr;     //4 字節
};

注意 : 爲了使不同格式地址能被傳入套接字函數,地址須要強制轉換成通用套接字地址結構。

//此結構體大小是16字節,函數參數的類型是此結構體,但其沒有表示地址信息的成員變量,
//所以用IPv4結構體定義,強轉成這個就可以了。(關鍵:大小一樣)
struct sockaddr  
{
    sa_family_t sa_family;    // 2 字節
    char sa_data[14];         //14 字節
};  //通用套接字地址結構體,一般用來強轉IPv4結構體

所以現在就是怎樣給IPv4結構體賦值的問題了。
例子 :

//定義服務器IPv4地址結構(假設服務器的IP10.0.110.110  port=8080)
struct sockaddr_in server_addr;    //定義變量
//memset(&server_addr,0,sizeof(server_addr));   //清空1
bzero(&server_addr,sizeof(server_addr));     //清空2
//給成員變量賦值
server_addr.sin_family = AF_INET;		//ipv4協議
server_addr.sin_port = htons(8080);		 //給端口賦值,htons作用未知
inet_pton(AF_INET,"10.0.110.110",&server_addr.sin_addr.s_addr)  // 給ip地址賦值,inet_pton作用未知

接下來了解網絡編程中的字節序(大小端)、字節序轉換函數和地址轉換函數。
1.字節序
概念:多字節數據的存儲順序
分類:
(1)大端格式:將高位字節數據存儲在低位地址上
(2)小端格式:將低位字節數據存儲在低位地址上
字節序
特點
1、網絡協議指定了通訊字節序——大端
2、只有在多字節數據處理時才需要考慮字節序
3、運行在同一臺計算機上的進程相互通信時,一般不用考慮字節序
4、異構計算機之間通訊,需要轉換自己的字節序爲網絡字節序
確定主機的字節序程序。(瞭解)

#include <stdio.h>
union{
	short s;
	char c[sizeof(short)];
}un;  //公用同一塊空間

int main(int argc, const char *argv[])
{
	un.s =0x0102;
	if((un.c[0]==1)&&(un.c[1]==2))  
		printf("big-endian\n");
	if((un.c[0]==2)&&(un.c[1]==1))
		printf("little-endian\n");
	return 0;
}

2.字節序轉換函數
注意 : 在需要字節序轉換的時候一般調用特定字節序轉換函數。
(1)htonl 函數

uint32_t htonl(uint32_t hostint32);
功能:32位主機字節序數據轉換成網絡字節序數據
參數:
	@hostint32    :      待轉換的 32 位主機字節序數據
返回值:
	成功:返回網絡字節序的值  失敗:一般不失敗
注意:
	將主機字節序的IP地址轉換成網絡字節序的IP地址。(重點)
頭文件:
	#include <arpa/inet.h>

(2)htons 函數

uint16_t htons(uint16_t hostint16);
功能:16位主機字節序數據轉換成網絡字節序數據
參數:
	@hostint16    :    待轉換的 16 位主機字節序數據
返回值:
	成功:返回網絡字節序的值   失敗:一般不失敗
注意:
	將主機字節序的port端口號轉換成網絡字節序的port端口號(重點)
頭文件:
	#include <arpa/inet.h>

在上面給IPv4結構體變量賦值是用到的htons函數,應該就容易理解了。

(3)ntohl 函數

uint32_t ntohl(uint32_t netint32);
功能:32位網絡字節序數據轉換成主機字節序數據
參數:
	@netint32     :     待轉換的32位網絡字節序數據
返回值:
	成功:返回主機字節序的值
注意:
	將網絡字節序的IP地址轉換成主機字節序的IP(一般在對接收的數據分析時用來查看ip)
頭文件:
	#include <arpa/inet.h>

(4)ntohs 函數

uint16_t ntohs(uint16_t netint16);
功能:16位網絡字節序數據轉換成主機字節序數據
參數:
	@netint16     :       待轉換的16位網絡字節序數據
返回值:
	成功:返回主機字節序的值
注意:
	將網絡字節序的port端口號轉換成主機字節序的port端口號(一般在對接收的數據分析時用來查看ip)
頭文件:
	#include <arpa/inet.h>

3.地址轉換函數
在網絡通信中IP地址是32位,實際中是點分十進制數串(10.0.110.110直觀)。
(1)inet_pton 函數

字符串ip地址轉整型數據  (點分十進制數串 轉 32位網絡字節序IP)
int inet_pton(int family,const char *strptr, void *addrptr);
功能:將點分十進制數串轉換成32位無符號整數
參數:
	@family    :    協議族
	@strptr    :    點分十進制數串(:10.0.110.110)
	@addrptr   :    32位無符號整數的地址
返回值:
	成功:返回1      失敗:其它
頭文件:
	#include <arpa/inet.h>

在上面給IPv4結構體變量賦值是用到的inet_pton函數,應該就容易理解了。

(2)inet_ntop 函數

整型數據轉字符串格式ip地址   (32位網絡字節序IP 轉 點分十進制數串)
char *inet_ntop(int family, const void *addrptr,char *strptr, size_t len);
功能:32位無符號整數轉換成點分十進制數串
參數:
	family         :      協議族
	addrptr        :      32位無符號整數
	strptr         :      點分十進制數串
	len            :      strptr緩存區長度
						  #define INET_ADDRSTRLEN 16  //ipv4
						  #define INET6_ADDRSTRLEN 46 //ipv6
返回值:
	成功:則返回字符串的首地址      失敗:NULL
頭文件:
	#include <arpa/inet.h>

到這,可以說從TCP三次握手四次握手 、 TCP,UDP有關函數 到 網絡通信有關函數已經通了。可以自己寫個有關TCP或UDP通信程序了。

朋友,加油!點個關注…

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章