【问题标题】:Python 3: Sending files through socket. (Client-Server Program)Python 3:通过套接字发送文件。 (客户端-服务器程序)
【发布时间】:2019-01-01 21:39:35
【问题描述】:

我遇到了上述问题。假设客户端询问文件名并将文件名发送到服务器,之后服务器将打开文件并显示它。问题是服务器没有打开文件并显示它。

下面是客户端。

#!/usr/bin/env python3 
import socket, os.path, datetime, sys

def Main():
    host = '127.0.0.1'
    port = 50001

    s = socket.socket()
    s.connect((host, port))

    Filename = input("Type in ur file ")
    s.send(Filename.encode('utf-8'))
    data = s.recv(1024).decode('utf-8')
    s.close()

if __name__ == '__main__':
    Main()

下面是服务器

#!/usr/bin/env python3

import socket
import os
import sys



def Main():
    host = '127.0.0.1'
    port = 50001

    s = socket.socket()
    s.bind((host,port))
    print("server Started")
    s.listen(1)
    c, addr = s.accept()
    print("Connection from: " + str(addr))
    while True:
        data = c.recv(1024).decode('utf-8')
        myfile = open(data, "r")
        if not data:
            break
        print("from connected user: " + myfile)

    c.close()

if __name__ == '__main__':
    Main()

【问题讨论】:

标签: python python-3.x sockets


【解决方案1】:

我对您运行的代码进行了一些最小的调整,以便server.py 持续侦听给定端口并发送回client.py 每次调用所要求的数据。

server.py

#!/usr/bin/env python3
import socket
import os
import sys

def Main():
    host = '127.0.0.1'
    port = 50001

    s = socket.socket()
    s.bind((host,port))
    print("server Started")
    s.listen(1)
    while True:
        c, addr = s.accept()
        print("Connection from: " + str(addr))
        filename = ''
        while True:
            data = c.recv(1024).decode('utf-8')
            if not data:
                break
            filename += data
        print("from connected user: " + filename)
        myfile = open(filename, "rb")
        c.send(myfile.read())
        c.close()

if __name__ == '__main__':
    Main()

client.py

#!/usr/bin/env python3 
import socket, os.path, datetime, sys

def Main():
    host = '127.0.0.1'
    port = 50001

    s = socket.socket()
    s.connect((host, port))

    Filename = input("Type in ur file ")
    s.send(Filename.encode('utf-8'))
    s.shutdown(socket.SHUT_WR)
    data = s.recv(1024).decode('utf-8')
    print(data)
    s.close()

if __name__ == '__main__':
    Main()

现在解释一下。

在服务器端。外部循环接受一个连接,然后从连接中读取直到完成(稍后会详细介绍)。打印您的调试信息,但请注意您尝试print 文件对象而不是文件名(尝试连接将失败)。我还以二进制模式打开文件(这样我可以跳过 str -> bytes 翻译。

在客户端。我添加了在发送文件时关闭套接字的写入端。请注意,对于此用例,您可能希望使用 sendall 而不是 send:查看这些文档链接以获取详细信息。我为传入的数据添加了print。

现在关闭客户端中的写入端和内部循环读取(也与sendall 提示有关。顺便说一句,服务器端也适用,否则你应该循环,如你所见您的内容被截断;其他选择是也有一个发送循环。)。流套接字将保证您按照发送它们的顺序获取字节。它本身不知道您的消息是否完整,它也不保证发送和接收数据的数量和大小(分别)。

服务器的内部循环继续读取直到我们看到EOF(我们在pythonsocket中收到零长度字符串)。这会发生(当远程套接字(或至少其写入端)已关闭时,由recv 返回。由于我们仍然想重用连接,我们只在客户端的发送端这样做。希望这个帮助您前进。

【讨论】:

  • 哇哦。它实际上现在打印文件内容。刚刚有一个问题,以二进制模式打开文件会不会限制文件的功能?例如,如果我在 r 模式下打开文件,我可以执行 myfile.readline() 但我不能在 rb 模式下执行此操作。
  • 如有疑问,请查看docs。 TL;DR:您可以使用readline()。除了bytes/str 的差异以及大部分幕后细节之外,您应该在那些更高级别的接口上获得相同的行为。这并不是那么重要,但基本上,我认为没有必要来回转换数据。因此,我会将所有转换留给客户端,以处理与人类交谈的控制台输入/输出。我也有点懒惰。
  • 好的。我明白你的解释。非常感谢你的帮助。今天学习了很多东西。 ^^
  • this >> decode('utf-8') 对于二进制类型的文件(例如图片或视频)还不错?
猜你喜欢
  • 2016-03-03
  • 2015-05-17
  • 2017-07-10
  • 1970-01-01
  • 2012-12-15
  • 2011-08-12
  • 1970-01-01
  • 1970-01-01
  • 2012-12-01
相关资源
最近更新 更多