python socket programming for transferring a photo

2019-08-21 14:40发布

I'm new to socket programming in python. Here is an example of opening a TCP socket in a Mininet host and sending a photo from one host to another. 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

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

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:

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()

2条回答
Lonely孤独者°
2楼-- · 2019-08-21 14:43

First of all, you should use TCP and not UDP. TCP will ensure that your client/server has received the whole photo properly. UDP is more used for content streaming. Absolutely not your use case.

查看更多
男人必须洒脱
3楼-- · 2019-08-21 14:57

This loop in client2 is wrong:

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

As the send docs say:

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.

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.

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:

Unlike send(), this method continues to send data from bytes until either all data has been sent or an error occurs. 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.


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.

查看更多
登录 后发表回答