IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Python知识库 -> python中使用socket编程实现带有界面的客户端向服务端发送文件和下载文件 -> 正文阅读

[Python知识库]python中使用socket编程实现带有界面的客户端向服务端发送文件和下载文件

一主界面:
在这里插入图片描述
**二:发送文件界面:**首先需要开启发送文件服务端(这里需要注意的是每一次发送文件之前都需要开启一次服务端,因为我在这里将每一次发送文件之后就关闭了客户端和服务端之间的连接)
在这里插入图片描述
输出相关客户端和服务端的文件传输过程中的信息:
在这里插入图片描述
如果发送文件没有选择,将会得到提示“请选择发送文件”
在这里插入图片描述
三:下载文件主界面:首先需要开启下载文件服务端(同样,这里需要注意的是每一次发送文件之前都需要开启一次服务端,因为我在这里将每一次发送文件之后就关闭了客户端和服务端之间的连接)
注意:这里的下载文件的思路:
1.当开启下载服务端之后,客户端选择要下载的文件
2.客户端将要下载的文件路径发送给服务端
3.服务端根据客户端发送来的文件路径,将要发送的文件大小,类型,文件名打包为消息头发送给客户端
4.服务端将根据文件路径打开文件进行分段发送
5.客户端也根据服务端发送的文件消息头新建一个同样类型的文件名,进行写操作
在这里插入图片描述
当未选择要下载的文件时,也会给出提示“请选择您要下载的文件”。
在这里插入图片描述
如果自己对现在的背景不满意,也可以点击修改背景,换为自己喜欢的图片。
最后就是点击退出操作。
在这里插入图片描述

主界面:

import os
import cv2
import Client
import Server
import socket
import tkinter
import threading
from tkinter import ttk
from PIL import Image,ImageTk
from tkinter import filedialog
from tkinter.messagebox import showerror,showinfo,showwarning

root=tkinter.Tk()
#设置主窗口标题
root.title('文件传输——Keep_Trying_Go')
#设置主窗口大小
root['width']=800
root['height']=600
#固定窗口大小
root.resizable(0,0)
#设置主窗口背景颜色
root['background']='#FFFFFF'
#设置主窗口图标
#设置标题为图像形式,第一个参数设置为True,表示该图标适用于所有的窗口
#这里注意图像格式为.png,就算是从.jpg到.png的格式转换也不能,只能是.png格式
root.iconphoto(True,tkinter.PhotoImage(file='title.png'))

#背景图自适应大小
def ChangeBackground(w,h,w_box,h_box,PIL_Image):
    """
    :param w: 图片的宽度
    :param h: 图片的高度
    :param w_box: 画布的宽度
    :param h_box: 画布的高度
    :param PIL_Image:
    :return:
    """
    factor_w=1.0*w_box/w
    factor_h=1.0*h_box/h
    factor=min([factor_h,factor_w])
    #新的图片高度和宽度
    width=int(w*factor)
    height=int(h*factor)
    print('width: {}'.format(width))
    print('height: {}'.format(height))
    return PIL_Image.resize((width,height),Image.ANTIALIAS)


tk_image_file=''
def setBackground(root,filename):
    """
    :param root: 主窗口
    :return:
    """
    global tk_image_file
    PIL_Image=Image.open(filename)
    w,h=PIL_Image.size
    PIL_Image_Size=ChangeBackground(w,h,600,450,PIL_Image)
    # PIL.ImageShow.show(PIL_Image_Size)
    try:
        #方式一
        #创建画布
        canvas=tkinter.Canvas(root,bg='white',width=598,height=450,borderwidth=1)
        canvas.place(x=5,y=0)
        #加在图片文件
        tk_image_file=ImageTk.PhotoImage(PIL_Image_Size)
        #将图片放置在创建的画布上
        image=canvas.create_image(0,0,anchor='nw',image=tk_image_file)
        # #将图像放置画布上端,也就是主窗口‘前方’
        # canvas.pack(side='top')
        #方法二
        # label=tkinter.Label(root,image=tk_image_file,width=600,height=450)
        # label.place(x=90,y=0)
    except :
        print('加载图像出错')

