网络编程
1.网络基础
用途:未来的web框架的学习 未来的工作场景做铺垫
- 两个运行中的程序如何传递信息?
- 通过文件
- 两台机器上的两个运行中的程序如何通信?
- 通过网络
-
- 网络应用开发架构
- C/S
- client 客户端
- server 服务端
- 例如:迅雷 qq 浏览器 飞秋 输入法 百度云 pycharm git VNC 红蜘蛛 各种游戏
- B/S
- browser 浏览器
- server 服务端
- 例如:淘宝 邮箱 各种游戏 百度 博客园 知乎 豆瓣 抽屉
- 统一程序的入口
- B/S和C/S架构的关系:B/S是特殊的C/S架构
- C/S
- 网络应用开发架构
3.网卡:是一个实际存在计算机中的硬件
4.mac地址:每块网卡上都有一个全球独一无二的mac地址
5.交换机:链接多台机器并帮助通讯的物理设备,只认识mac地址。
6.协议:两台物理设备之间对于要发送的内容,长度,顺序的一些约定
7.ip地址:
- 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
8.公网ip:能被所有人访问到ip地址
9.内网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
10.arp协议:通过ip地址获取mac地址
11.网关ip:一个局域网的网络出口,访问局域网之外的区域都需要经过路由器和网关
12.网段:指的是一个地址段 ,如x.x.x.0或x.x.0.0或x.0.0.0
13.子网掩码:判断两台机器是否在同一个网段、子网内。
14.port:端口 ,0-65535
- ip地址能够确认一台机器
- ip+port能确认一台机器上的一个应用
2.osi七层模型
- 第七层:应用层
- 第六层:表示层
- 第五层:会话层
- 第四层:传输层
- 第三层:网络层
- 第二层:数据链路层
- 第一层:物理层
3.osi 五层协议
层数 | 名称 | 协议 | 物理设备 | |
---|---|---|---|---|
第五层 | 应用层 | python代码相关 | http/https/ftp/smtp协议 | |
第四层 | 传输层 | port端口 | tcp、udp协议 | 四层路由器、四层交换机 |
第三层 | 网络层 | ip地址相关 | ipv4、ipv6协议 | 三层路由器、三层交换机 |
第二层 | 数据链路层 | mac地址相关 | arp协议,以太网协议 | 网卡、二层交换机 |
第一层 | 物理层 | 电信号 |
4.tcp、udp协议
tcp协议:
- 特点:
- 可靠、慢、全双工通信
- 建立链接时:三次握手
- 断开链接时:四次挥手
- 在建立起连接之后
- 发送的每一条信息都有回执
- 为了保证数据的完整性,还有重传机制
- 长连接:会一直占用双方的端口
- 能够传递的数据长度几乎没有限制
应用场景:
- 文件的上传下载
- 发送邮件,网盘,缓存电影等
SYN=1,是tcp的标志位,代表这是一个请求信息
ACK=1,代表确认信息
seq=x 代表这一个数据包的序列号, 一半都加到ACK+1代表是这个包
3次握手:connect客户端发起一个syn链接请求,如果得到了server端响应ack的同时还会再收到一个由server端发来的syc链接请求client端进行回复ack之后,就建立起了一个tcp协议的链接
4次挥手:每一端发起的close操作都是一次fin的断开请求,得到'断开确认ack'之后,就可以结束一端的数据发送
如果两端都发起close,那么就是两次请求和两次回复,一共是四次操作.
服务端确认信息和close操作不能同时,是因为可能服务端还没处理完数据
udp协议:
1、特点:
- 无连接,速度快
- 可能会丢消息
- 能够传递的长度有限,是根据数据传递的设备的设置有关
应用场景:
- 即时通信类
- qq,微信,飞秋等
tcp协议和udp协议的区别:
tcp协议:是一个面向连接的,流式的,可靠的,慢的,全双工通信
- 邮件 文件 http web
udp协议:是一个面向数据报的,无连接的,不可靠的,快的,能完成一对一,一对多,多对多的高效通讯协议
- 即时聊天工具 在线视频
总结
- TCP(transport control protocol,传输控制协议)是面向连接的,面向流的,提供高可靠性服务。收发两端(客户端和服务器端)都要有一一成对的socket,因此,发送端为了将多个发往接收端的包,更有效的发到对方,使用了优化方法(Nagle算法),将多次间隔较小且数据量小的数据,合并成一个大的数据块,然后进行封包。这样,接收端,就难于分辨出来了,必须提供科学的拆包机制。 即面向流的通信是无消息保护边界的。
- UDP(user datagram protocol,用户数据报协议)是无连接的,面向消息的,提供高效率服务。不会使用块的合并优化算法,, 由于UDP支持的是一对多的模式,所以接收端的skbuff(套接字缓冲区)采用了链式结构来记录每一个到达的UDP包,在每个UDP包中就有了消息头(消息来源地址,端口等信息),这样,对于接收端来说,就容易进行区分处理了。 即面向消息的通信是有消息保护边界的。
- tcp是基于数据流的,于是收发的消息不能为空,这就需要在客户端和服务端都添加空消息的处理机制,防止程序卡住,而udp是基于数据报的,即便是你输入的是空内容(直接回车),那也不是空消息,udp协议会帮你封装上消息头
5.scoket(套接字)
什么是socket?
Socket是应用层与TCP/ip协议族通信的中间软件抽象层,它是一组接口,帮助我们完成了所有信息的组织和拼接
基于tcp协议的socket
- tcp是基于链接的,必须先启动服务端,绑定ip和端口,然后再启动客户端去链接服务端
#服务端
import socket
socket_server=socket.socket(family=socket.AF_INET, type=socket.SOCK_STREAM)
socket_server.bind(('127.0.0.1',8802)) #把地址绑定到套接字
socket_server.listen(5)#监听链接
conn,addr = socket_server.accept()#接受客户端链接
print(conn,addr) #conn为套接字,addr为地址端口
ret = conn.recv(1024)#接受客户端信息
print(ret)
conn.send(ret.upper())#向客户端发送信息
conn.close()#关闭客户端套接字
socket_server.close()#关闭服务端套接字
#客户端
import socket
socket_client = socket.socket() #创建客户端套接字
socket_client.connect(('127.0.0.1',8802))#尝试链接服务器
socket_client.send('hello!'.encode('utf-8'))#发送消息
#send、recv本质是发给自己的操作系统,操作网卡在根据tcp、udp协议往后面传
ret = socket_client.recv(1024) #接受消息
print(ret.decode('utf-8'))
socket_client.close() #关闭客户端套接字
#注意消息的传递都是bytes类型
加上通讯循环+解决bug+多台客户端一个个访问
#服务端
import socket
socket_server=socket.socket(family=socket.AF_INET, type=socket.SOCK_STREAM)
socket_server.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1) #会遇到端口在用,加上这句搞定
socket_server.bind(('127.0.0.1',8805)) #把地址绑定到套接字
socket_server.listen(5)
while True: #这里循环接受客户端连接,一个断链后,可以继续接受。串行,这里还不是并发
conn,addr = socket_server.accept()
print(conn,addr)
while True:
try:
data = conn.recv(1024)
if not data:break
print(data)
conn.send(data.upper())
except ConnectionResetError:#在window机器上会报这个错误
break
conn.close()#关闭一个客户端
socket_server.close()
#客户端
import socket
socket_client = socket.socket()
socket_client.connect(('127.0.0.1',8805))
while True:
try:
msg = input('<<<').strip()
if not msg:
continue
socket_client.send(msg.encode('utf-8'))
data = socket_client.recv(1024)
print(data.decode('utf-8'))
except ConnectionResetError:
break
socket_client.close()
socket实现ssh服务
#服务端
import socket,subprocess
ip_port = ('127.0.0.1',8081)
ssh_server = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
ssh_server.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
ssh_server.bind(ip_port)
ssh_server.listen(5)
while 1:
conn,addr=ssh_server.accept()
print('客户端',addr)
while 1:
cmd = conn.recv(1024)
if not cmd:break
print('recv cmd',cmd)
res = subprocess.Popen(cmd.decode('GBK'),shell=True,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
stdin=subprocess.PIPE) #windows机器上是GBK
stderr = res.stderr.read()
stdout = res.stdout.read()
print('res length',len((stdout)))
conn.send(stderr)
conn.send(stdout)
conn.close()
#客户端
import socket
ip_port = ('127.0.0.1', 8081)
ssh_client = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
ssh_client.connect_ex(ip_port)
while 1:
msg = input('>>').strip()
if not msg:continue
if msg == 'quit':break
ssh_client.send(msg.encode('utf-8'))
res = ssh_client.recv(1024)
print(res.decode('GBK'))
基于udp协议的socket:
#server
import socket
import subprocess
ip_port = ('127.0.0.1', 9003)
bufsize = 1024
udp_server = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
udp_server.bind(ip_port)
#不用建立链接
while True:
# 收消息
cmd, addr = udp_server.recvfrom(bufsize)
print('用户命令----->', cmd,addr)
# 逻辑处理
res = subprocess.Popen(cmd.decode('utf-8'), shell=True, stderr=subprocess.PIPE, stdin=subprocess.PIPE,
stdout=subprocess.PIPE)
stderr = res.stderr.read()
stdout = res.stdout.read()
# 发消息
udp_server.sendto(stdout + stderr, addr) #回消息也要指定端口
udp_server.close()
#client
from socket import *
import time
ip_port = ('127.0.0.1', 9003)
bufsize = 1024
udp_client = socket(AF_INET, SOCK_DGRAM)
while True:
msg = input('>>: ').strip()
if len(msg) == 0:
continue
udp_client.sendto(msg.encode('utf-8'), ip_port) #发送消息时要告诉向哪个端口发消息
data, addr = udp_client.recvfrom(bufsize)
print(data.decode('utf-8'), end='')
6.粘包现象:
定义:同时执行多条命令之后,得到的结果很可能只有一部分,在执行其他命令的时候又接收到之前执行的另外一部分结果,这种现象就是黏包
粘包的成因:只有TCP有粘包现象,UDP永远不会粘包
tcp协议的粘包现象:
- 什么是粘包现象
- 发生在发送端的粘包
- 由于两个数据的发送时间间隔短+数据的长度小
- 所以由tcp协议的优化机制将两条信息作为一条信息发送出去了
- 为了减少tcp协议中的“确认收到”的网络延迟时间
- 发生再接收端的粘包
- 由于tcp协议中所传输的数据无边界,所以来不及接收的多条
- 数据会在接收放的内核的缓存端黏在一起
- 本质: 接收信息的边界不清晰
- 发生在发送端的粘包
总结:
- 粘包现象只发生在tcp协议
- 从表面上来看,粘包问题主要是因为发送方和接受方的缓存机制,tcp协议的面向流通信的特点
- 实际上。主要还会因为接受方不知道消息之间的边界,不知道一次性提取多少字节的数据造成的
解决粘包问题 :
- 自定义协议1
- 首先发送报头的长度,报头长度4个字节,内容是发送的报文的字节长度
- 在发送报头
- 自定义协议2
- 我们专门用来做文件发送的协议
- 先发送报头字典的字节长度,再发送字典(字典中包含文件的名字、大小),再发送文件的内容
#服务端
import socket,subprocess
import json,struct
ip_port = ('127.0.0.1',8082)
ssh_server = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
ssh_server.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
ssh_server.bind(ip_port)
ssh_server.listen(5)
while 1:
conn,addr=ssh_server.accept()
print('客户端',addr)
while 1:
try:
#1、收命令
cmd = conn.recv(8096)
if not cmd:break
#2、执行命令拿到结果
res = subprocess.Popen(cmd.decode('GBK'),shell=True,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
stdin=subprocess.PIPE)
stderr = res.stderr.read()
stdout = res.stdout.read()
#3、把命令的结果返回给客户端
#第一步:制作固定长度的报头
header_dic = {
'filename':'a.txt',
'md5':'xxx',
'total_size':len(stdout)+len(stderr)
}
header_json = json.dumps(header_dic)
header_bytes = header_json.encode('GBK')
#第二步:先发送报头的长度
conn.send(struct.pack('i',len(header_bytes))) #这里的固定长度是4,为了防止粘包
#第三步:在发送报头
conn.send(header_bytes)
#第四步:在发送真实的数据
conn.send(stderr)
conn.send(stdout)
except ConnectionResetError:
break
conn.close()
ssh_server.close()
#客户端
import socket,json,struct
ip_port = ('127.0.0.1', 8082)
ssh_client = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
ssh_client.connect_ex(ip_port)
while 1:
msg = input('>>').strip()
if not msg:continue
if msg == 'quit':break
ssh_client.send(msg.encode('GBK'))
#2、拿到命令,并打印
#第一步:接受报头的长度
obj=ssh_client.recv(4) #bytes类型的
header_size =struct.unpack('i',obj)[0] #解包 报头的长度
#第二步:接受报头
header_bytes=ssh_client.recv(header_size) #收的报头的长度
#第三步:从报头中解析出对应真实的数据
header_json = header_bytes.decode('GBK')
header_dic = json.loads(header_json)
total_size = header_dic['total_size']
#第四步:接受真实的数据
recv_size = 0
recv_data = b''
while recv_size < total_size:
res = ssh_client.recv(1024)
recv_size+=len(res)
recv_data+=res
print(recv_data.decode('GBK'))
ssh_client.close()
7.实现文件传输
简单版本:
#server
import os
import socket,subprocess
import json,struct
ip_port = ('127.0.0.1',9999)
ssh_server = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
ssh_server.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
ssh_server.bind(ip_port)
ssh_server.listen(5)
share_dir =r'D:pycharm2018python_stack 3面向对象&网络编程基础网络编程_文件传输servershare'
while 1:
conn,addr=ssh_server.accept()
print('客户端',addr)
while 1:
try:
#1、收命令
res = conn.recv(8096) #get 1.mp4
if not res:break
#2、解析命令,拿到相应的参数
cmds=res.decode('GBK').split()
filename = cmds[1]
#3、以读的方式打开文件,读取文件内容返回给客户端
#第一步:制作固定长度的报头
header_dic = {
'filename':filename,
'md5':'xxx',
'total_size':os.path.getsize('%s\%s'%(share_dir,filename))
}
header_json = json.dumps(header_dic)
header_bytes = header_json.encode('GBK')
#第二步:先发送报头的长度
conn.send(struct.pack('i',len(header_bytes))) #这里的固定长度是4,为了防止粘包
#第三步:在发送报头
conn.send(header_bytes)
#第四步:在发送真实的数据
with open('%s\%s'%(share_dir,filename),'rb')as f:
for line in f:
conn.send(line)
except ConnectionResetError:
break
conn.close()
ssh_server.close()
#client
import socket,json,struct
ip_port = ('127.0.0.1', 9999)
ssh_client = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
ssh_client.connect_ex(ip_port)
download_dir = r'D:pycharm2018python_stack 3面向对象&网络编程基础网络编程_文件传输clientdownload'
while 1:
msg = input('>>').strip() #get 1.mp4
if not msg:continue
if msg == 'quit':break
ssh_client.send(msg.encode('GBK'))
#2、拿到命令,并打印
#第一步:接受报头的长度
obj=ssh_client.recv(4) #bytes类型的
header_size =struct.unpack('i',obj)[0] #解包 报头的长度
#第二步:接受报头
header_bytes=ssh_client.recv(header_size) #收的报头的长度
#第三步:从报头中解析出对应真实的数据
header_json = header_bytes.decode('GBK')
header_dic = json.loads(header_json)
total_size = header_dic['total_size']
filename = header_dic['filename']
#第四步:接受真实的数据
with open('%s\%s'%(download_dir,filename),'wb')as f: #windows
recv_size = 0
while recv_size < total_size:
res = ssh_client.recv(1024)
f.write(res)
recv_size+=len(res)
print('总共%s,现在下载了%s' % (total_size, recv_size))
ssh_client.close()
函数版本:
#服务端
import os
import socket,subprocess
import json,struct
share_dir =r'D:pycharm2018python_stack 3面向对象&网络编程基础网络编程_文件传输函数版本servershare'
def get(conn,filename):
# 3、以读的方式打开文件,读取文件内容返回给客户端
# 第一步:制作固定长度的报头
header_dic = {
'filename': filename,
'md5': 'xxx',
'total_size': os.path.getsize('%s\%s' % (share_dir, filename))
}
header_json = json.dumps(header_dic)
header_bytes = header_json.encode('GBK')
# 第二步:先发送报头的长度
conn.send(struct.pack('i', len(header_bytes))) # 这里的固定长度是4,为了防止粘包
# 第三步:在发送报头
conn.send(header_bytes)
# 第四步:在发送真实的数据
with open('%s\%s' % (share_dir, filename), 'rb')as f:
for line in f:
conn.send(line)
def put(ssh_client):
# 2、拿到命令,并打印
# 第一步:接受报头的长度
obj = ssh_client.recv(4) # bytes类型的
header_size = struct.unpack('i', obj)[0] # 解包 报头的长度
# 第二步:接受报头
header_bytes = ssh_client.recv(header_size) # 收的报头的长度
# 第三步:从报头中解析出对应真实的数据
header_json = header_bytes.decode('GBK')
header_dic = json.loads(header_json)
total_size = header_dic['total_size']
filename = header_dic['filename']
# 第四步:接受真实的数据
with open('%s\%s' % (share_dir, filename), 'wb')as f: # windows
recv_size = 0
while recv_size < total_size:
res = ssh_client.recv(1024)
f.write(res)
recv_size += len(res)
print('总共%s,现在下载了%s' % (total_size, recv_size))
def run():
ip_port = ('127.0.0.1',8889)
ssh_server = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
ssh_server.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
ssh_server.bind(ip_port)
ssh_server.listen(5)
while 1:
conn,addr=ssh_server.accept()
print('客户端',addr)
while 1:
try:
#1、收命令
res = conn.recv(8096) #get 1.mp4
if not res:break
#2、解析命令,拿到相应的参数
cmd=res.decode('GBK')
cmds = cmd.split()
print(cmds)
filename = cmds[1]
if cmds[0] == 'get':
get(conn,filename)
elif cmds[0] == 'put':
put(conn)
except ConnectionResetError:
break
conn.close()
ssh_server.close()
if __name__ == '__main__':
run()
#客户端
import socket,json,struct
import os
download_dir = r'D:pycharm2018python_stack 3面向对象&网络编程基础网络编程_文件传输简单版本clientdownload'
def get(ssh_client):
# 2、拿到命令,并打印
# 第一步:接受报头的长度
obj = ssh_client.recv(4) # bytes类型的
header_size = struct.unpack('i', obj)[0] # 解包 报头的长度
# 第二步:接受报头
header_bytes = ssh_client.recv(header_size) # 收的报头的长度
# 第三步:从报头中解析出对应真实的数据
header_json = header_bytes.decode('GBK')
header_dic = json.loads(header_json)
total_size = header_dic['total_size']
filename = header_dic['filename']
# 第四步:接受真实的数据
with open('%s\%s' % (download_dir, filename), 'wb')as f: # windows
recv_size = 0
while recv_size < total_size:
res = ssh_client.recv(1024)
f.write(res)
recv_size += len(res)
print('总共%s,现在下载了%s' % (total_size, recv_size))
def put(ssh_client,filename):
# 3、以读的方式打开文件,读取文件内容返回给客户端
# 第一步:制作固定长度的报头
header_dic = {
'filename': filename,
'md5': 'xxx',
'total_size': os.path.getsize('%s\%s' % (download_dir, filename))
}
header_json = json.dumps(header_dic)
header_bytes = header_json.encode('GBK')
# 第二步:先发送报头的长度
ssh_client.send(struct.pack('i', len(header_bytes))) # 这里的固定长度是4,为了防止粘包
# 第三步:在发送报头
ssh_client.send(header_bytes)
# 第四步:在发送真实的数据
with open('%s\%s' % (download_dir, filename), 'rb')as f:
for line in f:
ssh_client.send(line)
print(line)
def run():
ip_port = ('127.0.0.1', 8889)
ssh_client = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
ssh_client.connect_ex(ip_port)
while 1:
try:
msg = input('>>').strip() #get 1.mp4
if not msg:continue
if msg == 'quit':break
ssh_client.send(msg.encode('GBK'))
inp = msg.split()
filename = inp[1]
if inp[0] == 'get': #下载操作,服务端读取,内容发给客户端
get(ssh_client)
elif inp[0] == 'put': #上传操作,从本地读取,发给服务端
put(ssh_client,filename)
except ConnectionResetError:
break
ssh_client.close()
if __name__ == '__main__':
run()
面向对象版本:
#服务端
import socket
import struct
import json,subprocess
import os
class MYTCPServer:
address_famliy =socket.AF_INET #协议
socket_type = socket.SOCK_STREAM #TCP
coding = 'GBK'
max_packet_size = 8096
request_queue_size = 5
allow_reuse_address = False
server_dir = r'D:pycharm2018python_stack 3面向对象&网络编程基础网络编程_文件传输面向对象版本load'
def __init__(self,server_address):
self.server_address = server_address
self.socket = socket.socket(self.address_famliy,self.socket_type)
self.server_bind()
self.server_activate()
def server_bind(self):
if self.allow_reuse_address:
self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
self.socket.bind(self.server_address)
self.server_address = self.socket.getsockname()
def server_activate(self):
self.socket.listen(self.request_queue_size)
def server_close(self):
self.socket.close()
def get_request(self):
return self.socket.accept()
def close_request(self,request):
request.close()
def get(self):
header_dic = {
'filename':self.filename,
'total_size':os.path.getsize(self.server_dir)
}
head_json = json.dumps(header_dic)
header_bytes = head_json.encode(self.coding)
#发送报头长度
self.conn.send(struct.pack('i',len(header_bytes)))
#再发报头
self.conn.send(header_bytes)
#发送真实数据
with open('%s'%self.filename,'rb')as f:
for line in f:
self.conn.send(line)
def put(self):
pass
def run(self):
while 1:
self.conn,self.addr = self.get_request()
while 1:
try:
# 1、收命令
res = self.conn.recv(self.max_packet_size)
if not res:break
print(res)
# 2、解析命令,拿到相应的参数
cmd = res.decode(self.coding)
cmds = cmd.split()
print(cmds)
self.cmd=cmds[0]
self.filename = cmds[1]
if hasattr(self,self.cmd):
func = getattr(self,self.cmd)
func()
else:print('没有这个功能')
except ConnectionResetError:
break
#####
obj =MYTCPServer(('127.0.0.1',8888))
obj.run()
·
#客户端
import socket
import struct
import json,subprocess
import os
class MYTCPClient:
address_famliy =socket.AF_INET #协议
socket_type = socket.SOCK_STREAM #TCP
coding = 'GBK'
server_dir =r'D:pycharm2018python_stack 3面向对象&网络编程基础网络编程_文件传输面向对象版本up'
def __init__(self,server_address):
self.server_address = server_address
self.socket = socket.socket(self.address_famliy,self.socket_type)
self.connect_ex()
def connect_ex(self):
self.socket.connect_ex(self.server_address)
def server_close(self):
self.socket.close()
def close_request(self,request):
request.close()
def get(self):
obj=self.socket.recv(4)
header_size = struct.unpack('i',obj)[0]
header_bytes = self.socket.recv(header_size)
header_json = header_bytes.decode(self.coding)
header_dic = json.loads(header_json)
#根据字典筛选有用信息
total_size = header_dic['total_size']
filename = header_dic['filename']
#写文件
with open('%s'%self.filename,'rb')as f:
recv_size = 0
while recv_size< total_size:
res=self.socket.recv(1024)
f.write(recv_size)
recv_size+=len(res)
print('总共%s,现在下载了%s' % (total_size, recv_size))
def put(self):
pass
def run(self):
while 1:
try:
# 1、收命令
msg = input('>>').strip() # get 1.mp4
if not msg: continue
if msg == 'quit': break
self.socket.send(msg.encode(self.coding))
print(msg.encode(self.coding))
inp = msg.split()
self.filename = inp[1]
self.cmd = inp[0]
if hasattr(self,self.cmd):
func = getattr(self,self.cmd)
func()
except ConnectionResetError:
break
#####
obj =MYTCPClient(('127.0.0.1',8888))
obj.run()