Python套接字编程: Upload files from Client to Server

标签 python sockets unix filesystems virtual-machine

我正在寻找有关 python 套接字编程的一些帮助。
目的:将文件从客户端上传到服务器。我当前的设置涉及两个虚拟机,一个服务器和一个客户端,各自的 .py 文件将驻留在其中; server.py 和 client.py 。我遇到的问题是,当我选择上传选项时,输出显示“文件上传......文件已成功上传”但是当我查看服务器端时,该文件不存在 - 也不存在我收到一个错误。当我发送要上传的文件时,服务器显示它收到了连接。我目前所拥有的如下...任何帮助将不胜感激。

服务器.py

import config, protocol
import os
from socket import *
import threading
import time
import sys


class server():

    # Constructor: load the server information from config file
    def __init__(self):
        self.port, self.path, self.path2 = config.config().readServerConfig()

    # function to receive file data from client 
    def receiveFile(self, serverSocket, fileName):
        serverSocket.connect()
        serverSocket.send(protocol.prepareMsg(protocol.HEAD_UPLOAD, fileName))
        with open(fileName, 'wb') as f:
            print('file incoming...')
            while True:
                print('receiving data...')
                data = serverSocket.recv(1024)
                if not data:
                    break
                f.write(data)
        print(fileName + " has been Received!")
        serverSocket.close()


    # Main function of server, start the file sharing service
    def start(self):
        serverPort=self.port
        serverSocket=socket(AF_INET,SOCK_STREAM)
        serverSocket.bind(('',serverPort))
        serverSocket.listen(20)
        print('The server is ready to receive')
        while True:
            connectionSocket, addr = serverSocket.accept()
            print("**Conn. to ", addr)
            dataRec = connectionSocket.recv(1024)
            header,msg= protocol.decodeMsg(dataRec.decode()) # get client's info, parse it to header and content
            # Main logic of the program, send different content to client according to client's requests
            if(header== protocol.HEAD_REQUEST):
                self.listFile(connectionSocket)
            elif(header == protocol.HEAD_DOWNLOAD):
                self.sendFile(connectionSocket, self.path+"/"+msg)
            elif(header == protocol.HEAD_UPLOAD):
                self.receiveFile(connectionSocket, self.path2+"/"+msg)
            else:
                connectionSocket.send(protocol.prepareMsg(protocol.HEAD_ERROR, "Invalid Message"))
            connectionSocket.close()






def main():
    s=server()
    s.start()

main()


Client.py

import config, protocol
from socket import *
import threading
import time
import os
import sys

class client:

    fileList=[] # list to store the file information
    uploadFileList = []

    #Constructor: load client configuration from config file
    def __init__(self):
        self.serverName, self.serverPort, self.clientPort, self.downloadPath, self.uploadPath = config.config().readClientConfig()

    # Function to produce user menu 
    def printMenu(self):
        print("Welcome to simple file sharing system!")
        print("Please select operations from menu")
        print("--------------------------------------")
        print("3. Upload File")
        print("5. Quit")

    # Function to get user selection from the menu
    def getUserSelection(self):       
        ans=0
        # only accept option 1-4
        while ans>5 or ans<1:
            self.printMenu()
            try:
                ans=int(input())
            except:
                ans=0
            if (ans<=5) and (ans>=1):
                return ans
            print("Invalid Option")

    # Build connection to server
    def connect(self):
        serverName = self.serverName
        serverPort = self.serverPort
        clientSocket = socket(AF_INET, SOCK_STREAM)
        clientSocket.connect((serverName,serverPort))
        return clientSocket

    def getUploadFileList(self):
        self.uploadFileList = os.listdir(self.uploadPath)

    def printUploadFileList(self):
        count = 0
        for f in self.uploadFileList:
            count += 1
            print('{:<3d}{}'.format(count, f))

    def selectUploadFile(self):
        if (len(self.uploadFileList)==0):
            self.getUploadFileList()
        ans=-1
        while ans<0 or ans>len(self.uploadFileList)+1:
            self.printUploadFileList()
            print("Please select the file you want to upload from the list (enter the number of files):")
            try:
                ans=int(input())
            except:
                ans=-1
            if (ans>0) and (ans<len(self.uploadFileList)+1):
                return self.uploadFileList[ans-1]
            print("Invalid number")

    def uploadFile(self, fileName):
        mySocket=self.connect()
        mySocket.send(protocol.prepareMsg(protocol.HEAD_UPLOAD, fileName))
        f = open(fileName, 'rb')
        l = f.read(1024)  # each time we only send 1024 bytes of data
        while (l):
            print('File uploading...')
            mySocket.sendall(l)
            l = f.read(1024)
        f.close()
        print("File Uploaded Successfully!")


    # Main logic of the client, start the client application
    def start(self):
        opt=0
        while opt!=5:
            opt=self.getUserSelection()
            if opt==3:
                self.uploadFile(self.selectUploadFile())
            else:
                pass


