1.网络通信协议
网络通讯的基本要素
C/S构架
OSI七层模型
2.socket编程
server(服务器) client(客户端)
网络通讯的基本要素
1.物理连接介质 2.通讯协议
应用 表示 会话 传输 网络 数据链路 物理
以太网协议
1.物理层 规定 物理介质的相关规范 比如网线接口是什么样的 有几根线
二进制
问题:无法理解单纯的二进制数据
2.数据链路层 工作在这一层的是以太网协议
规定一组电信号有多少位 规定每组电信号包含什么样的内容
每一台电脑必须拥有一个全球唯一的mac地址(可以有多个)
通过广播的方式 来找到对方的mac地址
255-1 一个局域网的容量
问题:不可能全球广播 会造成广播风暴(广播太多 网络瘫痪)
3.网络层
工作在这一层的是ip协议
网络地址协议:给每一个计算机分配一个ip地址
dns(域名解析服务器) 将域名转为ip地址
ARP协议是根据ip获取对方的mac地址
在IP协议中 包含一个路由协议: 用最短的路径找到对方的主机
路由器就相当于古代的驿站
通常是ipv4
0.0.0.0-255.255.255.255
前三段称之为网络号 后一段称之为主机号
子网掩码用来判断是否处于同一个局域网
arp协议 把ip转成mac地址的协议
ip协议最主要的目的就是找到全球范围内的某一个局域网 与某一台具体的计算机
问题:一个数据包到达对方计算机后 到底交给哪一个应用程序来处理
端口范围0-65535 0-1023为系统占用端口
传输层: 用于规范数据传输方式(tcp udp) 以及识别应用程序(端口号)
四次挥手 断开连接 也是为了确保数据传输完整性
TCP
优点 可靠 保证数据传输是完整的
缺点 由于每次都需要传输确认信息 导致传输效率降低
适用于 对数据完整性要求高的程序 比如支付数据 文字信息等
相当于手机
udp 不可靠传输
优点 由于不需要传输确认信息 所以传输效率高于tcp协议
缺点 传输数据可能不完整 完全不关心对方是否收到数据 把数据发送到网络中
适用于:视频 语音 即时对战游戏
相当于对讲机
网络传输数据 其实就是一层层封包与一层层解包的过程
应用层:主要是用于规定 双防应用程序之间以什么形式来传输数据
这一层的数据形式是由程序员自己来定制的 长剑有HTTP FTP Email等等
重点关注的就是传输层协议 以及网络地址
socket
封装了传输层一堆协议的模块
当你需要开发一款C/S结构的应用程序的时候 就需要使用它
基于C/S结构的应用程序 需要分别开发服务器和客户端程序
学习的重点就是如何使用socket编写服务器程序 以及客户端程序
通常应该先开发服务器
服务器程序的大致流程 1.创建socket对象 2.绑定ip和port 3.监听连接 4.接受请求 5.收发数据 6.断开连接 import socket #默认情况下创建的是基于网络的TCP协议的socket对象 s=socket.socket(socket.AF_INET,socket.SOCK_STREAM) #参数1:协议家族 网络的为AF_INET #参数2:type 用于设置采用的传输协议 TCP的为SOCK_STREAM UDP为SOCK_DGRAM #重用端口号 当你已经关闭了服务器 但是还是报异常说 端口占用时 可以使用 s.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1) s.bind(('127.0.0.1',8888)) #端口号取值:0-65535 0-1023是系统保留的 s.listen()#监听客户端的连接 #c:当接受到请求时 会返回一个表示客户端的socket对象 #客户端的socket对象就负责这个客户端的数据手法 #c_addr 同时返回对方的ip和端口 打包成元组 c,addr=s.accept()#接受客户端的连接请求 #开始接受数据 #recv接受数据 #buffersize 缓冲区大小 单位为字节 1kb data=c.recv(1024) print(data.decode('utf-8')) c.close()#断开与客户端的连接 s.close()#关闭服务器socket 后续的客户端就无法在连接服务器了 一般正常服务器是不会关闭的
import socket #创建socket对象 c=socket.socket() #与服务器建立连接 传入服务器的ip和端口 c.connect(('127.0.0.1',8888)) #收发数据 只能发送bytes类型的数据(任何数据都能发) c.send('你真帅'.encode('utf-8')) #断开与服务器的连接 c.close()
import socket s=socket.socket() s.bind(('127.0.0.1',8888)) s.listen() # 连接循环 重复接受客户端连接请求 直到关闭程序为止 while True: c,addr=s.accept() print('收到了一个请求') # 通讯循环 重复的收发数据 直到断开连接 while True: try: data=c.recv(1024)# 也是一个阻塞函数 会一直等到对方发送数据为止 # 如果对方断开了连接 会重复收到空消息 if not data: print('客户端下线了') break print('收到了一个数据',data) # 给客户端 返回一个消息 data+=b'dsb' c.send(data) except ConnectionResetError: print('对方异常断开连接') break # s.send(data) #错误示范 服务器只负责 接收请求 建立连接 具体的收发数据由客户端socket来做 # 注意:服务器和客户端之间 不能同时都执行recv 由于recv是一个阻塞 会导致双方卡死 # windows中 客户端 强行下线 服务器会抛出ConnectionResetError异常 来try处理 # windows中 客户端 正常下线 会重复收到空消息 # linux 客户端 强行下线 服务器会重复收到空消息 # linux 客户端 正常下线 服务器也会重复收到空消息 # 结论:既要处理异常 又要加上空消息的判断 保证服务器不会被终止或死循环
import socket c=socket.socket() c.connect(('127.0.0.1',8888)) while True: msg=input('>>>:(q.退出)') if msg=='q': break elif not msg: continue # 发送数据 c.send(msg.encode('utf-8')) # 接收服务器返回的数据 data=c.recv(1024) print(data)