def SelectBackground(root):
    """
    :param root:
    :return:
    """
    filename=filedialog.askopenfilename(title='选择传输文件')
    if not filename:
        showinfo(title='提示',message='未选择传输文件')
        # 如果没有选择采用默认
        filename='Background.png'
    setBackground(root,filename)
btn_cov=tkinter.Button(root,text='修改背景',font=('黑体',14),width=17,height=1,cursor='hand2',command=lambda :SelectBackground(root),bg='#00FF7F')
btn_cov.place(x=615,y=350)

def CloseEvent(root):
    """
    :param root:
    :return:
    """
    btn_close=tkinter.Button(root,text='退出',font=('黑体',14),width=17,height=1,cursor='hand2',command=root.destroy,background='#708090')
    btn_close.place(x=615,y=400)

def SelectFile(root):
    """
    :param root:
    :return:
    """
    filename=filedialog.askopenfilename(title='选择传输文件')
    if not filename:
        showinfo(title='提示',message='请选择发送文件')
        # 如果没有选择采用默认
        filename='File/hometown.jpg'
    socket_Client=Client.socket_client()
    threading_client=threading.Thread(target=Client.Client_Send_File,args=(socket_Client,filename,root))
    threading_client.start()

btn_client=tkinter.Button(root,text='选择发送文件',font=('黑体',14),width=17,height=1,cursor='hand2',bg='#00FF7F',command=lambda :SelectFile(root))
btn_client.place(x=615,y=90)

def SwitchServer(root):
    """
    :param root:
    :return:
    """
    threading_server=threading.Thread(target=Server.Server_Recv_File)
    threading_server.start()

btn_client=tkinter.Button(root,text='开启发送文件服务端',font=('黑体',14),width=17,height=1,cursor='hand2',bg='#00FF7F',command=lambda :SwitchServer(root))
btn_client.place(x=615,y=140)

def SelectdownloadFile(root):
    """
    :param root:
    :return:
    """
    filename=filedialog.askopenfilename(title='选择下载文件')
    if not filename:
        showinfo(title='提示',message='请选择您要下载的文件')
        #如果没有选择采用默认
        filename='File/hometown.jpg'
    socket_Client=Client.socket_client()
    threading_client=threading.Thread(target=Client.Download_Server,args=(socket_Client,filename,root))
    threading_client.start()

btn_client_down=tkinter.Button(root,text='选择下载文件',font=('黑体',14),width=17,height=1,cursor='hand2',bg='#00FF7F',command=lambda :SelectdownloadFile(root))
btn_client_down.place(x=615,y=210)

def SwitchdownloadServer(root):
    """
    :param root:
    :return:
    """
    threading_server=threading.Thread(target=Server.server_Send_File)
    threading_server.start()

btn_server_send=tkinter.Button(root,text='开启下载文件服务端',font=('黑体',14),width=17,height=1,cursor='hand2',bg='#00FF7F',command=lambda :SwitchdownloadServer(root))
btn_server_send.place(x=615,y=260)


if __name__=='__main__':
    print('PyCharm')
    setBackground(root, filename='Background.png')
    CloseEvent(root)
    root.mainloop()

客户端代码:

import os
import tkinter

import cv2
import json
import socket
import threading
from tkinter import ttk
#读取文件的最大数
max_len=1024

def socket_client():
    #端口号和IP地址
    remote_PORT=5555
    remote_IP=socket.gethostbyname(socket.gethostname())
    remote_addr=(remote_IP,remote_PORT)

    #绑定端口号和IP地址
    socket_Client=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
    socket_Client.connect(remote_addr)
    return socket_Client

