在客户端和服务器之间传输文件(套接字错误和属性错误)

2024-10-01 00:20:45 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在尝试通过TCP套接字发送和接收文件

有很多问题
1当客户端连接到服务器时。服务器不“打印客户端连接…”,但在使用命令后打印。
2当我在服务器上使用'put'命令时发生了一个错误套接字错误:[Errno 107]传输终结点未连接,但文件映像已上载到服务器。
三。当我在客户端使用'get'命令时。我无法继续使用其他命令。
4最后一个问题是客户端无法退出并从服务器中列出文件。它显示AttributeError:“module”对象没有属性“send”

服务器

import socket
import sys
import os
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 'Client connected ..'
    reqCommand = conn.recv(2048)
    print 'Client> %s' %(reqCommand)
    if (reqCommand == 'quit'):
        break

    #list file on server
    elif (reqCommand == 'lls'):
        start_path = os.listdir('.') # server directory
        for path,dirs,files in os.walk(start_path):
            for filename in files:
                print os.path.join(filename)

    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:
                while True:
                    data = socket.recv(1024)
                    # print data
                    if not data:
                        break
                    # print data
                    file_to_write.write(data)
                    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()

客户

^{pr2}$

Tags: topathin命令服务器客户端datastring
1条回答
网友
1楼 · 发布于 2024-10-01 00:20:45

除此之外,您还需要在传输协议中添加“帧”。当您在流套接字上执行send操作时,数据将被添加到一个缓冲区中,该缓冲区最终将被传递到另一端。然而,该缓冲器的大小是传送到另一侧的而不是。换句话说,假设您使用命令"put myfile.txt"发送一个初始段。然后从myfile.txt发送数据。现在因为您使用的是file object iterator(for data in file_to_send),所以实际上一次只向它发送一行(可以说,对于文件传输协议,读取和发送固定的块更有意义,但这也可以工作)。假设myfile.txt的第一行是"The quick brown fox\n"

当服务器进行第一次接收时,它可以接收"put "或{}或{}或{}命令以及整个文件内容。这是因为流协议(TCP)不为您维护消息边界。在

实际上,在第一次接收时,您可能只接收到"put myfile.txt",但指望它是非常不明智的,因为这取决于发送和接收系统上各种因素的时间安排,而这些因素都超出了您的控制范围。在

因此,有两种常见的处理方法:

  1. 在开始处添加一个长度,该长度描述命令和任何命令参数的大小(以便您知道要传输的实际文件数据在流中的何处开始)。(大多数二进制文件传输协议都是这样工作的)

  2. 在命令末尾添加一些已知的分隔符,例如'\n'。例如,HTTP就是这样工作的。

同样地,你的接收端需要确保它在每一点上都读取所需的数据量,以便保存正在传输的文件的完整内容。在

这意味着您要么(a)小心地recv恰好是命令数据所需的字节数,然后单独处理文件内容,要么(b)recv将初始数据块放入缓冲区,然后精确地分割出“command”所需的内容,并确保其余部分稍后将作为文件数据进行处理。选项(b)通常可以通过在套接字上构建一个file对象来实现(请参见socket.makefile),然后使用file对象的readline方法只获得第一行。在

代码的其他问题:

  1. socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)是个非常糟糕的主意。您刚刚通过创建一个同名的变量隐藏了整个socket模块。例如,如果您试图在下一行中再次引用socket.AF_INET,您将得到异常AttributeError: '_socketobject' object has no attribute 'AF_INET'。您应该给变量起其他名称,比如说socket1,就像在客户端那样。

  2. 在客户端,你有相反的问题。您试图使用socketobject方法,但是提供了socket模块对象。(这就是您得到AttributeError: 'module' object has no attribute 'send')您需要重新组织代码,以便像在putget函数中那样,对已连接的套接字对象调用send方法。

  3. 出现错误socket.error: [Errno 107] Transport endpoint is not connected,因为您试图在侦听套接字上recv,而不是连接的套接字(conn,它由socket.accept返回)。使用侦听套接字可以做的唯一事情是accept新连接(或close)。

  4. 您应该使用sendall而不是send来确保每个字节都被发送。一般来说,所有的数据也将与send一起发送,但在某些情况下,这种情况不会发生。

  5. 服务器中的文件接收循环以while True:开始,但始终是breaks。因此,它只接收第一个数据块(最多1024个字节)。如果文件比这个大,你肯定会截短它。

  6. 您的服务器文件列表函数(lls命令)不会将其输出发送回客户端,它只是printin把它放到服务器端的控制台上。(别忘了,您需要在发回的文件名之间提供某种分隔符,否则它们将全部串联成一个大字符串。)

相关问题 更多 >