gpt4 book ai didi

python - 带套接字的 TCP 客户端/服务器、服务器向客户端发送文件、客户端挂起、Python

转载 作者:IT老高 更新时间:2023-10-28 21:12:24 26 4
gpt4 key购买 nike

我想用 Python 中的套接字编写一个简单的 TCP 服务器。服务器应将图像发送到连接的客户端。客户端应该会收到图像。但是,现在,客户端只收到图像的一部分,我什至无法打开它。

服务器是使用 select 的多客户端,但这不是问题所在。我认为问题在于发送图像。

我希望这里的“协议(protocol)”非常简单。

SERVER                   CLIENT
GET
<----------------
IMAGE
----------------->
END OF COMMUNICATION

所以客户端只能向服务器发送“GET”消息,而服务器在得到“GET”字符串后,应该立即将整个图像发送给客户端。至此,通讯结束。

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。

------------------------------------------ -------------------------------------------------- --------------------------------------编辑----------------------------------------------- -------------------------------------------------- ----------------------------------

根据其中一位用户在评论中给出的建议,我尝试实现一个简单的协议(protocol):

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

表示客户端成功接收到图片。现在好吗?我的意思是,我从服务器获取了图像,但我不知道我是否正确实现了协议(protocol)。也许这里可以改进一些东西?

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)

在客户端?

最佳答案

你不小心忘记了只使用 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 .

关于python - 带套接字的 TCP 客户端/服务器、服务器向客户端发送文件、客户端挂起、Python,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42356322/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com