【问题标题】:How to send file client to client python 3如何将文件客户端发送到客户端python 3
【发布时间】:2018-10-27 01:04:30
【问题描述】:

我重新搜索了这个主题,但没有结果。我已经在 python 中创建了一个客户端到客户端的通信,但我需要知道如何通过在控制台中插入文件路径来将文件从一个发送到另一个。

def send_file(path):
    file = open(path, "r")
    msg = file.readline()
    while msg:
        signature = signing_key.sign(msg.encode(), encoding="hex")
        msg = msg + "~" + signature.decode()
        client_socket.send(bytes(msg, "utf8"))
        msg = file.readline()
    file.close()

def receive_file(msg):
    file = open("new.txt", "w")
    file.write(msg)
    file.close()

编辑: 1.服务器

#!/usr/bin/env python3
"""Server for multithreaded (asynchronous) chat application."""
from socket import AF_INET, socket, SOCK_STREAM
from threading import Thread


def accept_incoming_connections():
    """Sets up handling for incoming clients."""
    while True:
        client, client_address = SERVER.accept()
        print("%s:%s has connected." % client_address)
        client.send(bytes("Greetings from the cave!", "utf8"))
        addresses[client] = client_address
        Thread(target=handle_client, args=(client,)).start()


def handle_client(client):  # Takes client socket as argument.
    """Handles a single client connection."""

    name = client.recv(BUFSIZ).decode("utf8")
    welcome = 'Welcome %s! If you ever want to quit, type {quit} to exit.' % name
    client.send(bytes(welcome, "utf8"))
    msg = "%s has joined the chat!" % name
    broadcast(bytes(msg, "utf8"))
    clients[client] = name

    while True:
        msg = client.recv(BUFSIZ)
        if msg != bytes("{quit}", "utf8"):
            broadcast(msg, name + ": ")
        else:
            client.send(bytes("{quit}", "utf8"))
            client.close()
            del clients[client]
            broadcast(bytes("%s has left the chat." % name, "utf8"))
            break


def broadcast(msg, prefix=""):  # prefix is for name identification.
    """Broadcasts a message to all the clients."""
    print(msg)
    for sock in clients:
        sock.send(bytes(prefix, "utf8") + msg)


clients = {}
addresses = {}

HOST = '127.0.0.1'
PORT = 33000
BUFSIZ = 1024
ADDR = (HOST, PORT)

SERVER = socket(AF_INET, SOCK_STREAM)
SERVER.bind(ADDR)

if __name__ == "__main__":
    SERVER.listen(5)
    print("Waiting for connection...")
    ACCEPT_THREAD = Thread(target=accept_incoming_connections)
    ACCEPT_THREAD.start()
    ACCEPT_THREAD.join()
    SERVER.close()

2:这是我们可以运行多个客户端实例的客户端,因此连接将是客户端到使用服务器作为中间件的客户端

#!/usr/bin/env python3
"""Script for Tkinter GUI chat client."""
from socket import AF_INET, socket, SOCK_STREAM
from threading import Thread

import tkinter


def receive():
    """Handles receiving of messages."""
    while True:
        try:
            msg = client_socket.recv(BUFSIZ).decode("utf8")
            msg_list.insert(tkinter.END, msg)
        except OSError:  # Possibly client has left the chat.
            break


def send(event=None):  # event is passed by binders.
    """Handles sending of messages."""
    msg = my_msg.get()
    my_msg.set("")  # Clears input field.
    client_socket.send(bytes(msg, "utf8"))
    if "/" in msg:
        send_file(msg)
    if msg == "{quit}":
        client_socket.close()
        top.quit()


def on_closing(event=None):
    """This function is to be called when the window is closed."""
    my_msg.set("{quit}")
    send()


def send_file(path):
    file = open('file.txt', "r")
    msg = file.readline()
    while msg:
        client_socket.send(bytes(msg, "utf8"))
        msg = file.readline()
    file.close()


