最近我写了一些代码(客户端和服务器)来发送图像 - 客户端只是将图像上传到服务器,只是使用 socket
模块: Sending image over sockets (ONLY) in Python, image cannot开放。
然而,图像发送部分现在是我关心的。这是我正在使用的原始图像:
在我的服务器代码(接收图像)中,我有这些行:
myfile = open(basename % imgcounter, 'wb')
myfile.write(data)
data = sock.recv(40960000)
if not data:
myfile.close()
break
myfile.write(data)
myfile.close()
sock.sendall("GOT IMAGE")
sock.shutdown()
但我认为这不是最好的方法。我想我应该改为实现服务器,以便它以块的形式接收数据:
#!/usr/bin/env python
import random
import socket, select
from time import gmtime, strftime
from random import randint
imgcounter = 1
basename = "image%s.png"
HOST = '127.0.0.1'
PORT = 2905
connected_clients_sockets = []
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
server_socket.bind((HOST, PORT))
server_socket.listen(10)
connected_clients_sockets.append(server_socket)
while True:
read_sockets, write_sockets, error_sockets = select.select(connected_clients_sockets, [], [])
for sock in read_sockets:
if sock == server_socket:
sockfd, client_address = server_socket.accept()
connected_clients_sockets.append(sockfd)
else:
try:
data = sock.recv(4096)
txt = str(data)
if data:
if data.startswith('SIZE'):
tmp = txt.split()
size = int(tmp[1])
print 'got size %s' % size
sock.sendall("GOT SIZE")
elif data.startswith('BYE'):
sock.shutdown()
else :
myfile = open(basename % imgcounter, 'wb')
myfile.write(data)
amount_received = 0
while amount_received < size:
data = sock.recv(4096)
amount_received += len(data)
print amount_received
if not data:
break
myfile.write(data)
myfile.close()
sock.sendall("GOT IMAGE")
sock.shutdown()
except:
sock.close()
connected_clients_sockets.remove(sock)
continue
imgcounter += 1
server_socket.close()
但是当我这样做时,服务器会打印:
got size 54674
4096
8192
12288
16384
20480
24576
28672
32768
36864
40960
45056
49152
50578
然后似乎挂了,客户端也挂了。但是,在服务器端,我只能看到客户端想要发送的图像的一部分:
似乎缺少一些字节。仅使用套接字发送大量数据(图像,其他类型的文件)的正确方法是什么?
原文由 yak 发布,翻译遵循 CC BY-SA 4.0 许可协议
我假设您有特殊原因使用裸套接字执行此操作,例如自我教育,这意味着我不会回答说“您不小心忘记了只使用 HTTP 和 Twisted”,也许您已经 之前听说过:-P。但实际上你应该在某个时候看看更高级别的库,因为它们要容易得多!
定义协议
如果您只想发送图像,那么它可以很简单:
Client -> server: 8 bytes
:大端,图像长度。Client -> server: length bytes
: 所有图像数据。Client <- server: 1 byte, value 0
:表示接收到传输 - 可选步骤你可能不关心你是否使用 TCP,只是假设它是可靠的。)编码吧
服务器.py
客户端.py