繁体   English   中英

使用 python 套接字编程发送多个数据包

[英]send multiple packets of data using python socket programming

所以现在我有一个服务器和客户端脚本。 我正在尝试将文件从客户端上传到服务器。 但是,客户端中文件的数据将被 HEADER 大小剪切掉。 如何在同一个发送命令下将多个数据包发送到服务器?

服务器.py:

import socket
import threading
HEADER=2048
PORT=5050
SERVER=socket.gethostbyname(socket.gethostname())
ADDR=(SERVER,PORT)
FORMAT='utf-8'
DISCONNECT_MESSAGE='!DISCONNECT'
SEPARATOR='<SEPERATE>'
server=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
server.bind(ADDR)
def handle_client(conn,addr):
    print(f'[NEW CONNECTION] {addr} connected.')
    connected=True
    while connected:
        data=conn.recv(HEADER).decode(FORMAT)
        if data==DISCONNECT_MESSAGE:
            connected=False
        else:
            data=data.split(SEPARATOR)
            file=open(data[0],'w')
            file.write(data[1])
            print('file received')
            conn.send('file received'.encode(FORMAT))         
    conn.close()
    print(f'[DISCONNECT] {addr} disconnected')

def start():
    server.listen()
    print(f'[LISTENING] Server is listening on {SERVER}')
    while True:
        conn,addr=server.accept()
        thread=threading.Thread(target=handle_client,args=(conn,addr))
        thread.start()
        print(f'[ACTIVE CONNECTIONS] {threading.activeCount()-1}')
print("[STARTING] server is starting...")
start()

客户端.py:

import socket
HEADER=2048
PORT=5050
FORMAT='utf-8'
DISCONNECT_MESSAGE='!DISCONNECT'
SEPARATOR='<SEPERATE>'
SERVER=socket.gethostbyname(socket.gethostname())
ADDR=(SERVER,PORT)
client=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
client.connect(ADDR)
def send(msg):
    message=msg.encode(FORMAT)
    client.send(message)
    print(client.recv(HEADER).decode(FORMAT))
file=open('question_pool.csv','r')
data=file.read()
send(f'question_pool.csv{SEPARATOR}{data}')
file.close()
send(DISCONNECT_MESSAGE)

简而言之,您想要发送大于HEADER大小的任何文件的多个块。 将文件拆分为小于HEADER大小的块,并单独发送每个块。 然后,当所有块都设置好后,发送一条消息,说明整个文件已发送,以便服务器可以保存它。

这是我用于上述解决方案的代码:
server.py

import socket
import threading


HEADER = 2048
PORT = 5050
SERVER = socket.gethostbyname(socket.gethostname())
ADDR = (SERVER, PORT)
FORMAT = 'utf-8'
DISCONNECT_MESSAGE = '!DISCONNECT'
SEPARATOR = '<SEPERATE>'
FILE_FINISHED_SENDING = '<!FILE_SENT!>'

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


def handle_client(conn, addr):
    print(f'[NEW CONNECTION] {addr} connected.')
    connected = True
    current_file = None

    while connected:
        data = conn.recv(HEADER).decode(FORMAT)
        if data == DISCONNECT_MESSAGE:
            connected = False
        elif data == FILE_FINISHED_SENDING:
            current_file.close()
            current_file = None
            conn.send(b'file received.')
        else:
            data = data.split(SEPARATOR)
            if len(data) == 2 and data[1] == '':
                # The name of the file was sent, more will follow.
                current_file = open(data[0], 'w')
                conn.send(b'filename recieved')
            else:
                # File data was send, so write it to the current file
                current_file.write(data[1])
                print('chunk of file recv''d')
                conn.send(b'chunk received')
    conn.close()
    print(f'[DISCONNECT] {addr} disconnected')



def start():
    server.listen()
    print(f'[LISTENING] Server is listening on {SERVER}')
    while True:
        conn, addr = server.accept()
        thread = threading.Thread(target=handle_client, args=(conn,addr))
        thread.start()
        print(f'[ACTIVE CONNECTIONS] {threading.activeCount()-1}')


print("[STARTING] server is starting...")
start()

client.py

import socket
from pathlib import Path

HEADER = 2048
PORT = 5050
FORMAT = 'utf-8'
DISCONNECT_MESSAGE = '!DISCONNECT'
SEPARATOR = '<SEPERATE>'
FILE_FINISHED_SENDING = '<!FILE_SENT!>'
SERVER = socket.gethostbyname(socket.gethostname())
ADDR = (SERVER, PORT)

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


def chunker(string: str, size: int):
    return (string[pos:pos + size] for pos in range(0, len(string), size))


def send(msg):
    message = msg.encode(FORMAT)
    client.send(message)
    print(client.recv(HEADER).decode(FORMAT))


def send_file(filepath: str):
    with open(filepath, 'r', encoding=FORMAT) as f:
        data = f.read()

    first_bits = f'{Path(filepath).name}{SEPARATOR}'  # Easy way of getting just a file's name from its path
    send(first_bits)  # Send the filename to the server
    for chunk in chunker(data, HEADER-48):  # Leave a safe buffer
        # Send each chunk of the file
        send(f"{SEPARATOR}{chunk}")

    # Tell the server that's all for this file.
    # Now it can close the file object.
    send(FILE_FINISHED_SENDING)


send_file("/path/to/file.html")
send(DISCONNECT_MESSAGE)

提示:

  • 确保您的特殊消息,如SEPARATORFILE_FINISHED_SENDINGDISCONNECT_MESSAGE不会出现在您发送的文件中。 否则事情可能会变得不稳定。
  • 当您通过套接字发送文件时,您可能希望将文件作为原始字节读取,而不是作为字符串读取、编码、解码等。这样您就可以发送二进制文件,例如.mp3

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM