我目前有一个Python客户端&服务器通过套接字发送json对象如下。
客户端
# Create the socket & send the request
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
print 'Connecting to server at host: ' + (self.host) + ' port: ' + str(self.port)
s.connect((self.host, self.port))
print 'Sending signing request to the server'
s.sendall(request_data)
print 'Waiting for server response'
response_data = s.recv(10 * 1024)
print 'Got server response'
s.close()
服务器
# Create a socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
print 'Starting the server at host: ' + (self.host) + ' port: ' + str(self.port)
s.bind((self.host, self.port))
s.listen(1)
while True:
# Create a new connection
print 'Listening for client requests...'
conn, addr = s.accept()
print 'Connected to: ' + str(addr)
# Get the data
request_data = conn.recv(10 * 1024)
print 'Got message: ' + str(request_data)
# Get the json object
try:
# Decode the data and do stuff
# ...
# ...
except Exception as e:
print e
finally:
# Close the connection
conn.close()
但是,除了json对象之外,我还需要发送一个文件(不是json对象)。在服务器的while循环中,套接字无法区分json对象何时结束和文件开始接收。
我的问题是关于方法论。通过套接字发送两种不同类型数据的常用方法是什么?我们可以使用相同的套接字按顺序接收两种数据类型吗?这会在当前while循环中需要两个while循环(一个用于json,另一个用于文件)吗?
或者还有其他方法吗?
感谢。
答案 0 :(得分:2)
首先,你不能只做
response_data = s.recv(10 * 1024)
print 'Got server response'
或
# Get the data
request_data = conn.recv(10 * 1024)
print 'Got message: ' + str(request_data)
然后说你已经获得了数据。 Transmissions over TCP do not preserve their borders
关于方法,您需要通过TCP构建的协议。如果您不需要服务器连接到没有请求的客户端,HTTP将是一个很好的选择。在这种情况下,可以使用很棒的库和框架。
如果要构建自己的协议,请考虑在数据流中使用控制字符。这样的事情是可能的:
json = b"{foo: ['b', 'a', 'r']}\n" # \n here stands for end-of-the-json symbol
sock.send_byte(TYPE_JSON_MESSAGE)
sock.sendall(json)
sock.send_byte(TYPE_FILE_MESSAGE)
sock.send_int(file_size) # so the server can determine where the file transmission ends
for chunk in chunked_file:
sock.sendall(chunk)
在此,您需要实施send_byte
和send_int
。如果你使用struct
模块,这并不是很难。
在服务器端:
message_type = sock.recv(1)
if message_type == TYPE_JSON_MESSAGE:
# ...
elif message_type == TYPE_FILE_MESSAGE:
file_size = sock.recv_int() # not implemented
# ...