udp client/server with resending messages - python

I have a client and a server. The server sends a random number to the client and if it is less than 4, the client responds unsuccessfully.
SERVER:
import random
from socket import *
serverSocket = socket(AF_INET, SOCK_DGRAM)
serverSocket.bind(('', 12000))
while True:
rand = random.randint(2, 4)
message, address = serverSocket.recvfrom(1024)
message = (message.decode()+" СЛУЧАЙНОЕ ЧИСЛО: "+str(rand)).upper()
print("Сервер готов!")
print("Случайное число: "+str(rand))
if rand < 4:
continue
serverSocket.sendto(message.encode(), address)
Client:
from time import *
from socket import *
localhost = '127.0.0.1'
for i in range(1, 11):
clientSocket = socket(AF_INET, SOCK_DGRAM)
date_current = ctime()
startTime = time()
clientSocket.settimeout(0.5)
try:
requestMessage = bytes("Ping " + str(i) + " " + date_current, 'utf8')
clientSocket.sendto(requestMessage, (localhost, 12000))
mess, rand = clientSocket.recvfrom(1024)
endTime = time()
rtt = endTime - startTime
print(mess.decode())
print("Ответ "+localhost+" подтверждено: "+str(float(rtt)))
print()
except:
print(requestMessage.decode())
print("Время вышло")
print()
I want the client to send a message to the server in case of failure and the server to regenerate the number and send it to the client until there is a response about luck (more than 4)

Related

UDP Ping Client - Python

I am trying to implement a UDP Pinger. In the client code that I wrote, the try statement is not evaluating and just the packet loss message is printing. It is clear that the try statement is not even being hit. I have tried so many different things and nothing has fixed it. Please let me know if you know the issue.
Here is the client code:
import random
import time
import sys
from socket import *
if len(sys.argv) != 3:
print("Usage: python UDPPingerClient <server ip address> <server port no>")
exit(0)
client_socket = socket(AF_INET, SOCK_DGRAM)
server = (sys.argv[1], int(sys.argv[2]))
client_socket.settimeout(1)
for i in range(0, 5):
start_time = time.time()
host_name = gethostname()
server_ip = gethostbyname(host_name)
msg = 'PING ' + str(server_ip) + " " + str(i)
try:
client_socket.sendto(msg.encode(), server)
client_socket.settimeout(1)
client_socket.recv(1024)
end_time = time.time()
rtt = (end_time - start_time) * 1000
msg += " " + str(format(rtt, '.3f')) + "ms\n"
print(msg)
except timeout:
timeout_msg = 'PING ' + str(server_ip) + " " + str(i + 1) + " " + 'Lost\n'
print(timeout_msg)
This is the server code:
import random
import time
import sys
from socket import *
if (len(sys.argv) != 2):
print("Required arguments: port")
exit(0)
port = int(sys.argv[1])
serverSocket = socket(AF_INET, SOCK_DGRAM)
serverSocket.bind(('', port))
LOSS_RATE = 0.3
AVERAGE_DELAY = 100
while True:
rand = random.uniform(0, 1)
message, address = serverSocket.recvfrom(1024)
print(message)
if rand < LOSS_RATE:
print("Reply not sent.")
continue
delay = random.randint(0.0, 2*AVERAGE_DELAY)
print(delay)
time.sleep(delay/1000)
serverSocket.sendto(message, address)
print("Reply sent.")

Changing my UDP server to take the same request multiple times

I need the UDP_server to take the request("message") multiple times (5-6 time will be ok) to calculate the arithmetic mean of the recorded response times (the time required from the moment you send the message to the time the response arrives from server). Probably I can do that with a "for", but I don't really know where to place it or to use it.
UDP_server code:
import socket
server_port = 21060
server_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
server_socket.bind(('127.0.0.1', server_port))
print ('[SERVER] Listening at: {}'.format(server_socket.getsockname()))
while True:
message, address = server_socket.recvfrom(65535)
modified_message = str(len(str(message).split(",")))
print ('[SERVER] The client at {}, originally sent: {}'.format(address, repr(message)))
server_socket.sendto(bytes('Server is sending back: "{}".'.format(modified_message), encoding='utf8'), address)
server_socket.close()
UDP_client code:
import socket
import string
import random
from time import time
def random_string(length, chars=string.ascii_letters + string.digits):
return ''.join(random.choice(chars) for x in range(length))
server_port = 21060
client_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
input_s = random_string(100)
sent_time = time()
client_socket.sendto(bytes(input_s, encoding='utf8'), ('127.0.0.1', server_port))
input_s_modified, address = client_socket.recvfrom(65535)
received_time = time()
print ('[CLIENT] Response from server {}, is: "{}"'.format(address, str(input_s_modified.decode('utf8'))))
client_socket.close()
print("Time response =", received_time - sent_time, 'seconds')

Socket python can't send information to the server "client.send(name)"

