Если вы не имеете полного контроля над клиентским и серверным программным обеспечением, вам следует без колебаний использовать pickle для передачи данных назад и вперед. Pickle - это здорово, если вы уверены, что данные, которые вы извлекаете, заслуживают доверия, но если они могли быть подделаны, они небезопасны. См. Почему Python Pickle небезопасен , или рекомендации по безопасности в документации модуля рассола .
JSON - хороший выбор для форматирования данных для отправки туда и обратно; С XML все в порядке, YAML довольно хорошо. Простым форматом обмена сообщениями может быть отправка размера данных сообщения, разделитель (CRLF
или \r\n
обычно) и затем данные сообщения.
Если вы используете JSON, вам придется либо придерживаться объектов, которые модуль json
знает, как кодировать / декодировать, либо писать подклассы JSONEncoder
и JSONDecoder
, чтобы иметь дело с интересующими вас типами. .
Ниже приведено небольшое JSON-подтверждение концепции, которую вы можете запустить (не уверен, будет ли она работать в Windows или нет). Просто запустите его на каждом из двух терминалов, введите один, и он должен появиться на другом.
import socket
import select
import sys
import json
CRLF = '\r\n'
class MalformedMessage(Exception): pass
class ConnectionClosed(Exception): pass
def read_exactly(sock, buflen):
data = ''
while len(data) != buflen:
data += sock.recv(buflen - len(data))
return data
def peek(sock, buflen):
data = sock.recv(buflen, socket.MSG_PEEK)
return data
def socket_send(sock, obj):
data = json.dumps(obj)
size = len(data)
sock.sendall('%i%s%s' % (size, CRLF, data))
def socket_recv(sock):
peekdata = peek(sock, 1024)
if peekdata == '':
raise ConnectionClosed
sizepos = peekdata.find(CRLF)
if sizepos == -1:
raise MalformedMessage('Did not find CRLF in message %r' % peekdata)
sizedata = read_exactly(sock, sizepos)
read_exactly(sock, len(CRLF))
try:
size = int(sizedata)
except ValueError:
raise MalformedMessage(
'size data %r could not be converted to an int' % sizedata)
data = read_exactly(sock, size)
return json.loads(data)
if __name__ == '__main__':
netloc = ('', 7777)
try:
servsock = socket.socket()
servsock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True)
servsock.bind(netloc)
servsock.listen(5)
sock, _ = servsock.accept()
except socket.error:
sock = socket.socket()
sock.connect(netloc)
try:
while True:
r_ok, _, _ = select.select([sys.stdin, sock], [], [])
for fd in r_ok:
if fd == sys.stdin:
obj = eval(fd.readline().strip())
socket_send(sock, obj)
elif fd == sock:
obj = socket_recv(sock)
print repr(obj)
except (KeyboardInterrupt, ConnectionClosed):
pass
finally:
print '\nexiting...'