def ProgressBar(root,text):
    label=tkinter.Label(root,text=text,font=('黑体',14))
    label.place(x=100,y=500)
    progressbar=ttk.Progressbar(root)
    progressbar.place(x=200,y=500)
    #设置进度条的最大值
    progressbar['maximum']=100
    #设置进度条的长度
    progressbar['length']=280
    #初始化初值
    progressbar['value']=0

    return progressbar

def Client_Send_File(socket_Client,filepath,root):
    """
    :param socket: 客户端套接字
    :param filename: 要传输的文件
    :param root:主窗口
    :return:
    """
    progressbar=ProgressBar(root,'发送进度')
    #分离路径和文件名
    path, filename = os.path.split(filepath)
    print('path: {}'.format(path))
    print('filename: {}'.format(filename))
    #分离文件名和文件后缀
    file, class_file = os.path.splitext(filename)
    #首先将消息头发送至服务端
    #获取文件大小
    # file_size=os.path.getsize(filename)
    file_Size=os.stat(filepath).st_size
    msg_header={'filename':file,'msg_type':class_file,'msg_len':file_Size}
    msg_header_bytes=bytes(json.dumps(msg_header),encoding='utf-8')
    #当消息头的长度不满1024时,使用空格填充
    msg_header_bytes+=b''*(max_len-len(msg_header_bytes))
    socket_Client.send(msg_header_bytes)
    file_len=0
    recv_count=0
    #发送的文件头大小
    print('msg_header_bytes: {}'.format(len(msg_header_bytes)))
    #发送的文件大小
    print('file_size: {}'.format(file_Size))
    with open(filepath,'rb') as fp:
        while file_len!=file_Size:
            message=fp.read(max_len)
            socket_Client.send(message)
            file_len+=len(message)
            progressbar['value']=file_len/file_Size*100
            recv_count+=1
    print('发送次数: {}'.format(recv_count))

    socket_Client.close()
    print('发送完成...')

#客户端从服务端下载文件
def Download_Server(socket_Client,filepath,root):
    """
    :param socket_Client: 客户端套接字
    :param filepath: 文件路径
    :param root: 主窗口
    :return:
    """
    progressbar=ProgressBar(root,'下载进度')
    socket_Client.send(filepath.encode('utf-8'))
    # 获取客户端发送的消息头
    msg_header = socket_Client.recv(max_len)
    header = json.loads(msg_header.decode('utf-8'))
    # 输出客户端发送的消息头信息
    print(header)
    # 保存接收文件的地方
    curr_path = os.getcwd()
    filename = curr_path + '\\client_recv_File\\client_recv_' + header['filename'] + header['msg_type']
    get_file_Size = header['msg_len']
    file_size = 0
    # 输出文件名和文件大小
    print('文件名: {}'.format(filename))
    print('file_size: {}'.format(get_file_Size))
    recv_count = 0
    # 如果文件不存在则创建
    if os.path.exists(filename) == False:
        with open(filename, 'wb') as fp:
            while file_size != get_file_Size:
                message = socket_Client.recv(max_len)
                fp.write(message)
                file_size += len(message)
                progressbar['value']=file_size/get_file_Size*100
                recv_count += 1
    else:
        with open(filename, 'wb') as fp:
            while file_size != get_file_Size:
                message = socket_Client.recv(max_len)
                fp.write(message)
                file_size += len(message)
                progressbar['value'] = file_size / get_file_Size * 100
                recv_count += 1
    print('接收次数: {}'.format(recv_count))
    socket_Client.close()
    print('下载完成...')


if __name__=='__main__':
    print('Pycharm')
    socket_Client=socket_client()
    Client_Send_File(socket_Client,'File\\2014.rar')

服务端代码:

import cv2
import os
import json
import socket
import threading
#读取文件的最大数
max_len=1024

