socket信息数据结构

  1. #include <netinet/in.h>
  2.  
  3. struct sockaddr
  4. {
  5. unsigned short sa_family; /*地址族*/
  6. char sa_data[14]; /*14字节的协议地址,包含该socket的IP地址和端口号。*/
  7. };
  8. struct sockaddr_in
  9. {
  10. short int sa_family; /*地址族*/
  11. unsigned short int sin_port; /*端口号*/
  12. struct in_addr sin_addr; /*IP地址*/
  13. unsigned char sin_zero[8]; /*填充0 以保持与struct sockaddr同样大小*/
  14. };
  15. struct in_addr
  16. {
  17. unsigned long int s_addr; /* 32位IPv4地址,网络字节序 */
  18. };
  19. #include <netinet/in.h>
  20.  
  21. tips
  1. sa_family:
  2. AF_INET -> IPv4协议
  3. AF_INET6 -> IPv6协议

注意

  1. 结构体struct in_addr中存放的s_addr,是无符号整型数。实际上32IPv4地址为点分十进制,每个字节的范围均为0-255,只要高字节大于等于128,那么这个整型数必然为负数,只不过我们这边仅仅关心ip每一位的存储情况,因此此处可以使用无符号数进行存储。

函数原型1

  1. SYNOPSIS
  2. #include <sys/socket.h>
  3. #include <netinet/in.h>
  4. #include <arpa/inet.h>
  5.  
  6. int inet_aton(const char *cp, struct in_addr *inp);/* 注意,参数inp为传出参数 */
  7. char *inet_ntoa(struct in_addr in);
  1. 实际上,我们在上篇文章中实现的三个函数是有系统函数可以直接调用的。我们的my_atoh,my_hton合并为系统函数inet_aton,而my_ntoa即为系统函数inet_ntoa

举例1

  1. /*************************************************************************
  2. > File Name: test.c
  3. > Author: KrisChou
  4. > Mail:zhoujx0219@163.com
  5. > Created Time: Wed 27 Aug 2014 11:06:11 PM CST
  6. ************************************************************************/
  7.  
  8. #include <stdio.h>
  9. #include <sys/socket.h>
  10. #include <netinet/in.h>
  11. #include <arpa/inet.h>
  12.  
  13. int main(int argc, char *argv[])
  14. {
  15. char ip_buf[] = "180.97.33.107";
  16. struct in_addr my_addr;
  17. inet_aton(ip_buf,&my_addr);
  18. printf("ip : %s \n", ip_buf);
  19. printf("net: %x \n", my_addr.s_addr);
  20. return 0;
  21. }

运行结果

  1. [purple@localhost 0827]$ gcc -o test test.c -Wall
  2. [purple@localhost 0827]$ ./test
  3. ip : 180.97.33.107
  4. net: 6b2161b4
  1. 照理,网络字节序是大端存储,应该返回0xb461216b。实际上调用系统函数inet_aton后,就直接在变量my_addr.s_addr的实际内存空间中以二进制形式写入了0xb461216b(其实用位运算,就可以直接操作二进制位,上篇博文有具体实现)。之所以运行结果是0x6b2161b4,是因为我们的主机是小端存储,用printf显示结果是先取低字节。

举例2

  1. /*************************************************************************
  2. > File Name: test1.c
  3. > Author: KrisChou
  4. > Mail:zhoujx0219@163.com
  5. > Created Time: Wed 27 Aug 2014 11:43:26 PM CST
  6. ************************************************************************/
  7.  
  8. #include <stdio.h>
  9. #include <sys/socket.h>
  10. #include <netinet/in.h>
  11. #include <arpa/inet.h>
  12.  
  13. int main(int argc, char *argv[])
  14. {
  15. struct in_addr my_addr;
  16. my_addr.s_addr = 0xb461216b;
  17. printf("net: %x \n", my_addr.s_addr);
  18. printf("ip : %s \n", inet_ntoa(my_addr));
  19. return 0;
  20. }
  1. 运行结果
  1. [purple@localhost 0827]$ gcc -o test1 test1.c -Wall
  2. [purple@localhost 0827]$ ./test1
  3. net: b461216b
  4. ip : 107.33.97.180
  1. 照理,ip应该输出的是180.97.33.107。其实道理很简单,我们的主机是小端模式存储,而网络字节序是大端模式,当我们把0xb461216b赋值给my_addr.s_addr 时,实际上在内存中存储形式是0x6b2161b4,而inet_ntoa的具体实现时通过位运算直接操纵二进制位的,因此结果就自然输出107.33.97.180

