网络编程知识基础
8.1
进程间通讯,经过发展,最后迎来了一个新的阶段——网络通讯
网络通讯其实是网络域套接字通信(socket)
即位于两个不同主机上的,2个进程之间的 通信
上 api
中 网卡驱动
下 网卡
学Linux的网络编程三个层次:
1 低级:直接基于socket编程,比较难,要设置的东西是很多的
2 高级:基于网络通信应用框架,封装使得编程更简单
3 更高级:基于http和网络控件的傻瓜式编程。
我们在这里学的是第一种,较为困难的编程,因为这种编程是无限可能的
8.2
网络发展史
单机阶段 1960’
主机是一个大设备,外接打字机和键盘就可以构成一个终端。
因为当时计算机很少,根本没有通讯的需求,所以多个终端就是当时的终极目标
打字机+键盘构成的终端,当时称作“telleytype”,简称TTY,这个简写沿用至今
局域网阶段
开始研究多个主机间的通讯问题
最早用的是串行口,但是有个问题是速度低而且不易组网,于是后来发明了集线器
广域网阶段
局域网与局域网之间的通讯
移动互联网阶段
1997’ - 现在
2015年开始进入成熟阶段,相关工作要求变高,职位变少
物联网阶段
即将到来的万物相连阶段
三大网络:电信网,电视网络,互联网
趋势:互联网将慢慢取代其他网络
网络通讯的媒介
有线:双绞线,同轴电缆,光纤
无线:wifi,GPRS,3G/4G/5G,华为把5G搞出来了,另外还有半死不活的zigbee
8.3 网络设备
1 网卡
这个一个可以集成,也可以扩展的模块,作用就是上网=v=
1 连接外部网络
2 串转并
3 封包与拆包
4 网络数据缓存 和 速率适配
2 集线器hub
1 信号的中继放大,避免信号衰减
2 局域网组网,以广播方式工作
但注意:不可以连接外网
3 交换机
高级集线器,广播方式发生改变,不再像集线器一样挨个发,而是根据ip地址进行判断
4 路由器
局域网和外网连接的接口,连接多个不同网段的设备,类似网关
他的核心功能就是提供外网
路由器由于是内部局域网、外部广域网的接口,所以他配备了2个网卡,一个用做网关,一个用做节点
对内:连接外网
对外:划分子网,DHCP服务
关于DNS服务:域名解析服务
域名:www.kkqqq.com 即是ip地址的别名。
DNS提供域名和ip地址之间的转换服务,所以域名是需要购买的。
8.5 DHCP 和 NAT
DHCP动态主机配置协议
IP地址可以静态设定,也可以动态分配
动态分配是局域网内DHCP服务器提供的,路由器就有这个功能
我记得理工大学的andbusiness就有一个DHCP由于手机设备太多导致连不上网的问题,这个问题的解决方法就是使用静态IP,这样一来就不使用自动分配的IP地址。
DHCP的优点:方便接入和断开,有限的IP地址得到充分利用。
NAT网络地址转换协议
IP地址分为公网地址和私网地址
局域网内主机向外网发送数据包时,路由器将局域网主机的内网IP替换为外网IP,这个过程就叫NAT
他是一种给ipv4打补丁的方法,最终解决ip不够的话还是要看ipv6。
NAT穿透
NAT就像一堵墙,192.168.2.1和另一个局域网的192.168.2.1不能直接相连
迅雷是一种点对点(P2P)的下载方式
我们下载的资源其实是从周围的、距离我们较近的其他有这个资源的电脑上获取的
资源下载时候的32/267 32代表我们实际连接上的资源,267是总资源
要想实现P2P,那么就需要NAT穿透。
服务器帮我们做了中介,帮我们打通了NAT的墙,这个技术就是NAT穿透
8.6 IP
ip在人机交互时候是点分十进制的,实际上是int型的
0xC0A80166 32位二进制方式
192.168.2.1 点分十进制
转换过程中有一些api,专门用来做显示转换。
一台主机包含在一个网络中的,找到这个主机要先找到他所在的网络
IP地址 = 网络地址 + 主机地址
譬如可以
8位表示网络,24位表示主机地址
16位表示网路,16位表示主机地址
表示网络部分、主机部分各自占多少位,要看子网掩码。子网掩码为1的位代表网络地址
子网掩码255 255 255 0时,代表前24位是网络地址,后8位是主机地址
常见的IP地址
A类
B类
C类
特殊IP地址:
127.0.0.0 用来做回环测试:网卡自己发自己收,测试网卡设备是否可用
区别就是网络地址和主机地址所占长度不同
如何判断两个ip地址是否在同一个子网内?
网络标识 = IP地址 & 子网掩码
若网络标识相同。那么证明两个IP地址在同一子网
============================================================
9.1 Linux网络编程框架
注意:这个层次是比较复杂的,而且分层的感觉比较明显。
TCP协议、socket接口
后面我们会学自己写一个服务器,能够让两端连接上。当然完整的服务器需要什么,会点到为止。
深入学习网络编程,就差不多要看书了
做什么,我们再去深入研究什么。
网络是分层的
OSI 7层网络模型
目的:解决整体的复杂性
具体表现:不一定分7层,如TCP只有4层
TCP/IP协议引入:
TCP/IP是使用最多的网络协议实现
上层进程在网络通讯的时候,也是有一个定向功能的。QQ和QQ通信的时候,是有办法精确到进程里面去的。
在上层是一个独特的层次,他不用考虑下层的问题,不管你什么设备到底用的是wifi还是4G。
Tips:关于网络的学习:应该是学哪个层次就深入哪个。我们的学习重点是API+APP。关注的重点也是应用层,了解传输层。
网络驱动、网卡相关和通讯相关的问题我们暂不考虑。
研究网络通信的时候,一定是在同一层次上研究。是讲应用都讲应用。一个主机的应用和另一个主机的驱动是没有任何话可以说的,因为这毫无意义。
BS和CS
BS架构 浏览器服务器架构 browser 多客户端集于浏览器 后
CS架构 客户端服务器架构 client-server 迅雷、 {MOD}、QQ 先
9.2 TCP
1 位于传输层,对上服务socket,对下服务ip
2 面向连接,需要先建立连接
3 可靠传输
TCP保证可靠的方法:
1 握手
2 ack和丢包重传
3 数据附带校验防止传输损坏
4 滑动窗口技术,根据带宽适配速率
5 报文编号顺序校验
TCP的握手
握手的次数设计,取决于成本和可靠程度。握手越多成本越高,也越可靠。
[建立连接]
建立连接3次握手
服务器listen时,客户端connect
[关闭连接]
关闭连接4次握手
双方任意一方都可以主动关闭
应用层写代码的时候,是不用管握手过程的,这些协议已经被传输层封装好了。
建立连接的过程
服务器端:
socket 创建套接字
bind 本地绑定
listen 进行监听
客户端:
socket 创建套接字
connect 发起连接
服务器端:同意连接
8.6 Socket编程接口介绍
1、建立连接
socket(int 网络域 , int type , int协议) //非常类似open
网络域: 宏定义的ipv4或ipv6
type: 三类宏定义
SOCK_STREAM //TCP网络
SOCK_DGRAM //UDP网络
SOCK_SEQPACKET
协议: 默认0
bind(int socket , const struct sockaddr * address , len) //类似fcntl,绑定本地ip
listen(int socket , int backlog)
backlog: 监听几个
connect(int socket, 目的ip, len)
2、发送和接收函数
send(int socket, buf,len,int flag)
flag: 平时设置为0,即实现write()的功能,特殊协议时会使用到其他
recv(int socket, buf,len,int flag)
flag: 平时设置为0,即实现write()的功能,特殊协议时会使用到其他
3、辅助型函数
不支持ipv6的三个函数
inet_aton
inet_addr 点分十进制 → int格式
inet_ntoa
滋瓷ipv6的两个函数
inet_ntop 32位 → 点分十进制 n代表net
inet_pton 32位 → 点分十进制 p当作person理解,其实是指针,字符格式的意思
13:27 2016/12/7
4、相关结构体
在/usr/include 下,netinet/in.c中,有对结构体的声明
typedef u32_t in_addr_t;
struct in_addr
{
in_addr_t s_addr;
}
struct sockaddr_in
{
in_port_t sin_port;
struct in_addr sin_addr;
}
struct sockaddr这个“ip地址标准结构体”实际上只是形参,是不存在的,他在实际应用过程中,会被替换为
struct sockaddr_in
或者
struct sockaddr_in6
5、补充一点:网络字节序
就是大端模式,网络传输中,不同大小端的 设备,都要遵从大端模式。
实战1 CS机制
网络之间用bind的原因
bind绑定的是 套接字 与 IP地址+端口号
网络进程与网络进程之间是不好直接通信的。因为根据IP地址仅仅能找到哪个设备,而不是哪个进程。
网络传输过程中是找不到目标进程的,这个时候就需要端口号port来为我们指引,是哪一个进程。、
服务器
socket 返回值fd =3(监听fd,专门用来监听,但是不能读写)
bind
listen
accept 返回值ret =4(连接fd,用来和连接另一端的程序进行读写操作)
客户端
socket
connect
htonl
host to net long 4字节
htons
host to net short 2字节
双向通信:
客户端发送 & 服务器接收
服务器发送 & 客户端接收
服务器:
WHILE1
ret = recv(clifd , recvbuf , sizeof(recvbuf) , 0);
printf recvbuf
memset
客户端
WHILE1
ret = send(sockfd , sendbuf , sizeof(sendbuf) , 0);
printf recvbuf
memset
双方自由收发:异步通信,需要一个通信约定完成同步。需要依靠应用层协议解决。