I am trying to send instructions from a Django website to a robot(Raspberry Pi) using Sockets but whenever I try and send a second instruction from the website it gives me the error. If you have any idea what is causing this, the help would be amazing! Website Send View:
def form_valid(self, form, **kwargs):
robo_pk = self.kwargs['pk']
robo = Robot.objects.get(pk=robo_pk)
PORT = robo.port
SERVER = robo.server
ADDR = (SERVER, PORT)
self.object = form.save()
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect(ADDR)
def send(msg):
message = msg.encode(FORMAT)
msg_length = len(message)
send_length = str(msg_length).encode(FORMAT)
send_length = b' ' * (HEADER - len(send_length))
client.send(send_length)
client.send(message)
send(form.cleaned_data['path_options'])
send("MESSAGE SENT :) !")
send(DISCONNECT_MESSAGE)
return render(self.request, "dashboard-home/thank-you.html")
ERROR TRACEBACK:
Traceback (most recent call last):
File "/usr/lib/python3.7/threading.py", line 917, in _bootstrap_inner
self.run()
File "/usr/lib/python3.7/threading.py", line 865, in run
self._target(*self._args, **self._kwargs)
File "main.py", line 46, in handle_client
conn.send("MSG Received".encode(FORMAT))
BrokenPipeError: [Errno 32] Broken pipe
Relevant Code:
def handle_client(conn, addr):
print(f"[NEW CONNECTION] {addr} connected")
connected = True
while connected:
msg_length = conn.recv(HEADER).decode(FORMAT)
if msg_length:
msg_length = int(msg_length)
msg = conn.recv(msg_length).decode(FORMAT)
if msg == '!DISCONNECT!':
connected = False
print("disconnect")
break
else:
my_queue.put(msg)
print(f"[{ADDR}] {msg}")
conn.send("MSG Received".encode(FORMAT))
conn.close()
def start():
server.listen()
print(f"[LISTENING] Server Is Listening On {SERVER}")
while True:
print("before")
conn,addr = server.accept()
print("after")
thread = threading.Thread(target=handle_client, args=(conn, addr))
thread.start()
print(f"[ACTIVE CONNECTIONS] {threading.activeCount()}")
print("[Starting] Server")
threading.Thread(target=start).start()
msg = my_queue.get()
CodePudding user response:
You are disconnecting the client before receiving all messages. To demonstrate this, run again with conn.close
commented out. You're missing additional logic to ensure all pending requests have been processed before closing the connection.
References
https://stackoverflow.com/a/11866962/806876
CodePudding user response:
The django client is disconnecting immediately after sending DISCONNECT_MESSAGE. The server detects the connection close and invalidates the conn socket, causing the exception. This invalidation can happen, for example, between the recv() for the message "MESSAGE SENT :)" and the server's response (conn.send()) to this.
See How to handle a broken pipe (SIGPIPE) in python? for further info.