在 Python 中通过 TCP 套接字发送文件

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/27241804/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-19 01:33:38  来源:igfitidea点击:

Sending a file over TCP sockets in Python

pythonfilesocketspython-2.7tcp

提问by Swaathi Kakarla

I've successfully been able to copy the file contents (image) to a new file. However when I try the same thing over TCP sockets I'm facing issues. The server loop is not exiting. The client loop exits when it reaches the EOF, however the server is unable to recognize EOF.

我已经成功地将文件内容(图像)复制到一个新文件中。然而,当我通过 TCP 套接字尝试同样的事情时,我遇到了问题。服务器循环没有退出。客户端循环在到达 EOF 时退出,但是服务器无法识别 EOF。

Here's the code:

这是代码:

Server

服务器

import socket               # Import socket module

s = socket.socket()         # Create a socket object
host = socket.gethostname() # Get local machine name
port = 12345                 # Reserve a port for your service.
s.bind((host, port))        # Bind to the port
f = open('torecv.png','wb')
s.listen(5)                 # Now wait for client connection.
while True:
    c, addr = s.accept()     # Establish connection with client.
    print 'Got connection from', addr
    print "Receiving..."
    l = c.recv(1024)
    while (l):
        print "Receiving..."
        f.write(l)
        l = c.recv(1024)
    f.close()
    print "Done Receiving"
    c.send('Thank you for connecting')
    c.close()                # Close the connection

Client

客户

import socket               # Import socket module

s = socket.socket()         # Create a socket object
host = socket.gethostname() # Get local machine name
port = 12345                 # Reserve a port for your service.

s.connect((host, port))
s.send("Hello server!")
f = open('tosend.png','rb')
print 'Sending...'
l = f.read(1024)
while (l):
    print 'Sending...'
    s.send(l)
    l = f.read(1024)
f.close()
print "Done Sending"
print s.recv(1024)
s.close                     # Close the socket when done

Here's the screenshot:

这是屏幕截图:

ServerServer

服务器服务器

ClientClient

客户客户

Edit 1: Extra data copied over. Making the file "not complete." The first column shows the image that has been received. It seems to be larger than the one sent. Because of this, I'm not able to open the image. It seems like a corrupted file.

编辑 1:复制的额外数据。使文件“不完整”。第一列显示已接收的图像。它似乎比发送的更大。因此,我无法打开图像。它看起来像一个损坏的文件。

File sizes

File sizes

Edit 2: This is how I do it in the console. The file sizes are the same here. Python ConsoleSame file sizes

编辑 2:这就是我在控制台中的做法。此处的文件大小相同。 Python ConsoleSame file sizes

采纳答案by falsetru

Client need to notify that it finished sending, using socket.shutdown(not socket.closewhich close both reading/writing part of the socket):

客户端需要通知它已完成发送,使用socket.shutdown(不是socket.close关闭套接字的读/写部分):

...
print "Done Sending"
s.shutdown(socket.SHUT_WR)
print s.recv(1024)
s.close()

UPDATE

更新

Client sends Hello server!to the server; which is written to the file in the server side.

客户端发送Hello server!到服务器;写入服务器端的文件中。

s.send("Hello server!")

Remove above line to avoid it.

删除上面的行以避免它。

回答by gajendra

The problem is extra 13 byte which server.py receives at the start. To resolve that write "l = c.recv(1024)" twice before the while loop as below.

问题是 server.py 在开始时收到的额外 13 字节。要解决该问题,请在 while 循环之前写入两次“l = c.recv(1024)”,如下所示。

print "Receiving..."
l = c.recv(1024) #this receives 13 bytes which is corrupting the data
l = c.recv(1024) # Now actual data starts receiving
while (l):

This resolves the issue, tried with different format and sizes of files. If anyone knows what this starting 13 bytes refers to, please reply.

这解决了问题,尝试使用不同的文件格式和大小。如果有人知道这个起始 13 个字节是什么意思,请回复。

回答by Rama Krishna

Remove below code

删除下面的代码

s.send("Hello server!")

because your sending s.send("Hello server!")to server, so your output file is somewhat more in size.

因为您发送s.send("Hello server!")到服务器,所以您的输出文件的大小要大一些。

回答by Irviano Yoe

Put file inside while Truelike so

while True像这样把文件放在里面

while True:
     f = open('torecv.png','wb')
     c, addr = s.accept()     # Establish connection with client.
     print 'Got connection from', addr
     print "Receiving..."
     l = c.recv(1024)
     while (l):
         print "Receiving..."
         f.write(l)
         l = c.recv(1024)
     f.close()
     print "Done Receiving"
     c.send('Thank you for connecting')
     c.close()   

回答by DAkbariSE

you may change your loop condition according to following code, when length of l is smaller than buffer size it means that it reached end of file

您可以根据以下代码更改循环条件,当 l 的长度小于缓冲区大小时,表示它已到达文件末尾

while (True):
    print "Receiving..."
    l = c.recv(1024)        
    f.write(l)
    if len(l) < 1024:
        break

回答by Ahmed

You can send some flag to stop while loop in server

您可以发送一些标志来停止服务器中的循环

for example

例如

Server side:

服务器端:

import socket
s = socket.socket()
s.bind(("localhost", 5000))
s.listen(1)
c,a = s.accept()
filetodown = open("img.png", "wb")
while True:
   print("Receiving....")
   data = c.recv(1024)
   if data == b"DONE":
           print("Done Receiving.")
           break
   filetodown.write(data)
filetodown.close()
c.send("Thank you for connecting.")
c.shutdown(2)
c.close()
s.close()
#Done :)

Client side:

客户端:

import socket
s = socket.socket()
s.connect(("localhost", 5000))
filetosend = open("img.png", "rb")
data = filetosend.read(1024)
while data:
    print("Sending...")
    s.send(data)
    data = filetosend.read(1024)
filetosend.close()
s.send(b"DONE")
print("Done Sending.")
print(s.recv(1024))
s.shutdown(2)
s.close()
#Done :)