Я хочу написать простой TCP-сервер, используя сокеты в Python. Сервер должен отправить изображение подключенному клиенту. Клиент должен получить изображение. Но на данный момент клиент получает только часть изображения, и я даже не могу его открыть.TCP-клиент/сервер с сокетами, сервер отправки файлов клиентам, зависания клиента, Python
Сервер - это мультиклиент, использующий select, но это не проблема. Я думаю, что проблема заключается в отправке изображения.
Я хотел, чтобы «протокол» был очень простым здесь.
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()
Я использую Python 2.7 на новейшем Ubuntu.
--------------------------------------------- -------------------------------------------------- ------------------------------------- EDIT ------ -------------------------------------------------- -------------------------------------------------- --------------------------
Следуя советам одного из пользователей в комментариях, я TRIED реализую простой протокол:
CLIENT SERVER
GET\r\n
----------------------------------->
OK\r\n
<-----------------------------------
GET_SIZE\r\n
----------------------------------->
SIZE 1024\r\n
<-----------------------------------
GET_IMG\r\n
----------------------------------->
IMG_DATA\r\r
<-----------------------------------
Все, кажется, работает, но после передачи изображения мой процессор на 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()
сервер.ру:
#!/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)
в клиенте?
Что такое протокол, который вы используете поверх TCP для отправки и получения файлов? Если вы его не задокументировали, вам нужно - в противном случае, практически невозможно определить, делают ли клиент и сервер правильные вещи. –
@DavidSchwartz: Я только хочу отправлять и получать изображения с использованием сокетов TCP - вот и все, без дополнительных протоколов. – yak
Тогда ваш клиент имеет серьезную ошибку в том, что он отправляет строку «GET», которая не является частью какого-либо изображения. (Честно говоря, я могу сказать вам это с многолетнего опыта - вам действительно нужно точно документировать свой протокол. Как ограничивается запрос? Как сервер отмечает конец данных? Как клиент идентифицирует его?) –