python学习笔记——捌 scoket 例子

服务端:

import socket
#使用MD5的原因 主要是为了确保发送和接受的是同样的文件
#MD5之后,对比两边的值
import hashlib
import os

#创建一个socket实例
server=socket.socket()
#指定 地址和端口 客户端会连接这个地址和端口
server.bind(('0.0.0.0',9999))
# 开始监听操作
server.listen()

while True:
#创建一个连接
conn,addr=server.accept()
print("addr是什么 %s"%addr)
while True:
print("等待新指令")
#循环接收数据
data=conn.recv(1024)
#如果接收的数据是空 就退出接收数据的循环
if not data :
print("客户端断开")
break
#接收来的数据是byte,转成字符串,去掉空格
cmd,filename=data.decode().split()
print("文件名称是"%filename)
#如果此文件名 是一个文件
if os.path.isfile(filename):
#用 二进制读的方式 打开文件 创建一个文件句柄
f=open(filename,"rb")
m=hashlib.md5()
# 此方法返回文件的大小
file_size=os.stat(filename).st_size
#文件的大小 ,转成字符串,再转化成byte类型 发送给客户端
conn.send(str(file_size).encode())
#一次接受就对应着一次发送
conn.recv(1024)
#循环读取文件
for line in f :
#用MD5进行加密处理
m.update(line)
#发送给客户端
conn.send(line)
#把MD5后的文件内容 打印出来
print("file mad5",m.hexdigest())
f.close()
#将MD5的值 转化成二进制后 发送给客户端
conn.send(m.hexdigest().endcode())
print("发送完成")

server.close()



客户端

import socket
import hashlib

# 创建一个scoket实例
client = socket.socket()
# 连接指定 地址和端口
client.connect(("localhost", 9999))

while True:
cmd = input(">>:").split()
# 如果输入的字符穿的 长度是0 就跳过本次循环 循环再次输入
if len(cmd) == 0: continue
#如果输入的字符串是 get 开头的
if cmd.startswith("get"):
#将字符串转化成byte类型 发送给服务端
client.send(cmd.encode())
#接收 服务端发来的 文件大小的byte
server_response=client.recv(1024)
print("server reponse:",server_response)
client.send(b"ready to recv file")
#将数据大小 转化成字符串
file_total_size=int(server_response.decode())

#用于统计接收来数据的大小
received_size=0
# 输入时是 get 文件名 用空格切分之后是一个列表 取第二个元素就是文件名
filename=cmd.split()[1]
f=open(filename+".new","wb")
#创建MD5句柄
m=hashlib.md5()

#接收来的数据 小于 服务端的数据 就会一直循环接收
while received_size < file_total_size:
#粘包 是指 两次数据 合并到一起接收 这样会导致数据混乱
#以下做法是为了避免粘包
#如果数据 源文件的数据大于 接收来的数据 超过1024 说明还要接收多次
if file_total_size -received_size > 1024: #要收数据不止一次
#接收数据的大小是1024
size=1024
else : #最后一次了,剩多少收多少
#如果小于1024 就用 源文件的大小 — 接收文件的大小 剩下的就是全部接受完了
#那些因为粘包多出来的数据 就无法接收到了

size=file_total_size - received_size
print("last receive:",size)
#接收文件
data = client.recv(size)
#把每次接收数据的长度都加起来
received_size += len(data)
#每次把数据都 加进MD5里
m.update(data)
#把数据写进文件
f.write(data)
else :
#转化成16进制的 hash
new_file_md5=m.hexdigest()
#把接收文件的大小和原文件的大小 打印出来
print("file recv done",received_size,file_total_size)
#关闭文件句柄
f.close()
#接收服务端发过来 文件MD5后的值
server_file_mad5=client.recv(1024)
print("server file mad5:",server_file_mad5)
print("client file md5",new_file_md5)

client.close()



原文地址:https://www.cnblogs.com/HL-blog/p/7593334.html