简体   繁体   English

用于传输照片的python套接字编程

[英]python socket programming for transferring a photo

I'm new to socket programming in python. 我是python套接字编程的新手。 Here is an example of opening a TCP socket in a Mininet host and sending a photo from one host to another. 这是在Mininet主机中打开TCP套接字并将照片从一台主机发送到另一台主机的示例。 In fact I changed the code that I had used to send a simple message to another host ( writing the received data to a text file ) in order to meet my requirements. 实际上,为了满足我的要求,我更改了用于向另一台主机发送简单消息( 将接收到的数据写入文本文件 )的代码。 Although when I implement this revised code, there is no error and it seems to transfer correctly, I am not sure whether this is a correct way to do this transmission or not. 尽管当我实现此修订的代码时,没有错误,并且似乎可以正确传输,但是我不确定这是否是进行此传输的正确方法。 Since I'm running both hosts on the same machine, I thought it may have an influence on the result. 由于我在同一台计算机上运行两个主机,因此我认为这可能会对结果产生影响。 I wanted to ask you to check whether this is a correct way to transfer or I should add or remove something. 我想请您检查这是否是正确的转移方式,还是应该添加或删除某些内容。

mininetSocketTest.py #!/usr/bin/python mininetSocketTest.py#!/ usr / bin / python

from mininet.topo import Topo, SingleSwitchTopo
from mininet.net import Mininet
from mininet.log import lg, info
from mininet.cli import CLI

def main():
    lg.setLogLevel('info')

    net = Mininet(SingleSwitchTopo(k=2))
    net.start()

    h1 = net.get('h1')
    p1 = h1.popen('python myClient2.py')

    h2 = net.get('h2')
    h2.cmd('python myServer2.py')

    CLI( net )
    #p1.terminate()
    net.stop()

if __name__ == '__main__':
     main()

myServer2.py myServer2.py

import socket
import sys

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.bind(('10.0.0.1', 12345))

buf = 1024
f = open("2.jpg",'wb')

s.listen(1)
conn , addr = s.accept()
while 1:
    data = conn.recv(buf)
    print(data[:10])
    #print "PACKAGE RECEIVED..."
    f.write(data)   
    if not data: break
    #conn.send(data)
conn.close()
s.close()

myClient2.py: myClient2.py:

import socket
import sys

f=open ("1.jpg", "rb")
print sys.getsizeof(f)
buf = 1024
data = f.read(buf)
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('10.0.0.1',12345))


while (data):
    if(s.sendall(data)):
        #print "sending ..."
        data = f.read(buf)
        print(f.tell(), data[:10])
    else:
         s.close()
s.close()

This loop in client2 is wrong: client2此循环是错误的:

while (data):
    if(s.send(data)):
        print "sending ..."
        data = f.read(buf)

As the send docs say: 正如send文档所说:

Returns the number of bytes sent. 返回发送的字节数。 Applications are responsible for checking that all data has been sent; 应用程序负责检查所有数据是否已发送; if only some of the data was transmitted, the application needs to attempt delivery of the remaining data. 如果仅传输了一些数据,则应用程序需要尝试传送其余数据。 For further information on this topic, consult the Socket Programming HOWTO . 有关此主题的更多信息,请参考Socket Programming HOWTO

You're not even attempting to do this. 您甚至都没有尝试这样做。 So, while it probably works on localhost, on a lightly-loaded machine, with smallish files, it's going to break as soon as you try to use it for real. 因此,尽管它可能可以在localhost上运行,但在轻载的机器上且文件很小,但是一旦您尝试将其真正使用,它就会崩溃。

As the help says, you need to do something to deliver the rest of the buffer. 正如帮助所述,您需要做一些事情来交付其余的缓冲区。 Since there's probably no good reason you can't just block until it's all sent, the simplest thing to do is to call sendall : 由于可能没有充分的理由,您不能仅在全部发送sendall ,因此最简单的方法是调用sendall

Unlike send(), this method continues to send data from bytes until either all data has been sent or an error occurs. 与send()不同,此方法继续从字节发送数据,直到所有数据都已发送或发生错误为止。 None is returned on success. 成功不返回任何内容。 On error, an exception is raised… 如果出错,则会引发异常…


And this brings up the next problem: You're not doing any exception handling anywhere. 这带来了下一个问题:您不在任何地方进行任何异常处理。 Maybe that's OK, but usually it isn't. 也许还可以,但通常不行。 For example, if one of your sockets goes down, but the other one is still up, do you want to abort the whole program and hard-drop your connection, or do you maybe want to finish sending whatever you have first? 例如,如果您的一个套接字发生故障,而另一个套接字仍然发生故障,您是否要中止整个程序并硬断开连接,还是想先完成所有发送的操作?

You should at least probably use a with clause of a finally , to make sure you close your sockets cleanly, so the other side will get a nice EOF instead of an exception. 您至少应该使用一个finallywith子句,以确保您干净地close套接字,以便另一端会得到一个不错的EOF而不是异常。


Also, your server code just serves a single client and then quits. 另外,您的服务器代码仅服务于一个客户端,然后退出。 Is that actually what you wanted? 那真的是您想要的吗? Usually, even if you don't need concurrent clients, you at least want to loop around accepting and servicing them one by one. 通常,即使您不需要并发客户端,您至少也要一遍一遍地接受和服务它们。


Finally, a server almost always wants to do this: 最后,服务器几乎总是想这样做:

s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)

Without this, if you try to run the server again within a few seconds after it finished (a platform-specific number of seconds, which may even depend whether it finished with an exception instead of a clean shutdown), the bind will fail, in the same way as if you tried to bind a socket that's actually in use by another program. 如果不这样做,如果您尝试在服务器完成后几秒钟内再次运行服务器(特定于平台的秒数,甚​​至可能取决于它是否以异常而不是完全关闭而完成),则bind将失败,就像您试图绑定另一个程序实际上正在使用的套接字一样。

First of all, you should use TCP and not UDP. 首先,您应该使用TCP而不是UDP。 TCP will ensure that your client/server has received the whole photo properly. TCP将确保您的客户端/服务器正确接收了整个照片。 UDP is more used for content streaming. UDP更用于内容流。 Absolutely not your use case. 绝对不是您的用例。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM