在通过网络传输数据时,通常按照大端字节顺序打包数据。尽管一次只有三个独立的字节,因此字节顺序并不重要,但我仍然更喜欢打包和解包,因为这是一种常见的通信方式。此外,在接收网络数据时,常见的事情是检查您是否确实收到了预期的数量,否则您必须请求更多数据。为简单起见,请考虑以下函数:
def recv(sock, size):
data = ''
to_receive = size
while to_receive > 0:
data += sock.recv(to_receive)
to_receive = size - len(data)
return data
现在,您的代码中缺少的是通用协议。客户端充当原始无意义数据的接收者。相反,它应该充当三元组的接收者。除此之外,我建议让客户询问他想要多少个三胞胎。考虑到这一点,我将把您的客户端代码更改为:
import sys
import socket
import struct
serv_host = ''
serv_port = 29876
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((serv_host, serv_port))
# Tell the server how many triplets I want.
amount = int(sys.argv[1])
s.sendall(struct.pack('!i', amount))
pack_size = struct.calcsize('!bbb')
while amount:
status, dx, dy = struct.unpack('!bbb', recv(s, pack_size))
print status, dx, dy
amount -= 1
s.close()
现在服务器也需要遵守这个新强加的协议。请注意,负值实际上使客户端收到无限的三元组,这是有意的。这是修改后的服务器:
import socket
import struct
def to_signed(n):
return n - ((0x80 & n) << 1)
mouse = open('/dev/input/mouse0')
host = ''
port = 29876
backlog = 5
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.bind((host, port))
s.listen(backlog)
print 'Listening'
while True:
client, address = s.accept()
# Obtain the number of triplets the client wants.
amount = struct.unpack('!i', recv(client, 4))[0]
while amount: # Send the triplets as they become available.
status, dx, dy = map(ord, mouse.read(3))
dx, dy = to_signed(dx), to_signed(dy)
print status, dx, dy
client.sendall(struct.pack('!bbb', status, dx, dy))
amount -= 1
client.close()