函数原型2

  1. SYNOPSIS
  2. #include <netdb.h>
  3. struct hostent *gethostbyname(const char *name);
  4.  
  5. The hostent structure is defined in <netdb.h> as follows:
  6.  
  7. struct hostent {
  8. char *h_name; /* official name of host */
  9. char **h_aliases; /* alias list */
  10. int h_addrtype; /* host address type */
  11. int h_length; /* length of address */
  12. char **h_addr_list; /* list of addresses */
  13. }
  14. #define h_addr h_addr_list[0] /* for backward compatibility */
  15.  
  16. The members of the hostent structure are:
  17.  
  18. h_name The official name of the host.
  19.  
  20. h_aliases
  21. An array of alternative names for the host, terminated by a NULL
  22. pointer.
  23.  
  24. h_addrtype
  25. The type of address; always AF_INET or AF_INET6 at present.
  26.  
  27. h_length
  28. The length of the address in bytes.
  29.  
  30. h_addr_list
  31. An array of pointers to network addresses for the host (in net-
  32. work byte order), terminated by a NULL pointer.
  33.  
  34. h_addr The first address in h_addr_list for backward compatibility.

代码

  1. /*************************************************************************
  2. > File Name: my_host.c
  3. > Author: KrisChou
  4. > Mail:zhoujx0219@163.com
  5. > Created Time: Wed 27 Aug 2014 05:22:46 PM CST
  6. ************************************************************************/
  7.  
  8. #include <stdio.h>
  9. #include <sys/socket.h>
  10. #include <netinet/in.h>
  11. #include <arpa/inet.h>
  12. #include <netdb.h>
  13. int main(int argc, char* argv[])// exe hostname
  14. {
  15. struct hostent* p ;
  16. p = gethostbyname(argv[1]) ;
  17. /*
  18. struct hostent {
  19. char *h_name;
  20. char **h_aliases;
  21. int h_addrtype;
  22. int h_length;
  23. char **h_addr_list;
  24. }
  25. #define h_addr h_addr_list[0]
  26. */
  27. printf("host name: %s \n", p ->h_name);
  28.  
  29. int index ;
  30. char** pp = p -> h_aliases ;
  31. for(index = 0 ; pp[index] != NULL; index ++ )
  32. {
  33. printf("alias : %s \n", pp[index]);
  34. }
  35.  
  36. printf("ip type : %d\n", p ->h_addrtype);
  37.  
  38. printf("addr len : %d \n", p ->h_length);
  39.  
  40. pp = p ->h_addr_list ;
  41. for(index = 0; pp[index] != NULL ; index ++)
  42. {
  43. /* 由于h_addr_list是一个字符串指针数组,数组中存放的指针指向一个网络字节序
  44. 但是系统函数inet_ntoa需要传入的参数是一个结构体,因此需要进行转换。
  45. pp[index]是一个char*类型的指针,先将其转换为struct in_addr*类型的指针,
  46. 接着去引用,即得到结构体。 */
  47. printf("ip : %s \n", inet_ntoa( *(struct in_addr *)pp[index] ) );
  48. }
  49.  
  50. return 0 ;
  51. }
  1. 运行结果
  1. [purple@localhost 0827]$ gcc -o myhost my_host.c -Wall
  2. [purple@localhost 0827]$ ./myhost www.baidu.com
  3. host name: www.a.shifen.com
  4. alias : www.baidu.com
  5. ip type : 2
  6. addr len : 4
  7. ip : 180.97.33.107
  8. ip : 180.97.33.108

干货

某年腾讯面试题:

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. int main()
  4. {
  5. int a = 0x61;//97
  6. printf("%x\n",(char*)(&a)[0]);
  7. }

结果输出61,说明是小端机,先存低字节。

总结

切记系统函数无论inet_aton还是inet_ntoa,都是直接以位运算形式实现的,因此其关注的是数据在内存中实际的二进制存储形式。

