Linux 网络编程详解一(IP套接字结构体、网络字节序,地址转换函数)
生活随笔
收集整理的這篇文章主要介紹了
Linux 网络编程详解一(IP套接字结构体、网络字节序,地址转换函数)
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
IPv4套接字地址結(jié)構(gòu)
struct sockaddr_in
{uint8_t sinlen;(4個字節(jié))sa_family_t sin_family;(4個字節(jié))in_port_t sin_port;(2個字節(jié))struct in_addr sin_addr;(4個字節(jié))char sin_zero[8];
};
sin_len:整個sockaddr_in結(jié)構(gòu)體的長度,部分Linux內(nèi)核版本沒有該成員
sin_family:指定該地址家族,一般設(shè)置為AF_INET(使用TCP,UDP協(xié)議)
sin_port:端口
sin_addr:IPv4的地址
sin_zero:暫不使用,一般將其設(shè)置為0通用地址結(jié)構(gòu)
struct sockaddr
{uint8_t sin_len;(4個字節(jié))sa_family_t sin_family;(4個字節(jié))char sa_data[14];
};
sin_len:整個sockaddr結(jié)構(gòu)的長度
sin_family:指定該地址家族
sa_data:由sin_family決定它的形式結(jié)論:struct sockaddr_in與struct sockaddr結(jié)構(gòu)大小相同 字節(jié)序
大端字節(jié)序
--最高有效位存儲與最低內(nèi)存地址處,最低有效位存儲于最高內(nèi)存地址處小端字節(jié)序
--最高有效位存儲于最高內(nèi)存地址處,最低有效位存儲于最低內(nèi)存地址處主機(jī)字節(jié)序
--不同主機(jī)有不同的字節(jié)序,如x86小端字節(jié)序,,Motorola 6800為大端字節(jié)序網(wǎng)絡(luò)字節(jié)序
--網(wǎng)絡(luò)字節(jié)序規(guī)定為大端字節(jié)序字節(jié)序說明:一個int類型變量254存儲在內(nèi)存中,如果變量的百位存儲于內(nèi)存地址條上的低地址處,
個位存儲于內(nèi)存地址條上的高地址處(即變量存儲序列和內(nèi)存地址序列相反)這就是大端字節(jié)序,反之則是小端字節(jié)序。
各個主機(jī)的字節(jié)序是不同的,但是在網(wǎng)絡(luò)中傳輸,必須要一個統(tǒng)一的字節(jié)序,這就是網(wǎng)絡(luò)字節(jié)序。 字節(jié)序轉(zhuǎn)換函數(shù) uint32_t htonl(uint32_t hostlong); uint16_t htons(uint16_t hostshort); uint32_t ntohl(uint32_t netlong); uint16_t ntohs(uint16_t netshort); 說明:在上述函數(shù)中,h代表host;n代表networks;s代表short;l代表long。 #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <errno.h> #include <sys/types.h> #include <arpa/inet.h>int main(int arg, char *args[]) {unsigned int data = 0x12345678;char *p = (char *)&data;printf("%x,%x,%x,%x\n", p[0], p[1], p[2], p[3]);/** 對于數(shù)組而言,內(nèi)存地址一定是遞增的,p[0]=*(p+0);p[1]=*(p+1);* 如果data變量的最低有效位處于p+0這個低內(nèi)存地址位,說明這是小端字節(jié)序* */if (p[0] == 0x78){printf("主機(jī)是小端字節(jié)序\n");} else{printf("主機(jī)是大端字節(jié)序\n");}//字節(jié)序轉(zhuǎn)換函數(shù)uint32_t ndata = htonl(data);p = (char *)&ndata;printf("%x,%x,%x,%x\n", p[0], p[1], p[2], p[3]);if (p[0] == 0x78){printf("網(wǎng)絡(luò)字節(jié)序是小端字節(jié)序\n");} else{printf("網(wǎng)絡(luò)字節(jié)序是大端字節(jié)序\n");}return 0; } 地址轉(zhuǎn)換函數(shù) typedef uint32_t in_addr_t; struct in_addr {in_addr_t s_addr; };int inet_aton(const char *p,struct in_addr *inp); 將點分十進(jìn)制(192.168.1.116)轉(zhuǎn)化成struct in_addrin_addr_t inet_addr(const char * cp); 將點分十進(jìn)制轉(zhuǎn)化成32bitchar *inet_ntoa(struct in_addr in);//注意:這里參數(shù)是結(jié)構(gòu)體變量,而非結(jié)構(gòu)體指針 將struct結(jié)構(gòu)體變量轉(zhuǎn)化成點分十進(jìn)制
inet_ntoa()返回值是char *,這個char *的內(nèi)存空間是在inet_ntoa()函數(shù)中靜態(tài)分配的,因此inet_ntoa()后面的調(diào)用會覆蓋上一次調(diào)用,inet_ntoa()是線程不安全函數(shù)。 套接字類型 1.流式套接字(SOCK_STREAM) --提供面向連接的,可靠的數(shù)據(jù)傳輸服務(wù),數(shù)據(jù)無差錯,無重復(fù)的發(fā)送,且按發(fā)送順序接收。 2.數(shù)據(jù)報式套接字(SOCK_DGRAM) --提供無連接服務(wù),不提供無錯保證,數(shù)據(jù)可能丟失或重復(fù),并且接收順序混亂。 3.原始套接字(SOCK_RAW)
個位存儲于內(nèi)存地址條上的高地址處(即變量存儲序列和內(nèi)存地址序列相反)這就是大端字節(jié)序,反之則是小端字節(jié)序。
各個主機(jī)的字節(jié)序是不同的,但是在網(wǎng)絡(luò)中傳輸,必須要一個統(tǒng)一的字節(jié)序,這就是網(wǎng)絡(luò)字節(jié)序。 字節(jié)序轉(zhuǎn)換函數(shù) uint32_t htonl(uint32_t hostlong); uint16_t htons(uint16_t hostshort); uint32_t ntohl(uint32_t netlong); uint16_t ntohs(uint16_t netshort); 說明:在上述函數(shù)中,h代表host;n代表networks;s代表short;l代表long。 #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <errno.h> #include <sys/types.h> #include <arpa/inet.h>int main(int arg, char *args[]) {unsigned int data = 0x12345678;char *p = (char *)&data;printf("%x,%x,%x,%x\n", p[0], p[1], p[2], p[3]);/** 對于數(shù)組而言,內(nèi)存地址一定是遞增的,p[0]=*(p+0);p[1]=*(p+1);* 如果data變量的最低有效位處于p+0這個低內(nèi)存地址位,說明這是小端字節(jié)序* */if (p[0] == 0x78){printf("主機(jī)是小端字節(jié)序\n");} else{printf("主機(jī)是大端字節(jié)序\n");}//字節(jié)序轉(zhuǎn)換函數(shù)uint32_t ndata = htonl(data);p = (char *)&ndata;printf("%x,%x,%x,%x\n", p[0], p[1], p[2], p[3]);if (p[0] == 0x78){printf("網(wǎng)絡(luò)字節(jié)序是小端字節(jié)序\n");} else{printf("網(wǎng)絡(luò)字節(jié)序是大端字節(jié)序\n");}return 0; } 地址轉(zhuǎn)換函數(shù) typedef uint32_t in_addr_t; struct in_addr {in_addr_t s_addr; };int inet_aton(const char *p,struct in_addr *inp); 將點分十進(jìn)制(192.168.1.116)轉(zhuǎn)化成struct in_addrin_addr_t inet_addr(const char * cp); 將點分十進(jìn)制轉(zhuǎn)化成32bitchar *inet_ntoa(struct in_addr in);//注意:這里參數(shù)是結(jié)構(gòu)體變量,而非結(jié)構(gòu)體指針 將struct結(jié)構(gòu)體變量轉(zhuǎn)化成點分十進(jìn)制
inet_ntoa()返回值是char *,這個char *的內(nèi)存空間是在inet_ntoa()函數(shù)中靜態(tài)分配的,因此inet_ntoa()后面的調(diào)用會覆蓋上一次調(diào)用,inet_ntoa()是線程不安全函數(shù)。 套接字類型 1.流式套接字(SOCK_STREAM) --提供面向連接的,可靠的數(shù)據(jù)傳輸服務(wù),數(shù)據(jù)無差錯,無重復(fù)的發(fā)送,且按發(fā)送順序接收。 2.數(shù)據(jù)報式套接字(SOCK_DGRAM) --提供無連接服務(wù),不提供無錯保證,數(shù)據(jù)可能丟失或重復(fù),并且接收順序混亂。 3.原始套接字(SOCK_RAW)
?
總結(jié)
以上是生活随笔為你收集整理的Linux 网络编程详解一(IP套接字结构体、网络字节序,地址转换函数)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: php 显示数据库操作错误,php操作m
- 下一篇: oracle 磁盘不分区吗,LINUX停