inet_ntop(), inet_pton() inet_ntoa(), inet_aton(), inet_addr, htons(), htonl(), ntohs(), ntohl() struct hostent ,struct sockaddr_in
http://xuxiaozhao163.blog.163.com/blog/static/3793592200810182506818/
#include <arpa/inet.h> const char *inet_ntop(int af, const void *src,char *dst, socklen_t size); int inet_pton(int af, const char *src, void *dst);
Example
// IPv4 demo of inet_ntop() and inet_pton() struct sockaddr_in sa; char str[INET_ADDRSTRLEN]; // store this IP address in sa: inet_pton(AF_INET, "192.0.2.33", &(sa.sin_addr)); // now get it back and print it inet_ntop(AF_INET, &(sa.sin_addr), str, INET_ADDRSTRLEN); printf("%s\n", str); // prints "192.0.2.33"
// IPv6 demo of inet_ntop() and inet_pton() // (basically the same except with a bunch of 6s thrown around) struct sockaddr_in6 sa; char str[INET6_ADDRSTRLEN]; // store this IP address in sa: inet_pton(AF_INET6, "2001:db8:8714:3a90::12", &(sa.sin6_addr)); // now get it back and print it inet_ntop(AF_INET6, &(sa.sin6_addr), str, INET6_ADDRSTRLEN); printf("%s\n", str); // prints "2001:db8:8714:3a90::12"
// Helper function you can use: //Convert a struct sockaddr address to a string, IPv4 and IPv6: char *get_ip_str(const struct sockaddr *sa, char *s, size_t maxlen) { switch(sa->sa_family) { case AF_INET: inet_ntop(AF_INET, &(((struct sockaddr_in *)sa)->sin_addr), s, maxlen); break; case AF_INET6: inet_ntop(AF_INET6, &(((struct sockaddr_in6 *)sa)->sin6_addr), s, maxlen); break; default: strncpy(s, "Unknown AF", maxlen); return NULL; } return s; }
inet_ntoa(), inet_aton(), inet_addr
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
// ALL THESE ARE DEPRECATED! Use inet_pton() or inet_ntop() instead!!
char *inet_ntoa(struct in_addr in);
int inet_aton(const char *cp, struct in_addr *inp);
in_addr_t inet_addr(const char *cp);
Example
struct sockaddr_in antelope; char *some_addr;
inet_aton("10.0.0.1", &antelope.sin_addr); // store IP in antelope
some_addr = inet_ntoa(antelope.sin_addr); // return the IP
printf("%s\n", some_addr); // prints "10.0.0.1"
// and this call is the same as the inet_aton() call, above:
antelope.sin_addr.s_addr = inet_addr("10.0.0.1");
htons(), htonl(), ntohs(), ntohl()
通过对大小端的存储原理分析可发现,对于 char 型数据,由于其只占一个字节,所以不存在这个问题,这也是一般情况下把数据缓冲区定义成 char 类型 的原因之一。对于 IP 地址、端口号等非 char 型数据,必须在数据发送到网络上之前将其转换成大端模式,在接收到数据之后再将其转换成符合接收端主机的存储模式。
Linux 系统为大小端模式的转换提供了 4 个函数,输入 man byteorder 命令可得函数原型:
#include <netinet/in.h>
uint32_t htonl(uint32_t hostlong); //host to network long
uint16_t htons(uint16_t hostshort); //host to network short
uint32_t ntohl(uint32_t netlong); //network to host long
uint16_t ntohs(uint16_t netshort);//network to host short
Example
uint32_t some_long = 10;
uint16_t some_short = 20;
uint32_t network_byte_order;
// convert and send
network_byte_order = htonl(some_long);
send(s, &network_byte_order, sizeof(uint32_t), 0);
some_short == ntohs(htons(some_short)); // this expression is true
用C语言写程序时需要知道是大端模式还是小端模式。
所谓的大端模式,是指数据的低位保存在内存的高地址中,而数据的高位,保存在内存的低地址中;
所谓的小端模式,是指数据的低位保存在内存的低地址中,而数据的高位保存在内存的高地址中。
为什么会有大小端模式之分呢?
这是因为在计算机系统中,我们是以字节为单位的,每个地址单元都对应着一个字节,一个字节为 8bit。但是在C语言中除了8bit的char之外,还有16bit的short型,32bit的long型(要看具体的编译器),另外,对于位数大于 8位的处理器,例如16位或者32位的处理器,由于寄存器宽度大于一个字节,那么必然存在着一个如果将多个字节安排的问题。因此就导致了大端存储模式和小端存储模式。例如一个16bit的short型x,在内存中的地址为0x0010,x的值为0x1122,那么0x11为高字节,0x22为低字节。对于大端模式,就将0x11放在低地址中,即0x0010中,0x22放在高地址中,即0x0011中。小端模式,刚好相反。我们常用的X86结构是小端模式,而KEIL C51则为大端模式。很多的ARM,DSP都为小端模式。有些ARM处理器还可以由硬件来选择是大端模式还是小端模式。
下面这段代码可以用来测试一下你的编译器是大端模式还是小端模式:
short int x;
char x0,x1;
x=0x1122;
x0=((char*)&x)[0]; //低地址单元
x1=((char*)&x)[1]; //高地址单元
若x0=0x11,则是大端; 若x0=0x22,则是小端......
完整C代码如下:
struct hostent结构体
struct hostent {
char *h_name;
char **h_aliases;
int h_addrtype;
int h_length;
char **h_addr_list;
};
struct hostent 数据结构的详细资料:
h_name – 地址的正式名称。
h_aliases – 空字节-地址的预备名称的指针。
h_addrtype –地址类型; 通常是AF_INET。
h_length – 地址的比特长度。
h_addr_list – 零字节-主机网络地址指针。网络字节顺序。
h_addr – h_addr_list中的第一地址。
printf("Host name : %s\n", h->h_name);
printf("IP Address : %s\n",inet_ntoa(*((struct in_addr *)h->h_addr)));
h->h_addr 是一个 char *, 但是 inet_ntoa() 需要的是 struct in_addr。因此,我转换 h->h_addr 成 struct in_addr *,然后得到数据。
struct sockaddr_in { short sin_family; // e.g. AF_INET, AF_INET6 unsigned short sin_port; // e.g. htons(3490) struct in_addr sin_addr; // see struct in_addr, below char sin_zero[8]; // zero this if you want to }; struct in_addr { unsigned long s_addr; // load with inet_pton() };