def receive_file(msg):
    file = open("new.txt", "w")
    file.write(msg)
    file.close()


top = tkinter.Tk()
top.title("Chatter")

messages_frame = tkinter.Frame(top)
my_msg = tkinter.StringVar()  # For the messages to be sent.
scrollbar = tkinter.Scrollbar(messages_frame)  # To navigate through past messages.
# Following will contain the messages.
msg_list = tkinter.Listbox(messages_frame, height=15, width=50, yscrollcommand=scrollbar.set)
scrollbar.pack(side=tkinter.RIGHT, fill=tkinter.Y)
msg_list.pack(side=tkinter.LEFT, fill=tkinter.BOTH)
msg_list.pack()
messages_frame.pack()

entry_field = tkinter.Entry(top, textvariable=my_msg)
entry_field.bind("<Return>", send)
entry_field.pack()
send_button = tkinter.Button(top, text="Send", command=send)
send_button.pack()

top.protocol("WM_DELETE_WINDOW", on_closing)

#----Now comes the sockets part----
HOST = input('Enter host: ')
PORT = input('Enter port: ')
if not PORT:
    PORT = 33000
else:
    PORT = int(PORT)

BUFSIZ = 1024
ADDR = (HOST, PORT)

client_socket = socket(AF_INET, SOCK_STREAM)
client_socket.connect(ADDR)

receive_thread = Thread(target=receive)
receive_thread.start()
tkinter.mainloop()  # Starts GUI execution.

【问题讨论】:

    标签: python-3.x file server client send


    【解决方案1】:

    真的很难说你的问题出在哪里。我认为 receive_file 函数中的msg 不是完整的文件,而只是其中的一部分。其背后的原因是socket.recv 方法与read() 不同,它不返回“所有”数据,而只返回在调用之前收到的部分数据(并且存在一些缓冲区限制,这并不重要)。所以你需要先接收所有数据,然后再写入文件。

    为此,您必须设法做到这一点。第一个只是将所有传入数据保存到内存中,直到连接关闭。第二个先发送信息,发送方发送多大的文件,然后读取数据,直到传输完成。第二种方法的优点是您可以对多个文件使用相同的连接。

    这里是完整的服务器-客户端实现(实现第二种方式):

    #send_recv.py
    import struct
    import sys
    import socket
    
    def send_file(path, sock):
        with open(path, "rb") as file:
            # First read file into memory
            content = file.read()
            # Now calculate size and convert it into 8-byte long bytes sequence
            size = struct.pack("<Q", len(content))
            # Send the file size
            sock.send(size)
            # Send the file
            sock.send(content)
    
    
    def recv_file(path, sock):
        with open(path, "wb") as file:
            # Receive size of file
            received = sock.recv(8)
            # Convert the 8-byte long sequence into integer
            size, = struct.unpack("<Q", received)
            # Start receiving data until the whole file is received
            received = 0
            while received < size:
                data = sock.recv(4096)
                file.write(data)
                received += len(data)
    
    
    if __name__ == "__main__":
        with socket.socket() as s:
            s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
            if sys.argv[1] == "-s":
                s.bind(("localhost", 55000))
                s.listen(1)
                conn, addr = s.accept()
                with conn:
                    print("Sending file {}".format(sys.argv[2]))
                    send_file(sys.argv[2], conn)
            elif sys.argv[1] == "-c":
                s.connect(("localhost", 55000))
                print("Receiving into file {}".format(sys.argv[2]))
                recv_file(sys.argv[2], s)
    

    用法:

    • python3 send_recv.py -s some_file - 启动服务器发送文件
    • python3 send_recv.py -c some_file - 开始客户端接收文件

    注意:使用 Python 3.6 测试

    你还应该添加一些错误检查。

    【讨论】:

    • 它会抛出一个错误:if sys.argv[1] == "-s": IndexError: list index out of range
    • 我会把我的整个申请贴在上面,让你看看!
    猜你喜欢
    • 2013-05-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-06-18
    相关资源
    最近更新 更多