我想在Python中使用套接字编写一个简单的TCP服务器。服务器应将映像发送到连接的客户端。客户端应该接收图像。但是,就目前而言,客户只收到图像的一部分,我甚至无法打开它。
服务器是使用select的多客户端,但这不是问题。我认为问题在于发送图像。
我想要"协议"在这里很简单。
SERVER CLIENT
GET
<----------------
IMAGE
----------------->
END OF COMMUNICATION
所以客户端只能发送&#34; GET&#34;获得&#34; GET&#34;之后发送给服务器和服务器的消息字符串,应立即将整个图像发送给客户端。就是这样,沟通就结束了。
server.py
#!/usr/bin/env python
import random
import socket, select
from time import gmtime, strftime
image = 'image.png'
HOST = '127.0.0.1'
PORT = 6666
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)
bytes = open(image).read()
if data:
sock.send(bytes)
except:
sock.close()
connected_clients_sockets.remove(sock)
continue
server_socket.close()
client.py
#!/usr/bin/env python
import socket
import sys
HOST = '127.0.0.1'
PORT = 6666
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_address = (HOST, PORT)
sock.connect(server_address)
try:
sock.sendall("GET")
while True:
myfile = open('imagefromserv.png', 'w')
while True:
data = sock.recv(4096)
if not data:
break
myfile.write(data)
myfile.close()
finally:
sock.close()
我在最新的Ubuntu上使用Python 2.7。
-------------------------------------------- -------------------------------------------------- -------------------------------------- 的修改 的 ----------------------------------------------- -------------------------------------------------- -----------------------------------
根据评论中的一个用户给出的建议,我试着实现一个简单的协议:
CLIENT SERVER
GET\r\n
----------------------------------->
OK\r\n
<-----------------------------------
GET_SIZE\r\n
----------------------------------->
SIZE 1024\r\n
<-----------------------------------
GET_IMG\r\n
----------------------------------->
IMG_DATA\r\r
<-----------------------------------
一切似乎都有效,但在图像传输后,我的CPU 100%忙碌,top
说。而且....
服务器的输出:
--GET--
--GET_SIZE--
--24518--
--GET_IMG--
客户的输出:
--OK--
--SIZE 24518--
--24518--
4096
8192
12288
16384
20480
24523
Image received successfully
表示客户端已成功收到图像。现在好吗?我的意思是,我从服务器获得了图像,但我不知道,如果我正确地实现了协议。也许这里可以改进一些东西?
client.py:
#!/usr/bin/env python
import socket
import sys
HOST = '127.0.0.1'
PORT = 6666
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_address = (HOST, PORT)
sock.connect(server_address)
fname = 'fromserver.png'
try:
sock.sendall("GET\r\n")
data = sock.recv(4096)
if data:
txt = data.strip()
print '--%s--' % txt
if txt == 'OK':
sock.sendall("GET_SIZE\r\n")
data = sock.recv(4096)
if data:
txt = data.strip()
print '--%s--' % txt
if txt.startswith('SIZE'):
tmp = txt.split()
size = int(tmp[1])
print '--%s--' % size
sock.sendall("GET_IMG\r\n")
myfile = open(fname, 'wb')
amount_received = 0
while amount_received < size:
data = sock.recv(4096)
if not data :
break
amount_received += len(data)
print amount_received
txt = data.strip('\r\n')
if 'EOF' in str(txt) :
print 'Image received successfully'
myfile.write(data)
myfile.close()
else :
myfile.write(data)
finally:
sock.close()
server.py:
#!/usr/bin/env python
import random
import socket, select
from time import gmtime, strftime
image = 'tux.png'
HOST = '127.0.0.1'
PORT = 6666
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)
if data :
txt = data.strip()
print '--%s--'%txt
if txt == 'GET' :
sock.sendall('OK\r\n')
elif txt == 'GET_SIZE' :
with open ('tux.png','rb') as f1:
file_size = len(f1.read())
f1.seek(0)
print '--%s--'%file_size
file_size = '%s' % file_size
sock.sendall('SIZE %s\r\n' % file_size)
elif txt == 'GET_IMG' :
with open(image, 'rb') as fp:
image_data = fp.read()
msg = '%sEOF\r\r' % image_data
sock.sendall(msg)
print msg
except:
sock.close()
connected_clients_sockets.remove(sock)
continue
server_socket.close()
或许我应该这样做:
sock.sendall(image_data)
sock.sendall('EOF\r\n')
而不是:
msg = '%sEOF\r\n' % image_data
sock.sendall(msg)
在客户?
答案 0 :(得分:12)
你不小心忘了使用HTTP和Twisted。
服务器:
from twisted.web.static import File
from twisted.web.resource import Resource
def resource():
resource = Resource()
resource.putChild(b"", File(u"xkcd/sandwich.png"))
return resource
客户端:
from filepath import FilePath
from twisted.internet.task import react
from treq import get, content
def main(reactor):
d = get(b"http://localhost:8080/")
d.addCallback(content)
d.addCallback(FilePath(u"image.png").setContent)
return d
react(main, [])
服务器演示:
(everything) exarkun@baryon:/tmp/demo$ twist web --class server.resource
2017-02-23T21:32:14-0500 [-] Site starting on 8080
2017-02-23T21:32:14-0500 [twisted.web.server.Site#info] Starting factory <twisted.web.server.Site instance at 0x7fd1ef81a8c0>
2017-02-23T21:32:14-0500 [twisted.application.runner._runner.Runner#info] Starting reactor...
2017-02-23T21:33:01-0500 [twisted.python.log#info] "127.0.0.1" - - [24/Feb/2017:02:33:01 +0000] "GET / HTTP/1.1" 200 21489 "-" "-"
^C
2017-02-23T21:33:05-0500 [-] Received SIGINT, shutting down.
2017-02-23T21:33:05-0500 [-] (TCP Port 8080 Closed)
2017-02-23T21:33:05-0500 [twisted.web.server.Site#info] Stopping factory <twisted.web.server.Site instance at 0x7fd1ef81a8c0>
2017-02-23T21:33:05-0500 [-] Main loop terminated.
(everything) exarkun@baryon:/tmp/demo$
客户端演示:
(everything) exarkun@baryon:/tmp/demo$ ls -l image.png
ls: cannot access 'image.png': No such file or directory
(everything) exarkun@baryon:/tmp/demo$ python client.py
(everything) exarkun@baryon:/tmp/demo$ ls -l image.png
-rwxr-xr-x 1 exarkun exarkun 21489 Feb 23 21:33 image.png
(everything) exarkun@baryon:/tmp/demo$
如果您想了解有关如何完成选择循环驱动网络的更多信息,您可以仔细阅读the Twisted implementation。
答案 1 :(得分:5)
您的客户端发送字符串“GET”。您只想发送和接收图像数据,“GET”不是图像数据。
您可能有其他错误,如果不了解您的协议,很难说清楚。例如,一方如何知道它获得了所有图像数据?
答案 2 :(得分:3)
你可以读到这个: https://picamera.readthedocs.io/en/release-1.12/recipes1.html 并学习如何在套接字上发送图片。&#39;基本食谱&#39;为您提供所需的一切。
答案 3 :(得分:3)
编辑部分下面的代码对我来说似乎不错。 我完全赞同@David Schwartz。如果您正在寻求实现协议,则必须考虑有关协议设计的大量内容。例如:
为此您可以阅读“TCP / IP和Linux协议实现”这是一本很好的书。
另一方面,你可以坚持使用基础知识并继续使用TCP套接字,我的拙见是你为客户端实现了一些机制,知道它是否有完整的信息,如:
答案 4 :(得分:-3)
这真的很奇怪。我尝试了两个不同的图像,代码工作。问题在于图像。