def socket_server():
    # 端口号和IP地址
    remote_PORT = 5555
    remote_IP = socket.gethostbyname(socket.gethostname())
    remote_addr = (remote_IP, remote_PORT)

    # 绑定IP地址和端口号PORT
    socket_Server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    socket_Server.bind(remote_addr)

    # 监听
    socket_Server.listen()
    print('正在监听来自客户端的消息......')
    return socket_Server

def Server_Recv_File():
    """
    :param socket: 服务端套接字
    :param root: 主窗口
    :return:
    """
    socket_Server=socket_server()
    new_socket, addr = socket_Server.accept()
    #获取客户端发送的消息头
    msg_header=new_socket.recv(max_len)
    header=json.loads(msg_header.decode('utf-8'))
    #输出客户端发送的消息头信息
    print(header)
    #保存接收文件的地方
    curr_path=os.getcwd()
    filename=curr_path+'\\server_recv_File\\server_recv_'+header['filename']+header['msg_type']
    get_file_Size=header['msg_len']
    file_size=0
    #输出文件名和文件大小
    print('文件名: {}'.format(filename))
    print('file_size: {}'.format(get_file_Size))
    recv_count=0
    #如果文件不存在则创建
    if os.path.exists(filename)==False:
        with open(filename,'wb') as fp:
            while file_size!=get_file_Size:
                message=new_socket.recv(max_len)
                fp.write(message)
                file_size+=len(message)
                recv_count+=1
    else:
        with open(filename,'wb') as fp:
            while file_size!=get_file_Size:
                message=new_socket.recv(max_len)
                fp.write(message)
                file_size+=len(message)
                recv_count+=1
    print('接收次数: {}'.format(recv_count))
    new_socket.close()
    print('发送完成...')

#服务端接收客户端的下载文件请求,并进行发送
def server_Send_File():
    """
    :param new_socket:
    :return:
    """
    socket_Server = socket_server()
    new_socket, addr = socket_Server.accept()
    filepath=new_socket.recv(max_len).decode('utf-8')
    print('filepath: {}'.format(filepath))
    # 分离路径和文件名
    path, filename = os.path.split(filepath)
    print('path: {}'.format(path))
    print('filename: {}'.format(filename))
    # 分离文件名和文件后缀
    file, class_file = os.path.splitext(filename)
    # 首先将消息头发送至服务端
    # 获取文件大小
    # file_size=os.path.getsize(filename)
    file_Size = os.stat(filepath).st_size
    msg_header = {'filename': file, 'msg_type': class_file, 'msg_len': file_Size}
    msg_header_bytes = bytes(json.dumps(msg_header), encoding='utf-8')
    # 当消息头的长度不满1024时,使用空格填充
    msg_header_bytes += b'' * (max_len - len(msg_header_bytes))
    new_socket.send(msg_header_bytes)
    file_len = 0
    recv_count = 0
    # 发送的文件头大小
    print('msg_header_bytes: {}'.format(len(msg_header_bytes)))
    # 发送的文件大小
    print('file_size: {}'.format(file_Size))
    with open(filepath, 'rb') as fp:
        while file_len != file_Size:
            message = fp.read(max_len)
            new_socket.send(message)
            file_len += len(message)
            recv_count += 1
    print('发送次数: {}'.format(recv_count))

    new_socket.close()
    print('发送完成...')

if __name__=='__main__':
    print('Pycharm')
    Server_Recv_File()

  Python知识库 最新文章
Python中String模块
【Python】 14-CVS文件操作
python的panda库读写文件
使用Nordic的nrf52840实现蓝牙DFU过程
【Python学习记录】numpy数组用法整理
Python学习笔记
python字符串和列表
python如何从txt文件中解析出有效的数据
Python编程从入门到实践自学/3.1-3.2
python变量
上一篇文章      下一篇文章      查看所有文章
加:2022-03-03 16:08:24  更:2022-03-03 16:12:42 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/15 22:37:01-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码