socket编程--sockaddr_in结构体操作
sockaddr結構體
sockaddr的缺陷: struct sockaddr是一個通用地址結構,這是為了統一地址結構的表示方法,統一接口函數,使不同的地址結構可以被bind(),connect()等函數調用;sa_data把目標地址和端口信息混在一起了
| struct sockaddr { ? ?????unsigned short sa_family; char sa_data[14];?????????????????? };? |
| sa_family是通信類型,最常用的值是 "AF_INET" sa_data14字節,包含套接字中的目標地址和端口信息 |
sockaddr_in結構體: struct sockaddr_in中的in表示internet,就是網絡地址,這只是我們比較常用的地址結構,屬于AF_INET地址族,它非常的常用。
sockaddr_in結構體解決了sockaddr的缺陷,把port和addr分開儲存在兩個變量中
| struct sockaddr_in {? short int sin_family; unsigned short int sin_port;? ?????struct in_addr sin_addr;
?????unsigned char sin_zero[8]; }??? |
sin_port和sin_addr都必須是NBO,一般可視化的數字都是HBO(本機字節順序)
sin_zero初始值應該使用函數bzero()來全部置零。
一般采用下面語句
| struct sockaddr_in cliaddr; bzero(&cliaddr,sizeof(cliaddr)); |
?sockaddr_in結構體變量的基本配置
| struct sockaddr_in ina; |
sockaddr和sockaddr_in的相互關系,一般先把sockaddr_in變量賦值后,強制類型轉換后傳入用sockaddr做參數的函數。
1.sockaddr_in用于socket定義和賦值。
2.sockaddr用于函數參數
最典型的源、目的節點socket定義,對于源、目的地址和源、目的地址端口,需要建立兩個socket變量,cliaddr綁定源地址和源端口,servaddr用于connect和sendto的設定目的地址和目的端口。
struct sockaddr_in servaddr,cliaddr;create_socket(char *server_addr_string, unsigned int server_port) {//源socket賦值bzero(&cliaddr, sizeof(cliaddr));cliaddr.sin_family = AF_INET;//通常TCP/UDP協議源地址和端口都是隨機的cliaddr.sin_addr.s_addr = htons(INADDR_ANY);cliaddr.sin_port = htons(0);//目的socket賦值bzero(&servaddr, sizeof(servaddr));servaddr.sin_family = AF_INET;inet_aton(server_addr_string, &servaddr.sin_addr);servaddr.sin_port = htons(server_port); }網絡字節順序(Network Byte Order) NBO結構體的sin_port和sin_addr都必須是NBO
本機字節順序(Host Byte Order) HBO一般可視化的數字都是HBO
NBO,HBO二者轉換
inet_addr() 將字符串點數格式地址轉化成無符號長整型(unsigned long s_addr s_addr;)
inet_aton() 將字符串點數地址轉化成NBO
inet_ntoa() 將NBO地址轉化成字符串點數格式
htons() "Host to Network Short"
htonl() "Host to Network Long"
ntohs() "Network to Host Short"
ntohl() "Network to Host Long"
常用的是htons(),inet_addr()正好對應結構體的端口類型和地址類型
三種給socket賦值地址的方法
inet_aton(server_addr_string, &myaddr.sin_addr); myaddr.sin_addr.s_addr = inet_addr("132.241.5.10"); INADDR_ANY轉不轉NBO隨便 myaddr.sin_addr.s_addr = htons(INADDR_ANY); myaddr.sin_addr.s_addr = INADDR_ANY;另種給socket賦值端口的方法
#define MYPORT 3490 myaddr.sin_port = htons(MYPORT); 0(隨機端口)轉不轉NBO隨便 myaddr.sin_port = htons(0); myaddr.sin_port = 0;htons/l和ntohs/l等數字轉換都不能用于地址轉換,因為地址都是點數格式,所以地址只能采用數字/字符串轉換如inet_aton,inet_ntoa;唯一可以用于地址轉換的htons是針對INADDR_ANY
cliaddr.sin_addr.s_addr = htons(INADDR_ANY)
inet_addr()與inet_aton()的區別
inet_addr()是返回值型
struct sockaddr_in ina;
ina.sin_addr.s_addr = inet_addr("132.241.5.10");
inet_aton()是參數指針型
struct sockaddr_in ina;
inet_aton("132.241.5.10", &ina.sin_addr);
inet_ntoa將NBO地址轉化成字符串點數格式
參數:結構體變量.sinaddr
返回值:字符串指針
a1 = inet_ntoa(ina.sin_addr);
printf("address 1: %s\n", a1);
address 1:132.241.5.10
inet_addr()的缺陷:比如對-1做檢測處理
因為inet_addr()的結果是整型,而發生錯誤時返回-1.
而ina.sin_addr.s_addr是Unsigned long 型,
-1在long short顯示成111111111,和IP地址255.255.255.255相符合!會被誤認廣播地址!
總結
以上是生活随笔為你收集整理的socket编程--sockaddr_in结构体操作的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: web安全攻防从入门到放弃-记录
- 下一篇: nginx服务器的文件大小的限制解决方法