Linux网络编程2——系统函数
socket信息数据结构
#include <netinet/in.h> struct sockaddr
{
unsigned short sa_family; /*地址族*/
char sa_data[14]; /*14字节的协议地址,包含该socket的IP地址和端口号。*/
};
struct sockaddr_in
{
short int sa_family; /*地址族*/
unsigned short int sin_port; /*端口号*/
struct in_addr sin_addr; /*IP地址*/
unsigned char sin_zero[8]; /*填充0 以保持与struct sockaddr同样大小*/
};
struct in_addr
{
unsigned long int s_addr; /* 32位IPv4地址,网络字节序 */
};
#include <netinet/in.h> tips
sa_family:
AF_INET -> IPv4协议
AF_INET6 -> IPv6协议
注意
结构体struct in_addr中存放的s_addr,是无符号整型数。实际上32位IPv4地址为点分十进制,每个字节的范围均为0-255,只要高字节大于等于128,那么这个整型数必然为负数,只不过我们这边仅仅关心ip每一位的存储情况,因此此处可以使用无符号数进行存储。
函数原型1
SYNOPSIS
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h> int inet_aton(const char *cp, struct in_addr *inp);/* 注意,参数inp为传出参数 */
char *inet_ntoa(struct in_addr in);
实际上,我们在上篇文章中实现的三个函数是有系统函数可以直接调用的。我们的my_atoh,my_hton合并为系统函数inet_aton,而my_ntoa即为系统函数inet_ntoa。
举例1
/*************************************************************************
> File Name: test.c
> Author: KrisChou
> Mail:zhoujx0219@163.com
> Created Time: Wed 27 Aug 2014 11:06:11 PM CST
************************************************************************/ #include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h> int main(int argc, char *argv[])
{
char ip_buf[] = "180.97.33.107";
struct in_addr my_addr;
inet_aton(ip_buf,&my_addr);
printf("ip : %s \n", ip_buf);
printf("net: %x \n", my_addr.s_addr);
return 0;
}
运行结果
[purple@localhost 0827]$ gcc -o test test.c -Wall
[purple@localhost 0827]$ ./test
ip : 180.97.33.107
net: 6b2161b4
照理,网络字节序是大端存储,应该返回0xb461216b。实际上调用系统函数inet_aton后,就直接在变量my_addr.s_addr的实际内存空间中以二进制形式写入了0xb461216b(其实用位运算,就可以直接操作二进制位,上篇博文有具体实现)。之所以运行结果是0x6b2161b4,是因为我们的主机是小端存储,用printf显示结果是先取低字节。
举例2
/*************************************************************************
> File Name: test1.c
> Author: KrisChou
> Mail:zhoujx0219@163.com
> Created Time: Wed 27 Aug 2014 11:43:26 PM CST
************************************************************************/ #include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h> int main(int argc, char *argv[])
{
struct in_addr my_addr;
my_addr.s_addr = 0xb461216b;
printf("net: %x \n", my_addr.s_addr);
printf("ip : %s \n", inet_ntoa(my_addr));
return 0;
}
运行结果
[purple@localhost 0827]$ gcc -o test1 test1.c -Wall
[purple@localhost 0827]$ ./test1
net: b461216b
ip : 107.33.97.180
照理,ip应该输出的是180.97.33.107。其实道理很简单,我们的主机是小端模式存储,而网络字节序是大端模式,当我们把0xb461216b赋值给my_addr.s_addr 时,实际上在内存中存储形式是0x6b2161b4,而inet_ntoa的具体实现时通过位运算直接操纵二进制位的,因此结果就自然输出107.33.97.180。
函数原型2
SYNOPSIS
#include <netdb.h>
struct hostent *gethostbyname(const char *name); The hostent structure is defined in <netdb.h> as follows: struct hostent {
char *h_name; /* official name of host */
char **h_aliases; /* alias list */
int h_addrtype; /* host address type */
int h_length; /* length of address */
char **h_addr_list; /* list of addresses */
}
#define h_addr h_addr_list[0] /* for backward compatibility */ The members of the hostent structure are: h_name The official name of the host. h_aliases
An array of alternative names for the host, terminated by a NULL
pointer. h_addrtype
The type of address; always AF_INET or AF_INET6 at present. h_length
The length of the address in bytes. h_addr_list
An array of pointers to network addresses for the host (in net-
work byte order), terminated by a NULL pointer. h_addr The first address in h_addr_list for backward compatibility.
代码
/*************************************************************************
> File Name: my_host.c
> Author: KrisChou
> Mail:zhoujx0219@163.com
> Created Time: Wed 27 Aug 2014 05:22:46 PM CST
************************************************************************/ #include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
int main(int argc, char* argv[])// exe hostname
{
struct hostent* p ;
p = gethostbyname(argv[1]) ;
/*
struct hostent {
char *h_name;
char **h_aliases;
int h_addrtype;
int h_length;
char **h_addr_list;
}
#define h_addr h_addr_list[0]
*/
printf("host name: %s \n", p ->h_name); int index ;
char** pp = p -> h_aliases ;
for(index = 0 ; pp[index] != NULL; index ++ )
{
printf("alias : %s \n", pp[index]);
} printf("ip type : %d\n", p ->h_addrtype); printf("addr len : %d \n", p ->h_length); pp = p ->h_addr_list ;
for(index = 0; pp[index] != NULL ; index ++)
{
/* 由于h_addr_list是一个字符串指针数组,数组中存放的指针指向一个网络字节序
但是系统函数inet_ntoa需要传入的参数是一个结构体,因此需要进行转换。
pp[index]是一个char*类型的指针,先将其转换为struct in_addr*类型的指针,
接着去引用,即得到结构体。 */
printf("ip : %s \n", inet_ntoa( *(struct in_addr *)pp[index] ) );
} return 0 ;
}
运行结果
[purple@localhost 0827]$ gcc -o myhost my_host.c -Wall
[purple@localhost 0827]$ ./myhost www.baidu.com
host name: www.a.shifen.com
alias : www.baidu.com
ip type : 2
addr len : 4
ip : 180.97.33.107
ip : 180.97.33.108
干货
某年腾讯面试题:
#include <stdio.h>
#include <stdlib.h>
int main()
{
int a = 0x61;//97
printf("%x\n",(char*)(&a)[0]);
}
结果输出61,说明是小端机,先存低字节。
总结
切记系统函数无论inet_aton还是inet_ntoa,都是直接以位运算形式实现的,因此其关注的是数据在内存中实际的二进制存储形式。
Linux网络编程2——系统函数的更多相关文章
- Linux 网络编程 入门-常用函数
网络连接无外乎服务器和客户端两方面的编程. 对于服务器大致的流程是:1---调用socket函数创建套接字 2---调用bind函数分配IP地址和端口号 3---调用listsen函数将套接字转为可接 ...
- linux网络编程:splice函数和tee( )函数高效的零拷贝
splice( )函数 在两个文件描述符之间移动数据,同sendfile( )函数一样,也是零拷贝. 函数原型: #include <fcntl.h> ssize_t splice(int ...
- linux网络编程:select()函数以及FD_ZERO、FD_SET、FD_CLR、FD_ISSET(转)
从别人的博客中转载过来了这一篇文章,经过重新编辑排版之后展现于此,做一个知识点保存与学习. select函数用于在非阻塞中,当一个套接字或一组套接字有信号时通知你,系统提供select函数来实现多路复 ...
- linux网络编程涉及的函数
常用的网络命令: netstat 命令netstat是用来显示网络的连接,路由表和接口统计等网络的信息. netstat有许多的选项我们常用的选项是-an用来显示详细的网络状态.至于其它选项我们使用帮 ...
- linux网络编程、系统编程
http://blog.csdn.net/lianghe_work/article/category/2871247
- linux 网络编程 inet_pton & inet_ntop函数
#include <arpa/inet.h> int inet_pton(int family,const char * strptr,void * addrptr); 返回:--成功, ...
- linux网络编程九:splice函数,高效的零拷贝
from:http://blog.csdn.net/jasonliuvip/article/details/22600569 linux网络编程九:splice函数,高效的零拷贝 最近在看<Li ...
- linux c编程调用系统的动态库时,要使用dlopen等函数吗?
同问 linux c编程调用系统的动态库时,要使用dlopen等函数吗? 2012-11-27 21:55 提问者: hnwlxyzhl 我来帮他解答 满意回答 2012-12-07 09:08 li ...
- 【深入浅出Linux网络编程】 "开篇 -- 知其然,知其所以然"
[深入浅出Linux网络编程]是一个连载博客,内容源于本人的工作经验,旨在给读者提供靠谱高效的学习途径,不必在零散的互联网资源中浪费精力,快速的掌握Linux网络编程. 连载包含4篇,会陆续编写发出, ...
随机推荐
- C# 执行Cmd窗口中的命令 [复制文件实例]
/// <summary> /// 复制文件夹 /// </summary> /// <param name="sCmd"></param ...
- web安全之token
Token,就是令牌,最大的特点就是随机性,不可预测.一般黑客或软件无法猜测出来. 那么,Token有什么作用?又是什么原理呢? Token一般用在两个地方: 1)防止表单重复提交. 2)anti c ...
- C#泛型集合之Dictionary<k, v>使用技巧
1.要使用Dictionary集合,需要导入C#泛型命名空间 System.Collections.Generic(程序集:mscorlib) 2.描述 1).从一组键(Key)到一组值(Value) ...
- Labview实现脉波调制( PAM )
Labview实现脉波调制( PAM ) 根据定义为脉冲振幅调制 生成一个正弦信号,得到其幅值输入给一个方波信号的幅值 这个等价于一个方波信号和一个正弦信号相乘 得到的PAM信号通过观察其频率可以发现 ...
- [shell基础]——paste命令
测试文本内容如下: # cat name1.txt name1 alvin1 name2 alvin2 name3 alvin3 name4 alvin4 # cat name2.txt name1 ...
- 论单页Web应用和RESTful架构
单页Web应用 概述 单页Web应用并不是突然诞生的一门新技术,而是web展示的一种新的尝试.它将所有的动作局限于一个Web页面,在加载站点首页的时候就加载站点需要的JavaScript和CSS.单页 ...
- JQuery 对 Select option 的操作---转载
<select id="selectID" > <option value="1">1</option> <optio ...
- hibernate 超级牛x的公共类
想法,能支持in查询和 =查询的 公共方法,类似下面实现 用 泛型 实现 参数 getList(String[] params,Object[] values){} for(int i=0;i< ...
- 团队项目NABC分析
我们的团队项目是“来用”实用工具集合软件,我针对我们项目功能丰富的特点进行NABC分析. N (Need 需求):我们的软件正是从最大程度上满足用户需求出发,因为软件集合了不同种类的功能,可以满足用户 ...
- 搭建SpringMVC+MyBatis开发框架三
新增spingmvc.xml配置 在WEB-INF下新增spingmvc.xml,主要是配置spring扫描的包:  <?xml version="1.0" encodin ...