网络编程——sockaddr 与 sockaddr_in
struct sockaddr 這個結構體是linux的網(wǎng)絡編程接口中用來表示IP地址的標準結構體,bind、connect等函數(shù)中都需要這個結構體,這個結構體是兼容IPV4和IPV6的。
在實際編程中這個結構體會被一個struct sockaddr_in所填充。
sockaddr
用于存儲參與(IP)Windows套接字通信的計算機上的一個internet協(xié)議(IP)地址。為了統(tǒng)一地址結構的表示方法 ,統(tǒng)一接口函數(shù),使得不同的地址結構可以被bind()、connect()、recvfrom()、sendto()等函數(shù)調(diào)用。但一般的編程中并不直接對此數(shù)據(jù)結構進行操作,而使用另一個與之等價的數(shù)據(jù)結構sockaddr_in。這是由于Microsoft TCP/IP套接字開發(fā)人員的工具箱僅支持internet地址字段,而實際填充字段的每一部分則遵循sockaddr_in數(shù)據(jù)結構,兩者大小都是16字節(jié),所以二者之間可以進行切換。
sockaddr 在bind的man手冊中提到
struct sockaddr {sa_family_t sa_family; //所選協(xié)議族AF_INETchar sa_data[14]; //ip地址及端口號 } 說明: sa_family :是2字節(jié)的地址家族,一般都是“AF_xxx”的形式,它的值包括三種:AF_INET,AF_INET6和AF_UNSPEC。 如果指定AF_INET,那么函數(shù)就不能返回任何IPV6相關的地址信息;如果僅指定了AF_INET6,則就不能返回任何IPV4地址信息。 AF_UNSPEC則意味著函數(shù)返回的是適用于指定主機名和服務名且適合任何協(xié)議族的地址。如果某個主機既有AAAA記錄(IPV6)地址,同時又有A記錄(IPV4)地址,那么AAAA記錄將作為sockaddr_in6結構返回,而A記錄則作為sockaddr_in結構返回 通常用的都是AF_INET。而sockaddr_in
struct sockaddr_in {short int sin_family; /* Address family */unsigned short int sin_port; /* Port number */struct in_addr sin_addr; /* Internet address */unsigned char sin_zero[8]; /* Same size as struct sockaddr */};sin_family:指代協(xié)議族,在socket編程中只能是AF_INETsin_port:存儲端口號(使用網(wǎng)絡字節(jié)順序)sin_addr:存儲IP地址,使用in_addr這個數(shù)據(jù)結構sin_zero:是為了讓sockaddr與sockaddr_in兩個數(shù)據(jù)結構保持大小相同而保留的空字節(jié)。 而其中in_addr結構的定義如下: typedef struct in_addr {union {struct{ unsigned char s_b1,s_b2, s_b3,s_b4;} S_un_b;struct{ unsigned short s_w1, s_w2;} S_un_w;unsigned long S_addr;} S_un;} IN_ADDR; 闡述下in_addr的含義,很顯然它是一個存儲ip地址的共用體有三種表達方式: 第一種用四個字節(jié)來表示IP地址的四個數(shù)字; 第二種用兩個雙字節(jié)來表示IP地址; 第三種用一個長整型來表示IP地址。 給in_addr賦值的一種最簡單方法是使用inet_addr函數(shù),它可以把一個代表IP地址的字符串賦值轉換為in_addr類型,如addrto.sin_addr.s_addr=inet_addr("192.168.0.2"); 其反函數(shù)是inet_ntoa,可以把一個in_addr類型轉換為一個字符串。雖然是兩個結構體可是二者的占用的內(nèi)存是一致的,因此可以互相轉化。
sockaddr常用于bind、connect、recvfrom、sendto等函數(shù)的參數(shù),指明地址信息。是一種通用的套接字地址。
而sockaddr_in 一般是儲存地址和端口的。用于信息的顯示及存儲使用
例如:
struct sockaddr_in addr_server;addr_server.sin_family = AF_INET; addr_server.sin_port = htons(RPORT); addr_server.sin_addr.s_addr = inet_addr(RHOST);然而,在類似于bind accept的函數(shù)中
ret = bind(fd_sock, (struct sockaddr *)&addr_server, sizeof(addr_server)); if(ret < 0) {perror("bind");return -1; }之前只是這樣的記下來了,可是知道一天,想顯示所連接的客戶端的ip地址的時候,就發(fā)現(xiàn)了問題所在
char *inet_ntoa(struct in_addr in);函數(shù)原型是這樣的,可是在
struct in_addr {in_addr_t s_addr; };這個in_addr是sockaddr_in的一個mamber
fd_connection = accept(fd_sock, (struct sockaddr *)&addr_client, &addr_client_len);if(fd_connection < 0){perror("accept");return -1;}printf("connected! : %d\n", fd_connection);printf("%s%s\n", "the client ip is :", inet_ntoa(addr_client.sin_addr));
轉載于:https://www.cnblogs.com/wuyepeng/p/9721546.html
總結
以上是生活随笔為你收集整理的网络编程——sockaddr 与 sockaddr_in的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 现代软件工程 作业 第一周博客作业
- 下一篇: JQGrid 参数、属性API