Linux网络编程2——系统函数的更多相关文章

  1. Linux 网络编程 入门-常用函数

    网络连接无外乎服务器和客户端两方面的编程. 对于服务器大致的流程是:1---调用socket函数创建套接字 2---调用bind函数分配IP地址和端口号 3---调用listsen函数将套接字转为可接 ...

  2. linux网络编程:splice函数和tee( )函数高效的零拷贝

    splice( )函数 在两个文件描述符之间移动数据,同sendfile( )函数一样,也是零拷贝. 函数原型: #include <fcntl.h> ssize_t splice(int ...

  3. linux网络编程:select()函数以及FD_ZERO、FD_SET、FD_CLR、FD_ISSET(转)

    从别人的博客中转载过来了这一篇文章,经过重新编辑排版之后展现于此,做一个知识点保存与学习. select函数用于在非阻塞中,当一个套接字或一组套接字有信号时通知你,系统提供select函数来实现多路复 ...

  4. linux网络编程涉及的函数

    常用的网络命令: netstat 命令netstat是用来显示网络的连接,路由表和接口统计等网络的信息. netstat有许多的选项我们常用的选项是-an用来显示详细的网络状态.至于其它选项我们使用帮 ...

  5. linux网络编程、系统编程

    http://blog.csdn.net/lianghe_work/article/category/2871247

  6. linux 网络编程 inet_pton & inet_ntop函数

    #include <arpa/inet.h> int inet_pton(int family,const char * strptr,void * addrptr); 返回:--成功, ...

  7. linux网络编程九:splice函数,高效的零拷贝

    from:http://blog.csdn.net/jasonliuvip/article/details/22600569 linux网络编程九:splice函数,高效的零拷贝 最近在看<Li ...

  8. linux c编程调用系统的动态库时,要使用dlopen等函数吗?

    同问 linux c编程调用系统的动态库时,要使用dlopen等函数吗? 2012-11-27 21:55 提问者: hnwlxyzhl 我来帮他解答 满意回答 2012-12-07 09:08 li ...

  9. 【深入浅出Linux网络编程】 "开篇 -- 知其然,知其所以然"

    [深入浅出Linux网络编程]是一个连载博客,内容源于本人的工作经验,旨在给读者提供靠谱高效的学习途径,不必在零散的互联网资源中浪费精力,快速的掌握Linux网络编程. 连载包含4篇,会陆续编写发出, ...

随机推荐

  1. C#.Net 图片处理大全

    C# How to: Image filtering by directly manipulating Pixel ARGB values C# How to: Image filtering imp ...

  2. MongoDB学习笔记-数据库命令

    概念 数据库命令(database command)是一种非常特殊类型的查询.文档的创建.更新.删除及查询都属于数据库命令的范畴,它还包含管理性的任务(比如关闭服务器和克隆数据库).统计数据及执行聚合 ...

  3. ubuntu 修改主机名

    sudo gedit /etc/hostname sudo gedit /etc/hosts

  4. ASCII码排序

    ASCII码排序 时间限制:3000 ms  |  内存限制:65535 KB 难度:2   描述 输入三个字符(可以重复)后,按各字符的ASCII码从小到大的顺序输出这三个字符.   输入 第一行输 ...

  5. How to check if NSString begins with a certain character

    How to check if NSString begins with a certain character How do you check if an NSString begins with ...

  6. Facebook Graph API 接口请求

    Graph API 调试器 这两天因项目需求,在调试FB的接口.项目的应用在FB上面.L特傻.没有区分FB的api的使用方式. 因为应用是在FB上面的.所以在登录应用的时候,就已经登录了FB平台.对于 ...

  7. mysql 存储过程 -- 游标的使用(备忘)

    BEGIN ; DECLARE f_ratio FLOAT DEFAULT 0.8; ); ); DECLARE i_statDate DATE; DECLARE i_accumulateCount ...

  8. 原生javascript开发仿微信打飞机小游戏

    今天闲来无事,于是就打算教一个初学javascript的女童鞋写点东西,因此为了兼顾趣味性与简易程度,果断想到了微信的打飞机小游戏.. 本来想用html5做的,但是毕竟人家才初学,连jquery都还不 ...

  9. CSS3 绘制360安仔小精灵[原创]

    Css3图形通常由矩形,圆形,椭圆,三角形,梯形等组合而成. 矩形,为display:block的块级元素设定宽高,便能实现, 圆角矩形,椭圆,圆形,则通过border-radius 属性来得到. 圆 ...

  10. 使用sqlserver日期函数获取当前日期

    使用sqlserver日期函数中的getdate()可以获取当现的日期,下面就将为您介绍这种使用sqlserver日期函数获取当前日期的方法,供您参考,希望对您学习sqlserver日期函数有所启迪. ...