在上篇文章中我們提到了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通信程序了。
朋友,加油!點個關注…