Сокеты TCP для отправки и получения файлов с использованием python

Я пытаюсь создать простую клиент-серверную программу для отправки и получения файлового сервера с использованием сокетов tcp. Поскольку получение файлов с сервера не является проблемой, сервер создает файл с тем же именем и помещает данные в этот файл, но когда дело доходит до размещения файлов на сервере, иногда это работает отлично, но всегда есть шанс, поэтому в основном сервер получает имя файла вместе с содержимым файла, и вместо того, чтобы записывать его в файл, он записывает и имя файла, и содержимое как новое имя файла, и этот файл остается пустым. Будет большой помощью, если кто-то может предложить какое-либо решение.

server.py

import socket
import sys
HOST = 'localhost'
PORT = 3820

socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
socket.bind((HOST, PORT))

socket.listen(1)
while (1):
    conn, addr = socket.accept()
    print 'New client connected ..'
    reqCommand = conn.recv(1024)
    print 'Client> %s' %(reqCommand)
    if (reqCommand == 'quit'):
        break
    #elif (reqCommand == lls):
        #list file in server directory
    else:
        string = reqCommand.split(' ', 1)   #in case of 'put' and 'get' method
        reqFile = string[1]

        if (string[0] == 'put'):
            with open(reqFile, 'wb') as file_to_write:
                data=conn.recv(1024)
                while True:
                    if not data:
                        break
                    else:
                        file_to_write.write(data)
                        data=conn.recv(1024)
                    file_to_write.close()
                    break
            print 'Receive Successful'
        elif (string[0] == 'get'):
            with open(reqFile, 'rb') as file_to_send:
                for data in file_to_send:
                    conn.sendall(data)
            print 'Send Successful'
    conn.close()

socket.close()

client.py

    import socket
import sys

HOST = 'localhost'    # server name goes in here
PORT = 3820


def put(commandName):
    socket1 = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    socket1.connect((HOST, PORT))
    socket1.send(commandName)
    string = commandName.split(' ', 1)
    inputFile = string[1]
    with open('clientfolder/'+inputFile, 'rb') as file_to_send:
        data=file_to_send.read(1024)
        while(data):
            socket1.send(data)
            data=file_to_send.read(1024)
            file_to_send.close()
    print 'PUT Successful'
    socket1.close()
    return


def get(commandName):
    socket1 = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    socket1.connect((HOST, PORT))
    socket1.send(commandName)
    string = commandName.split(' ', 1)
    inputFile = string[1]
    with open('clientfolder/'+inputFile, 'wb') as file_to_write:
        while True:
            data = socket1.recv(1024)
            # print data
            if not data:
                break
            # print data
            file_to_write.write(data)
    file_to_write.close()
    print 'GET Successful'
    socket1.close()
    return


msg = raw_input('Enter your name: ')
while(1):
    print 'Instruction'
    print '"put [filename]" to send the file the server '
    print '"get [filename]" to download the file from the server '
    print '"ls" to list all files in this directory'
    print '"lls" to list all files in the server'
    print '"quit" to exit'
    sys.stdout.write('%s> ' % msg)
    inputCommand = sys.stdin.readline().strip()
    if (inputCommand == 'quit'):
        socket.send('quit')
        break
    # elif (inputCommand == 'ls')
    # elif (inputCommand == 'lls')
    else:
        string = inputCommand.split(' ', 1)
        if (string[0] == 'put'):
            put(inputCommand)
        elif (string[0] == 'get'):
            get(inputCommand)
#current working directory is server location
#get will get file from current directory to clientfolder directory.

person Zanis Ali    schedule 17.10.2017    source источник


Ответы (1)


TCP — это протокол потоковой передачи, поэтому вам необходимо разработать разрывы сообщений в своем протоколе. Например:

s.send('put filename')
s.send('data')

Можно получить как:

s.recv(1024)
# 'put filenamedata'

Таким образом буферизовать полученные данные и извлекать только полные сообщения. Один из способов — отправить размер сообщения перед самим сообщением.

person Mark Tolonen    schedule 17.10.2017
comment
попытался сначала отправить имя файла, но вместо решения проблемы имя файла дублируется - person Zanis Ali; 17.10.2017