I have the following code I am sending the result of intermediate predictions results from the client to server.
Client
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
host_name = socket.gethostname()
host_ip = 'localhost'
print('HOST IP:', host_ip)
port = 9999
socket_address = (host_ip, port)
server_socket.bind(socket_address)
server_socket.listen(5)
while True:
client_socket, addr = server_socket.accept()
print('GOT CONNECTION FROM:', addr)
if client_socket:
vid = cv2.VideoCapture("D:/testing.mp4")
while (vid.isOpened()):
img, frame = vid.read()
image = img_to_array(frame)
image = image.reshape((1, image.shape[0], image.shape[1], image.shape[2]))
image = preprocess_input(image)
preds = model.predict(image)
a = pickle.dumps(preds)
message = struct.pack("Q", len(a)) + a
client_socket.sendall(message)
client_socket.close()
server
client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
host_ip = 'localhost'
port = 9999
client_socket.connect((host_ip, port))
data = b""
payload_size = struct.calcsize("Q")
while True:
while len(data) < payload_size:
packet = client_socket.recv(4 * 1024)
if not packet: break
data += packet
packed_msg_size = data[:payload_size]
data = data[payload_size:]
msg_size = struct.unpack("Q", packed_msg_size)[0]
while len(data) < msg_size:
data += client_socket.recv(4 * 1024)
frame_data = data[:msg_size]
data = data[msg_size:]
frame = pickle.loads(frame_data)
While running the above code I am facing the below error
msg_size = struct.unpack(“Q”, packed_msg_size)[0] struct.error: unpack requires a buffer of 8 bytes
Thank you
Advertisement
Answer
You haven’t sorted out normal end of connection. As mentioned in the comments, when the connection is closed by the client, you hit if not packet: break
but that only breaks you out of the inner loop and you keep on trying to process a non-existent message. There is another bug in there where you don’t clear out data
per message.
When nesting loops, especially in communications where end of processing is discovered several steps down, I find it best to break the work into multiple functions with more narrowly defined roles. Here, you want to receive exactly one message at a time, build that into a python object and then use it. 3 functions for three things.
def do_the_things():
client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
host_ip = 'localhost'
port = 9999
client_socket.connect((host_ip, port))
while True:
frame = recv_frame(client_socket)
if frame is None:
break
payload_size = struct.calcsize("Q")
def recv_obj(client_socket):
data = recvall(client_socket, payload_size)
if len(data) < payload_size:
if not data:
# client closed after last message, assume all is well
return None
else:
raise IOError("Truncated message")
packed_msg_size = data[:payload_size]
data = data[payload_size:]
msg_size = struct.unpack("Q", packed_msg_size)[0]
remaining_data = recvall(client_socket, msg_size)
if len(remaining_data) < msg_size:
raise IOError("Truncated message")
obj = pickle.loads(data + remaining_data)
return obj
def recvall(sock, count):
"""Keep receiving up to `count` bytes, returning partial result
if connection closed normally by remote."""
data_bufs = []
while count:
data = sock.recv(count)
if not data:
break
count -= len(data)
data_bufs.append(data)
return b"".join(data_bufs)