inet_addr() inet_ntoa() 及其自實現函數self_inet_ntoa() 和 self_inet_addr() 筆記
#include <WINSOCK2.h>
#include <iostream>
#pragma comment(lib,"WS2_32.LIB")
using namespace std;
char *self_inet_ntoa(UINT in);
ULONG self_inet_addr(const char *str);
int main()
{
char *a1,*a2;
struct sockaddr_in ina1,ina2;
ina1.sin_addr.s_addr = inet_addr("192.168.1.1");//192+168*256+256*256+256*256*256 = 16885952
//ina1.sin_addr.s_addr = inet_addr("255.255.255.255");
ina2.sin_addr.s_addr = inet_addr("192.168.1.2");
cout <<"self_inet_ntoa:" << endl << self_inet_ntoa(ina1.sin_addr.s_addr) << endl;//[IP] unsigned long --> char *
a1 = inet_ntoa(ina1.sin_addr);
cout << "self_inet_addr:" << endl << self_inet_addr(a1) << endl;//[IP] char * -->unsigned long
a2 = inet_ntoa(ina2.sin_addr);
cout << a1 << endl;
cout << a2 << endl;
return 0;
}
char *self_inet_ntoa(UINT in) //unsigned long --> char *
{ //內存字節存放順序 192 168 1 1 小端模式下代表的整數就是 1,1,168,192 --> 192+168*256+256*256+256*256*256 = 16885952
char *output=new char[16];
cout << in << endl;
u_char *p=(u_char *)∈
for(int i = 0;i<4;i++)
cout << "p[" << i << "]: " << (UINT)p[i] << endl;
sprintf(output, "%d.%d.%d.%d", p[0], p[1], p[2], p[3]);//--------------------
return output;
}
ULONG self_inet_addr(const char *str)//char * -->unsigned long
{//此處忽略對不合法輸入的檢查
long a, b, c, d;
ULONG addr = 0;
sscanf(str, "%ld.%ld.%ld.%ld", &a, &b, &c, &d);//---------------------
//網絡字節順序:a b c d, 內存字節存放順序: a b c d, 對應的自然順序的整數爲 d c b a
addr |= d<<24;
addr |= c<<16;
addr |= b<<8;
addr |= a;
return addr;
}
/*
Note0:
inet_ntoa() struct in_addr型轉化爲字符串 (需要及時使用strcpy()函數將結果存放到自己的另外一個字符串中)
inet_addr() 字符串轉換爲長整型----(返回的已經是網絡字節順序)
-------------------------------------------------------------------------------------------------------------------------
Note1:
int main(int argc, char *argv[])
{
struct in_addr addr1,addr2;
ulong l1,l2;
l1= inet_addr("192.168.0.74");
l2 = inet_addr("211.100.21.179");
memcpy(&addr1, &l1, 4);
memcpy(&addr2, &l2, 4);
// -----printf()的本質是函數 在同一個函數裏後面的變量得到的調用innet_ntoa()函數的返回值會覆蓋前面一次的變量得到的調用innet_nota()函數的返回值
printf("%s : %s\n", inet_ntoa(addr1), inet_ntoa(addr2)); //注意這一句的運行結果
printf("%s\n", inet_ntoa(addr1));
printf("%s\n", inet_ntoa(addr2));
return 0;
}
實際運行結果如下:
192.168.0.74 : 192.168.0.74 //從這裏可以看出,printf裏的inet_ntoa(addr2)先於inet_ntoa(addr1)執行。
192.168.0.74
211.100.21.179
inet_ntoa返回一個char *,而這個char *的空間是在inet_ntoa裏面靜態分配的,所以inet_ntoa後面的調用會覆蓋上一次的調用。
第一句printf的結果只能說明在printf裏面的可變參數的求值是從右到左的,僅此而已
-------------------------------------------------------------------------------------------------------------------------
Note2:
sprintf()把格式化的數據寫入某個字符串中。
int main(){
charbuffer[50];//“字符”類型的數組,下面共有50個元素。
int n,a=5,b=3;//三個變量都爲“整數”類型,intn中間要有空格
n=sprintf(buffer,"%dplus%dis%d",a,b,a+b);//賦予數值
printf("[%s]isastring%dcharslong\n",buffer,n);/*“格式輸出”
return0;/*“返回零” 也就是程序正常退出}
}
輸出結果:
[5 plus 3 is 8] is a string 13 chars long
-------------------------------------------------------------------------------------------------------------------------
Note3:
sscanf() - 從一個字符串中讀進與指定格式相符的數據。
-------------------------------------------------------------------------------------------------------------------------
Note4:
inet_addr函數的實現
輸入是點分的IP地址格式(如A.B.C.D)的字符串,從該字符串中提取出每一部分,轉換爲ULONG,假設得到4個ULONG型的A,B,C,D,
ulAddress(ULONG型)是轉換後的結果,
ulAddress = D<<24 + C<<16 + B<<8 + A(網絡字節序),即inet_addr(const char *)的返回結果
另外,我們也可以得到把該IP轉換爲主機序的結果,轉換方法一樣
A<<24 + B<<16 + C<<8 + D [better]
*/