python UDP socket check connection - python

I have a small python console that works over UDP.
The problem I'm having is that if I abruptly disconnect from the client, the connection stays open in netstat (because it's UDP).
I have tried implementing a threading.Timer in the server that asks if the connection is active, and if the client does not respond within that time, the connection closes from the server-side.
This is what I tried
def check_conn(sock: socket.socket):
# sock.settimeout()
sock.send(b"\nAwake?")
try:
ack = sock.recv(1024)
ack = ack.decode("UTF-8")
if ack.strip() == "Yea":
pass
else:
sock.close()
except:
sock.close()
so = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
so.connect((host, port))
t = threading.Timer(10.0, check_conn, [so])
t.start()
data = so.recv(1024)
#rest of the main program
The problem I'm having is that when it asks for the password, two so.recv(1024) are open, and it does not know how to handle them (that's my guess).

Related

server-client where the client listens and responds in a loop doesn't work (python)

I'm building a Client-Server connection for an assignment. The server basically runs everything and the client only receives messages from the server and responds when the server needs it to.
For some reason, I can't build a client that repeatedly listens and then responds.
I thought that I could just listen with socket.recv() and it ended up just stopping everything.
this is what I ended up with after some tweaking (for the client) :
import socket
HOST = 'localhost'
PORT = 65432
conn = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
conn.connect((HOST, PORT))
conn.setblocking(False)
while True :
try :
msg_lgn = len(conn.recv(1024,socket.MSG_PEEK))
server_message = conn.recv(1024).decode()
print('Server Sent:\n' + server_message)
if server_message == 'exit':
break
except :
conn.send(input().encode())
conn.close()
I set it to non-blocking so it won't hang on the conn.recv() and move on to input in the exception, but then it just freezes on the input.
does the server close the connection every time recv() gets nothing ? why is this happening ?
I just want the client to receive messages whenever the server sends them, and when the server doesn't send, the client will send the server it's input.
would appreciate any help!
Lidor
Edit : the server file is much bigger, so i'll show the important parts.
#imported some classes for the game itself also (that i've created), but has nothing to do with the problem
import socket
import time
import threading
def startGame(conn):
#this is where the servers sends the questions and receives answer (pretty basic send and recv)
# Establish Client-Server Connection
HOST = 'localhost' # Standard loopback interface address (localhost)
PORT = 65432 # Port to listen on (non-privileged ports are > 1023)
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((HOST, PORT))
s.listen(3)
# Use Threading to start the game for an new player
while True:
if playerCount < 3:
(conn, addr) = s.accept()
playerCount += 1
x = threading.Thread(target=startGame, args=(conn,))
x.start()
# Close Server Socket
s.close()

Getting a ConnectionResetError when client script is stopped on UDP socket

