日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Socket编程:必须要了解的网络字节序和转换函数

發(fā)布時間:2024/2/28 编程问答 35 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Socket编程:必须要了解的网络字节序和转换函数 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

目錄

主機字節(jié)序和網(wǎng)絡字節(jié)序

轉換函數(shù)

htonl 、htons 、ntohl 和 ntohs

inet_addr 、inet_aton 和 inet_ntoa

inet_pton?和 inet_ntop


主機字節(jié)序和網(wǎng)絡字節(jié)序

現(xiàn)代 CPU 的累加器一次能裝載至少 4 字節(jié),即一個整數(shù)。那么這 4個 字節(jié)在內存中的排列的順序將影響它被累加器裝載成的整數(shù)的值,這就是字節(jié)序問題。字節(jié)序分為大端字節(jié)序?(即大端模式,Big endian) 和?小端字節(jié)序?(即小端模式,Little endian)。

大端字節(jié)序:整數(shù)的高位字節(jié)存儲在內存的低地址處,低位字節(jié)存儲在內存的高地址處。

小端字節(jié)序:整數(shù)的高位字節(jié)存儲在內存的高地址處,而低位字節(jié)存儲在內存的低地址處。

以下兩種方法可以用來驗證你的 PC 是大端模式還是小端模式:

#include <iostream> #include <string> using namespace std;int main() {int as = 0x12345678;char *p =(char *) &as;if(*p == 0x12)cout << "Big-endian" <<endl;elsecout << "Little-endian" <<endl;union {short s;char c[sizeof(short)];} un;un.s = 0x0102;if (sizeof(short) == 2) {if (un.c[0] == 1 && un.c[1] == 2)printf("Big-endian\n");else if (un.c[0] == 2 && un.c[1] == 1)printf("Little-endian\n");elseprintf("unknown\n");} elseprintf("sizeof(short) = %d\n", sizeof(short));return 0; }

一個 32 位值的、4 字節(jié)以下順序傳輸:首先是0?- 7位然后是8?- 15位接著是16?-?23位最后是24 - 31位。這就是所謂的大端字節(jié)序它是 TCP/IP 頭部中所有二進制整數(shù)在網(wǎng)絡中傳輸時所需的字節(jié)順序它也被稱為網(wǎng)絡字節(jié)序。計算機的 CPU 使用其他格式存儲二進制整數(shù)例如大多數(shù) PC 使用小端字節(jié)序。

當格式化的數(shù)據(jù)在兩臺使用不同字節(jié)序的主機之間直接傳遞時,接收端按自己模式對數(shù)據(jù)進行提取或解釋時必然會導致錯誤。解決問題的方法是:發(fā)送端總是把要發(fā)送的數(shù)據(jù)轉化成大端模式數(shù)據(jù)后再發(fā)送,而接收段知道對方傳送過來的數(shù)據(jù)總是采用大端模式,所以接收段可以根據(jù)自身采用的模式?jīng)Q定是否對接收到的數(shù)據(jù)進行轉換。

注意:網(wǎng)絡字節(jié)序是 TCP/IP 中規(guī)定好的一種數(shù)據(jù)表示格式,它與具體的 CPU?類型、操作系統(tǒng)等無關,它保證數(shù)據(jù)在不同主機之間傳輸時能夠被正確解釋。

?

?

轉換函數(shù)

htonl 、htons 、ntohl 和 ntohs

Linux 提供了如下4個函數(shù)來完成主機字節(jié)序和網(wǎng)絡字節(jié)序之間的轉換:

頭文件#include <netinet/in.h> unsigned long int htonl ( unsigned long int hostlong ); htonl 把unsigned long int類型從主機序轉換到網(wǎng)絡序unsigned short int htons ( unsigned short int hostlong ); htons把unsigned short int類型從主機序轉換到網(wǎng)絡序unsigned long int ntohl ( unsigned long int netlong ); ntohl 把unsigned long int類型從網(wǎng)絡序轉換到主機序 unsigned short int ntohs ( unsigned short int netshort ); ntohs 把unsigned short int類型從網(wǎng)絡序轉換到主機序

