网络编程1
接下来网络编程模块使用的是Berkeley Socket库。
最早的网络是APPA。
socket库实现了内核协议栈(传输层、网络层、数据链路层、物理层),用户代码基于Socket库实现的是应用层,绝大数功能由操作系统内核协议栈完成。
描述主机地址
应用层需要的地址: ip + port
使用 man 7 ip 查看
现在存在的问题,不同的网络,设计的数据结构是不一样的。同样的功能,需要为不同的数据结构,设计多个函数。这种做法会产生大量冗余的代码。为了减少代码的重复,我们把ipv4、ipv6等各种各样的网络支持的数据类型叫做具体类型,从各个具体类型中提取出一个公共类型,所有的具体类型都可以转换成公共类型。所有的库函数实现一套,以公共类型为参数 ,在使用时,赋值使用具体,传参时强转成公共类型。
ipv4
sin_fimily :整数 一般填写AF_INET表明为ipv4
sin_port:16bit整数 网络字节序
sin_addr:ip地址 是一个结构体类型in_addr,这个结构体里面只有一个大端存储的32bit整数ip地址
存储方式和字节序
真值:人类能够直接理解的信息。
机器数:计算机能够存储和处理的数据,他是一串由0和1组成的序列。
编码:将真值和机器数相互转换。
内存按字节编址,对于超过一个字节的机器数,需要选择数据的存储方式。
- 小端方式:地位地址存储低位数据
- 大端方式:高位地址存储低位数据
主机字节序和网络字节序
网络字节序是大端方式。
主机字节序取决于硬件架构
- 小端:Intel/AMD x86
- 大端:PowerPC
- 既可以大端又可以小端: ARM
判断大小端
取出超过一字节数据,取第一个数据地址查看即可知道是大端还是小端
从小端转大端
man htons
h: host 主机
n:net 网络
l:long 32bit
s: short 16bit
用户在代码中写一个数据默认是小端方式。
头文件:
#include <arpa/inet.h>
点分十进制和二进制机器数互转
#include <sys/socket.h> #include <netinet/in.h>
man inet_addr
char * 字符串对应的是点分十进制 如“127.0.0.1”
struct in_addr : 二进制
有const 是传入参数,没有的是传出参数。
inet_aton()、inet_addr()是点分十进制转二进制,inet_ntoa()是二进制转点分十进制。
域名
1. 查hosts 文件 /etc/hosts
2. 查询DNS服务
3. 使用DNS服务命令
nsloopup <www.xxx.com>
域名解析
gethostbyname()根据域名获取ip
h_name 官方名
h_aliases 别名 ,char ** 这里是一个数组,每个char*指向一个字符串数组,以\0结尾
h_addr_list IP地址,char **应该是void **(它不是字符串数组,它是很多个32bit大端二进制地址的数组)
断网的时候不能使用,gethostbyname()函数需要使用DNS服务器。