I am making a script that will allow multiple clients to see live camera footage from the server script, this all works fine until one of the client scripts is closed, then a ConnectionResetError is raised, To avoid this I used a try and except block to catch the ConnectionResetError but the same error is raised every time after a connection is lost. Using just socket.recv stops the ConnectionResetError but socket.recv does not return the senders address which is required for the script to send the video stream back to the client.
Server:
host = "0.0.0.0"
port = 5000
buffer_size = 1024
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.bind(("", port))
listeners = list() # the addresses of the clients that want the video stream
def handle_queue(sock):
while True:
try:
message, address = sock.recvfrom(buffer_size) # block the thread until a packet arrives
print(address)
message = str(message, "utf-8") # decode the message
if message == "join":
listeners.append(address) # add the list of listeners
else:
print("unknown queue msg: ", message)
except ConnectionResetError:
print("The connection was forcefully quit")
queue_handler_thread = Thread(target=handle_queue, args=(sock,), daemon=True)
queue_handler_thread.start() # start the queue
the script then uses sock.sendto() for each address in the listeners list
Client:
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.sendto(bytes("join","utf-8"), (host, port))
while True:
data, address = sock.recvfrom(max_length) # block main thread until a packet is received
I believe what you are looking for is socket.getpeername().
This will return the remote address to which the socket is connected.
Your approach in handling the data in the wire whilst the connection is closed/lost is the right way. Handling via try/catch or using a recv() or recvfrom() method to wait for a response before closing the socket.
Since posting this i have discovered that it is infact TCP and this will not work for the project I am trying to do. Any more guidance and help would be appreciated, I cant seem to find any examples of Multiclient UDP Servers that run through one socket.
I partially resolved my system, after using the Example provided by AztCrw4282.
I was able to find a solution, I instead used the socket.accept() aproach, I am unsure as to whether this is UDP or TCP (I want UDP but with the connect system I think that is the handshake for TCP, but I am not 100% sure), but it works for now.
The client has to connect to the server then the server will accept or deny the connection, upon accepting a thread will be created for that clients connection to be managed. If any errors are thrown when interacting with that client their connection will be closed.
Server
try:
ServerSocket.bind((host, port))
except socket.error as e:
print(str(e))
print('Waiting for a Connection..')
ServerSocket.listen(5)
connections = list()
def threaded_client(connection):
connection.send(str.encode('Welcome to the Server\n'))
while True:
try:
data = str(connection.recv(2048),"utf-8") # this needs to be try catched
print("Packet Recv: ", data)
if data == "join":
print("Client Joined")
if data == "quit":
break
if not data:
break
except ConnectionResetError:
break
print("Closing a connection") # need to handle leaving the stream
connection.close()
def handle_stream():
for connection in connections:
try:
connection.send(bytes(json.dumps(frame_info) ,"utf-8"))
except:
print("Packet send failure, kicking client")
connections.remove(connection)
while True:
Client, address = ServerSocket.accept()
print('Connected to: ' + address[0] + ':' + str(address[1]))
connections.append(Client)
Thread(target=threaded_client, args=(Client, ), daemon=True).start()
ThreadCount += 1
print('Thread Number: ' + str(ThreadCount))
The only part that changes for the client is the part where it connects to the server
try:
ClientSocket.connect((host, port))
except socket.error as e:
print(str(e))

How to fix multiprocessing echo server to handle multiple clients

I want to create a multiprocessing echo server. I am currently using telnet as my client to send messages to my echo server.Currently I can handle one telnet request and it echos the response. I initially, thought I should intialize the pid whenever I create a socket. Is that correct?
How do I allow several clients to connect to my server using multiprocessing.
#!/usr/bin/env python
import socket
import os
from multiprocessing import Process
def create_socket():
# Create socket
sockfd = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# Port for socket and Host
PORT = 8002
HOST = 'localhost'
# bind the socket to host and port
sockfd.bind((HOST, PORT))
# become a server socket
sockfd.listen(5)
start_socket(sockfd)
def start_socket(sockfd):
while True:
# Establish and accept connections woth client
(clientsocket, address) = sockfd.accept()
# Get the process id.
process_id = os.getpid()
print("Process id:", process_id)
print("Got connection from", address)
# Recieve message from the client
message = clientsocket.recv(2024)
print("Server received: " + message.decode('utf-8'))
reply = ("Server output: " + message.decode('utf-8'))
if not message:
print("Client has been disconnected.....")
break
# Display messags.
clientsocket.sendall(str.encode(reply))
# Close the connection with the client
clientsocket.close()
if __name__ == '__main__':
process = Process(target = create_socket)
process.start()
It's probably a good idea to understand which are blocking system calls and which are not. listen for example is not blocking and accept is blocking one. So basically - you created one process through Process(..), that blocks at the accept and when a connection is made - handles that connection.
Your code should have a structure - something like following (pseudo code)
def handle_connection(accepted_socket):
# do whatever you want with the socket
pass
def server():
# Create socket and listen to it.
sock = socket.socket(....)
sock.bind((HOST, PORT))
sock.listen(5)
while True:
new_client = sock.accept() # blocks here.
# unblocked
client_process = Process(target=handle_connection, args=(new_client))
client_process.start()
I must also mention, while this is a good way to just understand how things can be done, it is not a good idea to start a new process for every connection.
The initial part of setting up the server, binding, listening etc (your create_socket) should be in the master process.
Once you accept and get a socket, you should spawn off a separate process to take care of that connection. In other words, your start_socket should be spawned off in a separate process and should loop forever.