I'm working on a game project with tkinter and Python 3.7 and i can't send the name of the player that i'm typing to the server.
Server
server = None
HOST_ADDR = "192.168.1.13"
HOST_PORT = 5555
client_name = ""
clients = []
clients_names = []
player_data = []
def start_server():
global server, HOST_ADDR, HOST_PORT # code is fine without this
btnStart.config(state=tk.DISABLED)
btnStop.config(state=tk.NORMAL)
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
print("socket.AF_INET")
print("socket.SOCK_STREAM")
server.bind((HOST_ADDR, HOST_PORT))
server.listen(5) # server is listening for client connection
threading._start_new_thread(accept_clients, (server, " "))
lblHost["text"] = "Address: " + HOST_ADDR
lblPort["text"] = "Port: " + str(HOST_PORT)
def accept_clients(the_server, y):
while True:
if len(clients) < 2:
client, addr = the_server.accept()
clients.append(client)
# use a thread so as not to clog the gui thread
threading._start_new_thread(send_receive_client_message, (client, addr))
Client.py
client = None
HOST_ADDR = "192.168.1.13"
HOST_PORT = 5555
def connect():
global your_details
if len(ent_name.get()) < 1:
tk.messagebox.showerror(title="ERROR!!!", message="You MUST enter your first name <e.g. John>")
else:
your_details["name"] = ent_name.get()
connect_to_server(ent_name.get())
def connect_to_server(name):
global client, HOST_PORT, HOST_ADDR
try:
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((HOST_ADDR, HOST_PORT))
print('test') # OK, i can receive the print
client.send(name)
print('test') # can't receive the print
threading._start_new_thread(receive_message_from_server, (client, "m"))
top_welcome_frame.pack_forget()
top_frame.pack(side=tk.TOP)
window_main.title("Tic-Tac-Toe Client - " + name)
except Exception as e:
tk.messagebox.showerror(title="ERROR!!!", message="Cannot connect to host: " + HOST_ADDR + " on port: " + str(
HOST_PORT) + " Server may be Unavailable. Try again later")
Each time i enter a name, it doesn't send the name that i typed client.send(name) and it goes in the else.
If someone can help me with that.
Thank you for your help !

Why does my UDP pinger client only timeout?

I've made a UDP Pinger server side, however this UDP Pinger client only sends request time outs. I'm trying to make a pinger that sends 10 pings to the server.
import time
from socket import *
serverName = ''
serverPort = 12000
ClientSocket = socket(AF_INET, SOCK_DGRAM)
ClientSocket.settimeout(1)
ping = 1
message = 'ping'
counter = 10
i = 0
remain = counter - i
while counter < i :
i = i + 1
addr = ("", 120000)
start = time.time()
ClientSocket.sendto(message, (serverName,
serverPort))
while ping < 11:
try:
message, server = ClientSocket.recvfrom(1024)
end = time.time()
elapsed = end - start
print (message + " " + str(ping) + " " +
str(elapsed))
except timeout:
print ('REQUEST TIMED OUT')
ping = ping + 1

How do i get the socket to continue listening to the client and continuosly print information from the client

Server Side (server prints the first line of information sent from the client then it JUST STAYS open and doesn't seem to continue listening it just stays open. Is there a way to get the server to listen to the client more and print?)
import time
import socket
import signal
from datetime import datetime
serversocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
serversocket.bind(('localhost', 8089))
serversocket.listen(1024) # become a server socket, maximum 5 connectionn
def clientsocketentry():
while True:
connection, addr = serversocket.accept()
buf = connection.recv(64)
if not buf:
break
elif buf == 'killsrv':
connection.close()
sys.exit()
else:
print (buf)
buf = buf.decode("utf-8")
buf = buf.split(',')
serverLong = buf[0]
print('Longitude:' + '' + serverLong)
serverLat = buf[1]
print('Lattitude:' + '' + serverLat)
serverAlt = buf[2]
print('Altitude:' + '' + serverAlt)
serverTime = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
print('Time of Entry:' + ' ' + serverTime)
connection.close()
clientsocketentry()
Client Side (I am only able to send one of the strings of information then the server stays open ut does not take more information from the client)
import socket
import time
clientsocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
clientsocket.connect(('localhost', 8089))
a = '39.163100,-76.899428,0'
clientsocket.send(a.encode('utf-8'))
time.sleep(5)
a = '4.2,2.2415,0'
clientsocket.send(a.encode('utf-8'))
time.sleep(5)
a = '43454,354354,35435'
clientsocket.send(a.encode('utf-8'))
time.sleep(5)
a = '435742.,35.452,52434'
clientsocket.send(a.encode('utf-8'))
time.sleep(5)
clientsocket.close()
If you accept one single connection at a time (no need for a 1024 backlog then...) you can simply nest 2 loops: the outer one waiting for new connections the inner one processing input from the only one established connection. If you need to process more than one connection, you will have to use select or threads.
Here is an example for one single connection:
def clientsocketentry():
serversocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
serversocket.bind(('localhost', 8089))
serversocket.listen(5) # become a server socket, maximum 5 connectionn
cont = True
while cont:
connection, addr = serversocket.accept()
while True:
buf = connection.recv(64)
if len(buf) == 0: # end of connection
connection.close()
break
elif buf == b'killsrv': # request for closing server (beware of the byte string)
connection.close()
serversocket.close()
cont = False
break
else:
print (buf)
buf = buf.decode("utf-8")
buf = buf.split(',')
serverLong = buf[0]
print('Longitude:' + '' + serverLong)
serverLat = buf[1]
print('Lattitude:' + '' + serverLat)
serverAlt = buf[2]
print('Altitude:' + '' + serverAlt)
serverTime = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
print('Time of Entry:' + ' ' + serverTime)
# connection.close() # wait for client to close
You are closing the socket at the end of your print logic in the ClientSocketEntry function.
serverTime = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
print('Time of Entry:' + ' ' + serverTime)
connection.close()
Instead of closing the connection there only close it when the user sends killsrv
Because every time you close the connection on the socket it is saying that you are expecting another client to connect to the server. So maybe before going into the while statement accept the connection and then pass it into the while statement, because the way you have it structured at the moment is expecting multiple connections from different clients.

Categories