I am trying to make a small game and a part of it is to send a country name to Raspberry Pi from a laptop. Right now I am just sending a string, but later that string will be used to draw an image from a pen plotter attached to the RPi.
I am having trouble sending and receiving data using Python sockets (complete beginner). What I am trying to do is make the server keep sending the country name until the client receives it and then send a signal from the client back to the server that it has received the country name to make the server stop sending it and switch to listening mode. The client does some processing which right now is just print(f"Drawing country {country_name}") and then sends the server signal that it is finished.
Unfortunately both programs are running but nothing is happening. I am able to ping the laptop from RPi and vice versa. Furthermore the program in this link works for me: Communication between two computers using python socket
My code for server side and client side is provided below:-
Server side (laptop)
#Import the necessary libraries
from socket import socket, gethostbyname, AF_INET, SOCK_DGRAM
import sys
import time
#Designate a port over which the communication will happen
PORT_NUMBER = 5000
#Protocol ?
SIZE = 1024
#Get the name of the host, this is our laptop
SERVER_NAME = gethostbyname('')
#Create the server socket, this is our laptop
Server_Socket = socket( AF_INET, SOCK_DGRAM )
Server_Socket.bind( (SERVER_NAME, PORT_NUMBER) )
#Set the client IP, this is our raspberry pi
CLIENT_IP = "192.168.88.244"
print ("Test server listening on port {0}\n".format(PORT_NUMBER))
#Create a variable that will become True if the client responds
client_response = False
#Start of while loop to keep sending data until client responds
while client_response == False:
#Create a delay so the client is not overwhelmed
time.sleep(3)
Server_Socket.sendto(b"Country_Name", (CLIENT_IP, PORT_NUMBER))
(client_response,addr) = Server_Socket.recvfrom(SIZE)
print(client_response)
#End of while loop to keep sending data until client responds
#Set client_response again to false
client_response = False
#Start of while loop to listen until client has done the task, this is our raspberry pi finishing the drawing
while client_response == False:
(client_response,addr) = Server_Socket.recvfrom(SIZE)
#End of while loop to listen until client has done the task, this is our raspberry pi finishing the drawing
#Close the server socket
Server_Socket.close()
print("Done")
sys.ext()
Client side (Raspberry Pi)
#Import the necessary libraries
from socket import socket, gethostbyname, AF_INET, SOCK_DGRAM
import sys
import time
#Set the server IP, this is our laptop
SERVER_IP = '192.168.88.250'
#Designate a port over which the communication will happen
PORT_NUMBER = 5000
#Protocol ?
SIZE = 1024
#Create the cleint socket, this is our raspberry pi
Client_Socket = socket( AF_INET, SOCK_DGRAM )
Client_Socket.bind( (SERVER_IP, PORT_NUMBER) )
#Set a variable that becomes True if the data sent by server is received
server_data_rcvd = False
#Start of while loop to listen until data from server is received
while server_data_rcvd == False:
#Create a delay so the client is not overwhelmed
time.sleep(1)
#Store country name
(country_name, addr) = Client_Socket.recv(size)
print("country_name")
#Start of if statement to check if country name is received
if type(country) == str:
server_data_rcvd = True
#Send response to the server
Client_Socket.sendto(True, (SERVER_IP, PORT_NUMBER))
#End of if statement to check if country name is received
#End of while loop to listen until data from server is received
#Draw the country
print(f"Drawing country {country_name}")
Client_Socket.sendto(True, (SERVER_IP, PORT_NUMBER))
#Close the socket
Client_Socket.close()
sys.exit()
What mistake am I making ? And how can I make the code more efficient and readable ?
Thanks in advance !
CodePudding user response:
The client have to connect to the server with socket.connect
, not socket.bind
.
#Create the cleint socket, this is our raspberry pi
Client_Socket = socket( AF_INET, SOCK_DGRAM )
Client_Socket.connect( (SERVER_IP, PORT_NUMBER) )
CodePudding user response:
There are a number of issues that could be causing your problem outside of the couple of typos (ex: size vs SIZE, country vs country_name, sys.ext vs sys.exit, etc).
UDP vs TCP
First off, you are using SOCK_DGRAM which suggests UDP as a protocol rather than TCP. This is fine as long as this is what you were expecting. UDP is connectionless where TCP requires your client to connect
to your server.
Bytes
If you are using Python3, recv(buffersize[, flags]) -> data
returns bytes, not a tuple of the data and an address. If you update that line to accept country, you'll then want to convert it to a string via country.decode('utf-8')
If you are using Python3, sendto(data[, flags], address) -> count
expects data (not a boolean). What you can do is send bytes via b'True'
or send 'True'.encode('utf-8')
.
Blocking recv
The biggest issue I see and probably what is causing you the most trouble is that your while loops are problematic. Not only does the while loop in your server never exit, but recv
is a blocking action so if you were to start the server and then start your rpi, they will both be stuck at recv
and neither will be sending. In your current setup, you have to launch rpi first so that it can listen, then start your server so it can send the country to the rpi. Otherwise, they are deadlocked since they are both listening for the other end to send something.