通过Python中的套接字发送各种类型的数据

时间:2015-12-15 01:23:02

标签: python json sockets

我目前有一个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,另一个用于文件)吗?

或者还有其他方法吗?

感谢。

1 个答案:

答案 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_bytesend_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
    # ...