Skip to content Skip to sidebar Skip to footer

Sending Multiple Files Python Using Socket

I currently am trying to create a client-server application in which the client can send multiple files to the server using TCP protocol. The server will eventually create a hash-a

Solution 1:

One way to handle what you're doing is to buffer your socket data. Below is a class that buffers data and knows how to send and receive null-terminated, UTF-8-encoded strings, and raw chunks of bytes:

buffer.py:

classBuffer:
    def__init__(self,s):
        '''Buffer a pre-created socket.
        '''
        self.sock = s
        self.buffer = b''defget_bytes(self,n):
        '''Read exactly n bytes from the buffered socket.
           Return remaining buffer if <n bytes remain and socket closes.
        '''whilelen(self.buffer) < n:
            data = self.sock.recv(1024)
            ifnot data:
                data = self.buffer
                self.buffer = b''return data
            self.buffer += data
        # split off the message bytes from the buffer.
        data,self.buffer = self.buffer[:n],self.buffer[n:]
        return data

    defput_bytes(self,data):
        self.sock.sendall(data)

    defget_utf8(self):
        '''Read a null-terminated UTF8 data string and decode it.
           Return an empty string if the socket closes before receiving a null.
        '''whileb'\x00'notin self.buffer:
            data = self.sock.recv(1024)
            ifnot data:
                return''
            self.buffer += data
        # split off the string from the buffer.
        data,_,self.buffer = self.buffer.partition(b'\x00')
        return data.decode()

    defput_utf8(self,s):
        if'\x00'in s:
            raise ValueError('string contains delimiter(null)')
        self.sock.sendall(s.encode() + b'\x00')

With this class, your client and server become:

client.py:

import socket
import threading
import os

import buffer

HOST = '127.0.0.1'
PORT = 2345

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((HOST, PORT))

with s:
    sbuf = buffer.Buffer(s)

    hash_type = input('Enter hash type: ')

    files = input('Enter file(s) to send: ')
    files_to_send = files.split()

    for file_name in files_to_send:
        print(file_name)
        sbuf.put_utf8(hash_type)
        sbuf.put_utf8(file_name)

        file_size = os.path.getsize(file_name)
        sbuf.put_utf8(str(file_size))

        withopen(file_name, 'rb') as f:
            sbuf.put_bytes(f.read())
        print('File Sent')

server.py:

import socket
import os

import buffer

HOST = ''
PORT = 2345# If server and client run in same local directory,# need a separate place to store the uploads.try:
    os.mkdir('uploads')
except FileExistsError:
    pass

s = socket.socket()
s.bind((HOST, PORT))
s.listen(10)
print("Waiting for a connection.....")

whileTrue:
    conn, addr = s.accept()
    print("Got a connection from ", addr)
    connbuf = buffer.Buffer(conn)

    whileTrue:
        hash_type = connbuf.get_utf8()
        ifnot hash_type:
            breakprint('hash type: ', hash_type)

        file_name = connbuf.get_utf8()
        ifnot file_name:
            break
        file_name = os.path.join('uploads',file_name)
        print('file name: ', file_name)

        file_size = int(connbuf.get_utf8())
        print('file size: ', file_size )

        withopen(file_name, 'wb') as f:
            remaining = file_size
            while remaining:
                chunk_size = 4096if remaining >= 4096else remaining
                chunk = connbuf.get_bytes(chunk_size)
                ifnot chunk: break
                f.write(chunk)
                remaining -= len(chunk)
            if remaining:
                print('File incomplete.  Missing',remaining,'bytes.')
            else:
                print('File received successfully.')
    print('Connection closed.')
    conn.close()

Demo

client:

Enter hashtype: abc
Enter file(s) to send: demo1.dat demo2.dat
demo1.dat
File Sent
demo2.dat
File Sent

server:

Waiting for a connection.....
Got a connection from  ('127.0.0.1', 22126)
hashtype:  abc
file name:  uploads\demo1.dat
file size:  488892
File received successfully.
hashtype:  abc
file name:  uploads\demo2.dat
file size:  212992
File received successfully.
Connection closed.

Solution 2:

1. file_size = conn.recv(1024) In your server code you read 1024 bytes as your file_size, file_size is only 4 or 8 bytes long

2. file_name = conn.recv(1024) Your server don't know how long the filename/hashtype is.

-> Use a long for both sizes and read only sizeof(long) bytes from the stream.

You can use https://docs.python.org/2/library/struct.html for packing/encoding of these numbers

-> Or just go the easy way and use https://docs.python.org/3/library/pickle.html for serialization

Post a Comment for "Sending Multiple Files Python Using Socket"