在這 4 個函數(shù)中,長整型函數(shù)通常用來轉換 IP 地址,短整型函數(shù)用來轉換端口號。當然函數(shù)的使用不限于此,任何格式化的數(shù)據(jù)通過網(wǎng)絡傳輸時,都應該使用這些函數(shù)來轉換字節(jié)序。

?

inet_addr 、inet_aton 和 inet_ntoa

下面 3 個函數(shù)可用于將點分十進制字符串表示的 IPv4 地址和用網(wǎng)絡字節(jié)序整數(shù)表示的 IPv4 地址之間進行轉換,這里做一個簡單的介紹:

#include<arpa/inet.h> in_addr_t inet_addr( const char *strptr ); int inet_aton( const char * cp, struct in_addr* inp ); char * inet_ntoa( struct in_addr in );

inet_addr 函數(shù)將用點分十進制字符串表示的 IPv4 地址轉化為用網(wǎng)絡字節(jié)序整數(shù)表示的 IPv4 地址。它失敗時返回 INADDR_NONE。

inet_aton 函數(shù)完成和 inet_addr 同樣的功能,但是將轉化結果存儲于參數(shù) inp 指向的地址結構中。它成功返回 1 ,失敗返回 0。

inet_ntoa 函數(shù)將用網(wǎng)絡字節(jié)序整數(shù)表示的 IPv4 地址轉化為用點分十進制字符串表示的 IPv4 地址。但需要注意的是,該函數(shù)內部用一個靜態(tài)變量存儲轉化結果,函數(shù)的返回值指向該靜態(tài)內存,因此 inet_ntoa 是不可重入的。

?

inet_pton?和 inet_ntop

inet_pton?和 inet_ntop也能完成和前面 3 個函數(shù)同樣的功能,并且它們同時適用于 IPv4 地址和 IPv6 地址

#include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> int?inet_pton(int af, const char *src, void *dst);

inet_pton?函數(shù)將用字符串表示的 IP 地址 src 轉換成用網(wǎng)絡字節(jié)序整數(shù)表示的 IP 地址,即[點分十進制] -> [二進制整數(shù)]。并把轉換結果存儲于 dst 指向的內存中。

參數(shù)1:af 指定地址族,可以是 AF_INET 或 AF_INET6

參數(shù)2:src?是來源地址。

參數(shù)3:dst?接收轉換后的數(shù)據(jù)。

若成功,則返回1;如果函數(shù)出錯將返回一個負值,并將 errno 設置為 EAFNOSUPPORT;如果參數(shù) af 指定的地址族和?src 格式不對,函數(shù)將返回 0。

?

#include <sys/socket.h> #include <netinet/in.h> #include<arpa/inet.h> const?char *inet_ntop(int af, const void *src, char *dst, size_t len);

這 inet_ntop 函數(shù)將[二進制整數(shù)] -> [點分十進制]。

參數(shù)1:af?可以是 AF_INET 或 AF_INET6

參數(shù)2:src?是一個指向網(wǎng)絡字節(jié)序的二進制值的指針

參數(shù)3:dst?是一個指向轉換后的點分十進制串的指針

參數(shù)4:len?是目標的大小,以免函數(shù)溢出其調用者的緩沖區(qū)。

若成功則為指向結果的指針若出錯返回?NULL

#include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h>int main () {char IPdotdec[20]; //存放點分十進制IP地址struct in_addr s; //IPv4地址結構體//輸入IP地址printf("Please input IP address: ");scanf("%s", IPdotdec);//轉換inet_pton(AF_INET, IPdotdec, (void *)&s);printf("inet_pton: 0x%x\n", s.s_addr); //注意得到的字節(jié)序//反轉換inet_ntop(AF_INET, (void *)&s, IPdotdec, 16);printf("inet_ntop: %s\n", IPdotdec); }輸出: Please input IP address: 192.169.1.1 inet_pton: 0x101a9c0 inet_ntop: 192.169.1.1

?

?

參考:

百度百科:https://baike.baidu.com/item/inet_pton

https://blog.csdn.net/u010889616/article/details/47157637?utm_source=blogxgwz6

總結

以上是生活随笔為你收集整理的Socket编程:必须要了解的网络字节序和转换函数的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內容還不錯,歡迎將生活随笔推薦給好友。