def main():
    c=client()
    c.start()


main()


我已经在协议(protocol)文件中定义了模块...

协议(protocol).py

HEAD_LIST='LST'
HEAD_REQUEST='REQ'
HEAD_DOWNLOAD='DLD'
HEAD_UPLOAD='ULD'
HEAD_FILE='FIL'
HEAD_ERROR='ERR'

# we prepare the message that are sent between server and client as the header + content
def prepareMsg(header, msg):
    return (header+msg).encode()

def prepareFileList(header,fList):
    '''
    function to prepare file list to msg
    '''
    msg=header
    for i in range(len(fList)):
        if (i==len(fList)-1):
            msg+=fList[i]
        else:
            msg+=fList[i]+','
    return msg.encode()

# Decode the received message, the first three letters are used as protocol header
def decodeMsg(msg):
    if (len(msg)<=3):
        return HEAD_ERROR, 'EMPTY MESSAGE'
    else:
        return msg[0:3],msg[3:len(msg)]

我还定义了我的配置文件,如下......
Config.py

class config:
    #define header
    server_port='SERVER_PORT'
    path="PATH"
    path2="PATH2"
    server="SERVER"
    client_port="CLIENT_PORT"
    download="DOWNLOAD"
    upload="UPLOAD"
    serverConfig="server.config"
    clientConfig="client.config"

    def __init__(self):
        pass
    def readServerConfig(self):
        try:
            with open(self.serverConfig,'r') as f:
                serPort=0
                sharePath=""
                sharePath2=""
                for l in f:
                    sub=l.strip().split("=")
                    if(sub[0]==self.server_port):
                        serPort=int(sub[1])
                    elif(sub[0]==self.path):
                        sharePath=sub[1]
                    elif (sub[0] == self.path2):
                        sharePath2 = sub[1]


                    else:
                        pass
                return serPort, sharePath, sharePath2
        except:
            print(Exception.message())




    def readClientConfig(self):
        '''
        This function read client configuration file, return four values
        @return: serverName
        @return: serverPort
        @return: clientPort
        @return: downloadPath
        '''
        try:
            with open(self.clientConfig,'r') as f:
                serPort=0
                serName=""
                clientPort=0
                downPath=""
                upPath=""
                for l in f:
                    sub=l.strip().split("=")
                    if(sub[0]==self.server_port):
                        serPort=int(sub[1])
                    elif(sub[0]==self.server):
                        serName=sub[1]
                    elif(sub[0]==self.client_port):
                        clientPort=sub[1]   
                    elif(sub[0]==self.download):
                        downPath=sub[1]
                    elif(sub[0]==self.upload):
                        upPath=sub[1]
                    else:
                        pass  
                return serName, serPort, clientPort, downPath, upPath
        except:
            print(Exception.message())

# The function to test the configuration class           
def test():
    conf=config()
    client=conf.readClientConfig()
    server=conf.readServerConfig()
    print(client)
    print(server)

上面的代码将返回一个文件列表,我可以选择要上传的文件,代码将说明其完整,但我在服务器上找不到文件。我在两台机器上的目录路径中设置了测试文件。另外,我的 server.config 和 client.config 文件设置为:
服务器配置

SERVER_PORT=12007
PATH=/root/serverFiles
PATH2=/root/files


client.config

SERVER=192.168.10.1
SERVER_PORT=12007
CLIENT_PORT=12006
DOWNLOAD=/root/Downloads
UPLOAD=/root/Upload

最佳答案

您的 uploadFile() 方法将 connect() 到服务器,然后 sendall() 文件内容(以 1024 字节 block 为单位) .

另一方面,您的服务器将接收前 1024 个字节(即文件 内容的前 1024 个字节),并根据协议(protocol)对其进行解释,查看文件内容的前三个字节。然而,客户端永远不会像服务器期望的那样发送 protocol.HEAD_UPLOAD

(顺便说一句,我真的会向您推荐 PEP8 代码,并避免导入 * 。它使代码更易于阅读,从而提供帮助。)

关于Python套接字编程: Upload files from Client to Server,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53353987/

相关文章:

python - 如何改成sigmoid来学习多标签分类

c++ - C++中的事件调度

c - 当我使用 '' 关闭发送对等方的套接字时,为什么接收对等方的套接字不断接收 "control-c"

c - 当套接字设置为非阻塞时,有什么方法可以在阻塞模式下临时使用 send 或 recv

linux - 能否简化以下测试条件

python - Kerberos 安装错误,错误 : Setup script exited with error: command 'i686-linux-gnu-gcc' failed with exit status 1

python argparse : prefix or smart matching on sub parsers

python - NeuralNetwork 类无法访问其属性

在 C 中检查正在运行的进程

python - 无法使用 Python Paramiko 执行带有重定向多行输入的 shell 命令