网络编程
网络编程
1.网络概念的引入
- 两个运行中的程序如何传递信息?
- 通过文件
- 两台机器上的两个运行中的程序如何通信?
- 通过网络
2.网络开发架构
- B/S架构 网页开发
- browser 浏览器
- server 服务端
- C/S架构
ftp
- client 客户端
- server 服务端
- 开发趋势:统一程序的入口
- 两者关系:B/S架构是特殊的C/S架构
3.网络访问
3.1网络地址
ip
地址:确认一台机器- 公网
ip
- 这个
ip
地址能被所有人访问到,是申请得到的
- 这个
- 内网
ip
- 指定分配的,一般有
192.168.0.0 - 192.168.255.255
172.16.0.0 - 172.31.255.255
10.0.0.0 - 10.255.255.255
- 指定分配的,一般有
- 网关
ip
- 一个局域网的网络出口,访问局域网之外的区域都需要经过路由器和网关
- 公网
- 网段:指的是一个地址段
x.x.x.0 x.x.0.0 x.0.0.0
- 子网掩码:判断两台机器是否在同一个网段内的
- port 端口
- 0-65535
ip + port
确认一台机器上的一个应用
3.2设备
- 网卡 :是一个实际存在在计算机中的硬件
- mac地址 :每一块网卡上都有一个全球唯一的mac地址
- 交换机 :是连接多台机器并帮助通讯的物理设备,只认识mac地址
- 完成局域网内的多台机器之间的通信
- 单播,组播,广播
- 路由器:完成局域网与局域网之间的联系
- 能识别ip地址
4.协议
- 两台物理设备之间对于要发送的内容,长度,顺序的一些约定
4.1arp
协议
- 由交换机实现的,是一个地址解析协议
- 通过
ip
地址获取一台机器的mac地址 - 通过广播,单播实现
4.2ip
协议
ipv4
协议 4位的点分十进制 32位2进制表示- 0.0.0.0 - 255.255.255.255
ipv6
协议 6位的冒分十六进制 128位2进制表示0:0:0:0:0:0-FFFF:FFFF:FFFF:FFFF:FFFF:FFFF
4.3tcp/udp
协议
4.3.1tcp
协议
-
特点:面向连接的,可靠的,流式的,全双工通信,传递长度没有限制
-
三次握手
-
client端向server端:发送 请求连接 请求(syn)
-
server端向client端:通过接收到的 请求连接 请求(
ack
) 并且向client端发送 请求连接 请求(syn)
-
client端向server端:通过接收到的 请求连接 请求(
ack
)
-
-
四次挥手
- client端向server端:发送 断开连接 请求(fin)
- server端向client端:通过接收到的 断开连接 请求(
ack
) - server端向client端:向client端发送 断开连接 请求(fin)
- client端向server端:通过接收到的 断开连接 请求(
ack
)
-
在建立连接后,每发送一条信息都会有回执
-
为了保证数据的完整性,会有重传机制
-
长连接:会一直占用双方的端口
-
应用场景:文件的上传和下载
-
拆包机制,传输是先拆包再合包进行传输的
- 由于拆包机制会出现粘包现象
4.3.2udp
协议
- 特点:面向数据报的,无连接的,不可靠的
- 能完成一对一,一对多,多对一,多对多的高效通讯协议
- 可能会丢消息
- 能够传递的数据的长度是有限的,跟数据传递设备的设置有关系
- 应用场景:即时通讯
sk = socket.socket(type=socket.SOCK_DGRAM)
4.4自定义协议
- 自定义协议1
- 首先发送报头
- 报头长度为4个字节
- 内容是即将发送的报文的字节长度
- 使用
struct
模块
- 再发送报文
- 首先发送报头
- 自定义协议2
- 专门用来做文件发送的协议
- 先发送报头字典的长度
- 再发送字典(字典中包含文件的名字,大小····)
- 再发送文件的内容
- 专门用来做文件发送的协议
5.粘包现象
- 本质:接收信息的边界不清晰
- 在接收端的粘包
- 由于
tcp
协议中所传输的数据无边界,接收端来不及接收的多条数据会在接收端的内核的缓存端黏在一起
- 由于
- 在发送端的粘包
- 由于两个数据的发送时间间隔短+数据的长度小,为了减少
tcp
协议中的“确认收到”的网络延迟时间,所以由tcp
协议的优化机制将两条信息作为一条信息发送出去了
- 由于两个数据的发送时间间隔短+数据的长度小,为了减少
- 解决方法:使用自定义协议,核心借用
struct
模块
6.osi
七层模型
6.1.七层模型
- 应用层
- 表示层
- 会话层
- 传输层
- 网络层
- 数据链路层
- 物理层
6.2osi
五层协议
- 应用层 python代码
http https ftp smtp
协议
- 传输层 端口/服务相关
tcp/udp
协议 端口 四层交换机,四层路由器
- 网络层
ip
相关ipv4/ipv6
协议 路由器,三层交换机
- 数据链路层 mac相关
arp
协议 网卡,交换机
- 物理层
7. I/O操作
- 输入输出都是相对内存来讲的
- input 输入到内存
recv recvfrom
- output 从内存输出
send sendto
- input 输入到内存
8.阻塞和非阻塞
-
阻塞:
cpu
不工作,如accept -
非阻塞:
cpu
工作 -
几种模型
- 阻塞
io
模型 - 非阻塞
io
模型 - 事件驱动
io
io
多路复用- 异步
io
模型
- 阻塞
9.代码编写
9.1 socket模块
-
又称套接字
-
工作在应用层和传输层之间的抽象层,帮助我们完成所有信息的组织和拼接
-
对于程序员来说,已经是网络操作的底层
-
socket历史
- 同一台机器上的两个服务之间的通信
- 基于文件操作来完成的
- 基于网络的多台机器之间的多个服务通信
- 同一台机器上的两个服务之间的通信
-
基本模板
######## server端 ######## import socket sk = socket.socket() sk.bind(('127.0.0.1', 9000)) sk.listen() conn, addr = sk.accept() # 中间为要进行的操作 conn.close() sk.close() ######## client端 ######## import socket sk = socket.socket() sk.connect(('127.0.0.1', 9000)) # 中间为要进行的操作 sk.close()
9.2 struct
模块
-
struct.pack
将一个数字转换为四个字节的bytes类型import struct bytes_len = struct.pack('i', 10000) # 将10000转为一个4个字节的bytes类型
-
struct.unpack
将一个四个字节的bytes类型转换回数字,结果是一个元组import struct length = struct.unpack('i', bytes_len) # 将一个4个字节的bytes类型转回其原本的数字
9.3 hamc
模块
-
校验客户端的合法性
-
hamc.new(盐,要加密的内容)
import hamc h = hmac.new(secret_key, randseq) res = h.digest()
9.4 socketserver
模块
-
实现一个同时连接多个
-
基本模板
import socketserver class Myserver(socketserver.BaseRequestHandler): def handle(self): # 自动触发了handle方法,并且self.request == conn 要进行的操作 server = socketserver.ThreadingTCPServer(('127.0.0.1',9000),Myserver) server.serve_forever()