目录
[doc]
一、网络编程大体图
二、TCP协议
TCP协议又叫:流失协议、可靠协议
1.TCP协议像流水一样一直发送,一直接收
2.TCP协议可靠的原因:有反馈机制(发送一句,回复一句才会发送下一句)
洪水攻击:同一时间发送给服务器大量请求
1.三次握手,四次挥手图
2.tcp代码
1.简单版
服务端:
import socket server = socket.socket() # 生成对象 server.bind(('127.0.0.1', 8080)) # 绑定IP和端口 (自己的) server.listen(5) # 半连接池,允许等待数 conn, addr = server.accept() # 等待接听 # conn:地址 addr:端口号(随机分配) while True: data = conn.recv(1024) # 接收 print(data) # 打印接收的内容 # 判断如果接收的是空,就跳出循环 if len(data) == 0: break conn.send(data.lower()) # 发送反馈内容
客户端:
import socket client = socket.socket() # 生成对象 client.connect(('127.0.0.1', 8080)) # 拨号,对方IP和端口 while True: msg = input('请输出 >>>:').strip().encode('utf-8') # 转二进制 if len(msg) == 0: continue client.send(msg) # 发送 data = client.recv(1024) # 接收反馈内容 print(data)
2.电影上传
1.打包,固定长度模块struct
注意:一般用'i'模式,固定4个字节 长度,q模式最大8个字节长度
import struct """ 利用struct给 """ res1 = 'asdfkjhksdhfksadhfkkshfasjdfklasddfjkl' print('开始的', len(res1)) res2 = struct.pack('i', len(res1)) print('压缩的', len(res2)) res3 = struct.unpack('i', res2)[0] print('解压的', res3)
客户端:
import os import socket import struct import json move = socket.socket() # 生成对象 move.connect(('127.0.0.1', 8080)) # 写服务端的IP,port while True: # 1.拼接文件路径 MOVE_PATH = r'E:\学习视频\python老男孩\对象\day20\视频' move_list = os.listdir(MOVE_PATH) # 循环打印 for i in move_list: print(move_list.index(i)+1, i) # 用户选择 choice = input('请选择你要上传的电影>>>:') # 判断输入是否为数字 if choice.isdigit(): # 转成int型 choice = int(choice)-1 # 判断是否在范围内 if choice in range(0, len(move_list)): # 拿到用户选择的文件 move_choice = move_list[choice] # 拼接文件路径 move_path = os.path.join(MOVE_PATH, move_choice) # 拿到文件大小 move_size = os.path.getsize(move_path) # 定义字典容器,数据放到字典中 move_dict = {'name': '陪你到老.mp4', 'size': move_size} # 转成json格式和转成二进制格式的字典 json_dict = json.dumps(move_dict).encode('utf-8') # 制作字典报头 hander_dict = struct.pack('i', len(json_dict)) # 发送报头 move.send(hander_dict) # 发送字典 move.send(json_dict) # 发送文件 with open(move_path, 'rb')as f: for i in f: move.send(i) else: print('你选的不在范围内') else: print('请输入数字')
服务端:
import os import socket import json import struct server = socket.socket() # 生成对象 server.bind(('127.0.0.1', 8080)) # 绑定IP,port server.listen(5) # 半连接池 while True: data, addr = server.accept() # 接受连接 # print(data, addr) while True: try: # 接收字典报头 dict_hand = data.recv(4) # 解析字典报头,拿到字典长度 dict_len = struct.unpack('i', dict_hand)[0] # 接收字典长度,就是接收字典 dict_json = data.recv(dict_len) # 解开json,解码二进制 dict = json.loads(dict_json.decode('utf-8')) # 从字典中获取文件的大小长度 move_size = dict.get('size') # 循环接收,并写入文件 accept_size = 0 # print(dict.get('name')) with open(dict.get('name'), 'wb')as f: while accept_size < move_size: accept = data.recv(1024) f.write(accept) # 写入文件 accept_size += len(accept) print('上传成功') except ConnectionResetError as f: print(f) break data.close()
3.json补充,序列化类
from datetime import * import json """序列化类.先转换成字符串型,才能序列化""" # 1.手动转化成字符串型 b = str(datetime.today()) c = str(date.today()) a = {'1':b,'2':c} # print(json.dumps(a)) d = str(datetime.today().strftime('%Y-%m-%d')) # print(d) e = type(datetime.today()) print(e) # 2.定义一个继承json的新的类 class MyJson(json.JSONEncoder): def default(self, o): if isinstance(o,datetime): return o.strftime('%Y-%m-%d %X') elif isinstance(o,date): return o.strftime('%Y-%m-%d') else: return super().default(self,o) res = json.dumps(a) print(res)
4.subprocess补充
import subprocess cmd = input('输入命令>>>:') obj = subprocess.Popen(cmd,shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE) print(obj.stdout.read().decode('gbk')) # 正确命令返回结果 print(obj.stderr.read().decode('gbk')) # 错误命令返回结果 # subprocess获取到的数据 拿完就没有了 不能重复拿
三、UDP的使用
1.简介
udp协议又叫:
1.数据报协议(自带报头)
2.没有双向通道
3.也没有半连接池
发送数据就类似发短信,给指定的IP,port发送,不用管对方有没有收到
缺点:容易数据丢失,不安全
优点:速度快
2.使用基本代码
服务端:
import socket server = socket.socket(type=socket.SOCK_DGRAM) # UDP协议 server.bind(('127.0.0.1', 8080)) # 绑定自己的地址端口 while True: data, addr = server.recvfrom(1024) # 接收 print('接收到数据:', data) print('地址:', addr) server.sendto(data.upper(), addr) # 发送
客户端:
import socket client = socket.socket(type=socket.SOCK_DGRAM) server = ('127.0.0.1', 8080) # 要发送的地址端口 while True: client.sendto(b'hello', server) # 发送 data, addr = client.recvfrom(1024) # 接收 print(data) # 打印
2.1简易版qq
服务端:
import socket phone = socket.socket(type=socket.SOCK_DGRAM) # 1.建立对象 addres = ('127.0.0.1', 8080) while True: send = input('请输入要发送的内容>>>:').encode('utf-8') phone.sendto(send, addres) # 2.发送内容,填写地址 data, addr = phone.recvfrom(1024) # 3.接收 print('收到内容:', data.decode('utf-8')) # 4.接收转码
客户端:
import socket server = socket.socket(type=socket.SOCK_DGRAM) # 1.建立对象 server.bind(('127.0.0.1', 8080)) # 2.绑定地址 while True: data, addr = server.recvfrom(1024) # 3.接收 print('收到的内容:', data.decode('utf-8')) # 4.打印,解码 print('对方地址:', addr) # 打印,解码 msg = input('请输入你要回复的内容>>>:').encode('utf-8') server.sendto(msg, addr) # 5.回复发送
四、UDP和TCP的区别
UDP:类似发短信(只管往某个电话发短信,不管对方有没有看)
1.允许发空(自带报头)
2.不会粘包(自带报头)
3.UDP支持并发
4.UDP服务协议不安全(没有三次握手)
5.UDP速度更快
TCP:类似打电话(有人接听,有人回复)
1.不允许发空(没有报头)
2.会粘包(没有报头)
3.安全系数高(有三次握手)