Python - How to end a socket using a "with as" block

I'm learning about sockets and connections and trying to write a simple server Python script that echos a message to a client.
I began with just running a script that prints what it receives from a socket.
So i'm running what i wrote locally and using Putty as a client (so the message isn't printed to the putty session yet).
This is my code:
import socket
HOST = '127.0.0.1'
PORT = 65432
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.bind((HOST, PORT)) # bind accepts a tuple of a hostname or address and a port
s.listen()
conn, addr = s.accept() # returns a pair
with conn:
print("Connection started!", conn, addr)
data = conn.recv(1024)
while data:
data = data.decode("UTF-8")
print(data)
# if data == "exit":
# shutdown and close the connection,
# and ofcourse exit the two with as blocks gracefully
data = conn.recv(1024)
print("Connection is closed and the program continued")
Running this works but i have no way of terminating the connection other then killing the server.
I believe that data will always be true since i'm using putty and it seems that even when i'm hitting enter with no text to the connection window, it actually sends this:
b'\r\n'
So I tried placing this inside the commented if statement:
conn.shutdown(socket.SHUT_RDWR)
conn.close()
Hoping this will just make the socket be deleted - but it didn't work.
So what I want to do is to exit the with blocks and deleting the sockets without having to raise any exceptions or make the program stop. I tried doing so using python 3 change to socket that made it usable with with-as statements. I tried just calling the conn.__exit__ or s.__exit__ function but that didn't work also.
How can I close the socket and exit the two with blocks using an input from the user? Is there anything i'm confusing with the socket module here?

Python Socket Scripting. What am i doing wrong?

My socket program hangs at clientsocket, address) = serversocket.accept() and doesn't spit our an error or anything.
I followed directions on https://docs.python.org/3/howto/sockets.html
I've been trying to figure it out for an hour now, but to no avail. I'm using python3 btw. What am i doing wrong? EDIT: My intedentation is all screwed up because I pasted it wrong, but other than that my code is as I have it in my file.
#import socket module
import socket
#creates an inet streaming socket.
serversocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
print('socket created')
#binds socket to a public host, and a well known port
serversocket.bind(('127.0.0.1', 1024))
#print(socket.gethostname())# on desktop prints 'myname-PC')
#become a server socket
serversocket.listen(5) # listens for up to 5 requests
while True:
#accept connections from outside
#print('In while true loop') This works, but we never get to the next print statement. Why the hell is it catching at line 20?
(clientsocket, address) = serversocket.accept()
#clientsocket = serversocket.accept()
print('Ready to serve')
#now we do something with client socket...
try:
message = clientsocket.recv(1024)
filename = message.split()[1]
f = open(filename[1:])
outputdata = f.read()
#send an http header line
clientsocket.send('HTTP/1.1 200 OK\nContent-Type: text/html\n\n')
for i in range(0, len(outputdata)):
clientsocket.send(outputdata[i])
clientsocket.close()
except IOERROR:
clientsocket.send('HTTP/1.1 404 File not found!')
clientsocket.close()
If you haven't written a client script / program to connect to the socket and send it data, it's also going to hang on serversocket.accept() due to there being nothing to accept. But assuming you have...
while True:
#accept connections from outside
#print('In while true loop') This works, but we never get to the next print statement. Why the hell is it catching at line 20?
(clientsocket, address) = serversocket.accept()
#clientsocket = serversocket.accept()
It hangs because the loop never exits due to True always being True. In the example provided, once a connection is accepted they pretend that the server is threaded and the idea is to create a separate thread to begin reading and processing data received allowing the socket to continue to listen for more connections.
while True:
# accept connections from outside
(clientsocket, address) = serversocket.accept()
# now do something with the clientsocket
# in this case, we'll pretend this is a threaded server
ct = client_thread(clientsocket)
ct.run()

Categories

Resources