python 用于传输照片的套接字编程
python socket programming for transferring a photo
我是 python 中的套接字编程新手。下面是在 Mininet 主机中打开 TCP 套接字并将照片从一台主机发送到另一台主机的示例。事实上,我更改了用于向另一台主机 (writing the received data to a text file) 发送简单消息的代码以满足我的要求。虽然当我执行这个修改后的代码时,没有错误并且似乎传输正确,但我不确定这是否是进行此传输的正确方法。由于我 运行 两台主机都在同一台机器上,我认为这可能会对结果产生影响。我想请您检查一下这是否是正确的传输方式,或者我应该添加或删除一些内容。
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()
首先,你应该使用TCP而不是UDP。 TCP 将确保您的 client/server 已正确接收整张照片。 UDP更多地用于内容流。
绝对不是您的用例。
client2
中的这个循环是错误的:
while (data):
if(s.send(data)):
print "sending ..."
data = f.read(buf)
作为 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.
你甚至没有尝试这样做。因此,虽然它可能在本地主机上工作,在负载较轻的机器上,文件较小,但一旦您尝试真正使用它,它就会崩溃。
正如帮助所说,您需要做一些事情来传递剩余的缓冲区。由于可能没有充分的理由不能在所有发送之前阻止,最简单的方法是调用 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…
这带来了下一个问题:您没有在任何地方进行任何异常处理。也许这没关系,但通常情况并非如此。例如,如果您的一个套接字出现故障,但另一个套接字仍在运行,您是要中止整个程序并硬断开连接,还是要先完成发送所有内容?
您至少应该使用 finally
的 with
子句,以确保您 close
您的套接字干净利落,这样另一端将得到一个很好的 EOF 而不是一个例外。
此外,您的服务器代码只服务于一个客户端,然后退出。那真的是你想要的吗?通常,即使您不需要并发客户端,您至少也想一个接一个地接受和服务它们。
最后,服务器几乎总是想这样做:
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
如果没有这个,如果您在服务器完成后的几秒内再次尝试 运行 服务器(特定于平台的秒数,这甚至可能取决于它是否以异常结束而不是干净的结束shutdown),bind
将失败,就像您尝试绑定另一个程序实际正在使用的套接字一样。
我是 python 中的套接字编程新手。下面是在 Mininet 主机中打开 TCP 套接字并将照片从一台主机发送到另一台主机的示例。事实上,我更改了用于向另一台主机 (writing the received data to a text file) 发送简单消息的代码以满足我的要求。虽然当我执行这个修改后的代码时,没有错误并且似乎传输正确,但我不确定这是否是进行此传输的正确方法。由于我 运行 两台主机都在同一台机器上,我认为这可能会对结果产生影响。我想请您检查一下这是否是正确的传输方式,或者我应该添加或删除一些内容。
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()
首先,你应该使用TCP而不是UDP。 TCP 将确保您的 client/server 已正确接收整张照片。 UDP更多地用于内容流。 绝对不是您的用例。
client2
中的这个循环是错误的:
while (data):
if(s.send(data)):
print "sending ..."
data = f.read(buf)
作为 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.
你甚至没有尝试这样做。因此,虽然它可能在本地主机上工作,在负载较轻的机器上,文件较小,但一旦您尝试真正使用它,它就会崩溃。
正如帮助所说,您需要做一些事情来传递剩余的缓冲区。由于可能没有充分的理由不能在所有发送之前阻止,最简单的方法是调用 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…
这带来了下一个问题:您没有在任何地方进行任何异常处理。也许这没关系,但通常情况并非如此。例如,如果您的一个套接字出现故障,但另一个套接字仍在运行,您是要中止整个程序并硬断开连接,还是要先完成发送所有内容?
您至少应该使用 finally
的 with
子句,以确保您 close
您的套接字干净利落,这样另一端将得到一个很好的 EOF 而不是一个例外。
此外,您的服务器代码只服务于一个客户端,然后退出。那真的是你想要的吗?通常,即使您不需要并发客户端,您至少也想一个接一个地接受和服务它们。
最后,服务器几乎总是想这样做:
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
如果没有这个,如果您在服务器完成后的几秒内再次尝试 运行 服务器(特定于平台的秒数,这甚至可能取决于它是否以异常结束而不是干净的结束shutdown),bind
将失败,就像您尝试绑定另一个程序实际正在使用的套接字一样。