I'm trying to create a client/server console game, but I'm having trouble keeping the socket alive, it seems to be closing before I've called close() and I can't figure out why.
I've read the thread here but I have called connect() outside of the while loop since the logic of that already made sense to me before I attempted to run it, but I'm still getting the error from the server shell though:
ConnectionAbortedError: [WinError 10053] An established connection was aborted by the software in your host machine
So far I'm not getting an error on the client shell, it just exits running right after launching which is also when the server error occurs.
After fixing mistakes noted in the comments, the client now also shows an error stating that connected is undefined when attempting to start the while loop but should be since Connect() is run before entering the loop which should have set connected = True thus the loop should run but does not. I doubt this is related to the server issue at all, but what maybe the problem here?
I'll put the code for both below:
Client
import socket
def GetData():
data = s.recv(1000).decode()
if (data == "closing"):
connected = False
else:
print(data)
def SendData():
tdata = input("")
s.send(data.encode())
def Connect():
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(("127.0.0.1", 2222))
connected = True
global connected
Connect()
while (connected == True):
GetData()
if (connected == False):
s.close()
break
SendData()
Server
import socket
import random
def TheMainGame():
print ("started TheMainGame") # Remove after debug
def within(val, goal):
print ("Runing 'within' function") # Remove after debug
i = abs(val - goal)
if (i <= 5):
return True
else:
return False
def Guess():
print ("Running 'Guess' function") # Remove after debug
while True:
print ("Entered while loop") # Remove after debug
data = "What is your guess?"
c.send(data.encode())
print ("Sent data") # Remove after debug
t = c.recv(1000).decode()
print ("Got data") # Remove after debug
if (t == x):
data = "Correct!"
c.send(data.encode())
data = "closing"
c.send(data.encode())
c.close()
break
elif (within(t,x) == True):
data = "You're close!"
c.send(data.encode())
elif (within(t,x) == False):
data = "Try again"
c.send(data.encode())
else:
data = "There was an error computing the value"
c.send(data.encode())
c.close()
break
x = random.randrange(1, 20, 1)
Guess()
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind(("127.0.0.1", 2222))
s.listen(5)
global data
while True:
(c,a) = s.accept()
print("Received connection from", a) # Remove after debug
data = "Hello %s" %a[0] # Remove after debug
c.send(data.encode()) # Remove after debug
TheMainGame()
The error in the server shell relates to line 19 which is why the server attempts to ask the client the question, which is also the second time it attempts to send data to the client but the attempt never successfully happens, which is why I think the socket is being closed even though I never told it to anywhere before that point since it hasn't even been able to check if t == x. What is causing the socket to close?
You're mis-using global in the client.
in the main body you have global connected. This is incorrect.
Instead, at the top of the file put:
import socket
connected = False
Then, in the Connect function, pull in the global scoped variable:
def Connect():
global connected
...
The keyword global is to tell a function to use a variable from the global scope, not to define them.
Note:
There are other errors in this code which you will need to look at and address.
You've done the same in server.py
You're trying to reference socket s in the GetData and SendData functions but s is local to within the connect function only (meaning that the connection will drop once the function exists.
Related
I have a sort of strange issue here. I am somewhat new to python and especially parallel TCP sockets in Python. I followed a guide to make a multi-client TCP server that runs using multiprocessing so I can maintain a front end control.
My understanding of passing variables in Python multiprocessing is using the args parameter when calling the multiprocessing.Process function.
However to start my TCP server my target isn't actually a def (function) and I am unsure how to properly pass a boolean value that will allow me to enable a debug mode in my code on the server process.
See code below:
import os
import datetime
import socket
import jetson.inference
import jetson.utils
import sys
import multiprocessing
import socketserver
from cv2 import *
class ThreadedTCPRequestHandler(socketserver.BaseRequestHandler): #Class to process multiple clients if needed, handles sending and receiving messages as well as interperating them
def handle(self):
#cam_port = 0
if not os.path.exists("Images"):
os.makedirs("Images")
net = jetson.inference.detectNet("ssd-inception-v2", sys.argv, 0.5)
inputC = jetson.utils.videoSource("/dev/video0", argv=sys.argv)
# create video sources & outputs
#input = jetson.utils.videoSource(opt.input_URI, argv=sys.argv)
while True:
#print("Got here")
# self.request is the TCP socket connected to the client
self.data = self.request.recv(250).strip()
print("{} wrote:".format(self.client_address[0]))
rec = self.data.decode('utf-8')
print(rec)
if rec == "TRIGGER":
#cam = VideoCapture(cam_port)
#result, image = cam.read()
#processTrigger(cam, result, image, net)
processImage(net, inputC, debug)
double = "DOUBLE"
msg = double.encode('utf-8')
self.request.sendall(msg)
class ThreadedTCPServer(socketserver.ThreadingMixIn, socketserver.TCPServer): #Class to bind each client to a thread
pass
def openServer(thread, server, isCreate): #function that handles opening and closing the tcp server
if isCreate:
with server:
print("Server running as ", thread.name, "on", server.server_address)
return thread
if not isCreate:
with server:
thread.terminate()
print("Server and Process terminated")
def processImage(network, inputC, debug):
# saving image in local storage
img = inputC.Capture()
detections = network.Detect(img, overlay="box,labels,conf")
print("detected {:d} objects in image".format(len(detections)))
print(debug)
for detection in detections:
print(detection)
if debug:
dateNow = datetime.datetime.now()
currentMSStr = dateNow.strftime("%f")
currentMS = round(int(currentMSStr)/1000)
outputFile = "Images/Capture_"+dateNow.strftime("%y_%m_%d_%H_%M_%S")+"_"+str(currentMS)+".png"
output = jetson.utils.videoOutput(outputFile, argv=sys.argv+['--headless'])
network.PrintProfilerTimes()
output.Render(img)
print("Warning! Debug mode is enabled, this should not be used during normal operation!")
debug = False #global debug boolean
if __name__ == "__main__":
enabled = True
serverOpen = False
HOST, PORT = "", 3334
print("Welcome to the Fives Vision Solution")
print("Press 1 to enable the server")
print("Press 2 to shutdown the server")
print("Press 3 to change server port")
print("Press 4 to enable debug mode. WARNING impacts performance!")
print("Press 5 to exit")
while enabled:
choice = input("Make a selection... \n")
if choice == '1': #Create socket and send to process to run in background
if serverOpen:
print("Server is already active")
if not serverOpen:
try:
server = ThreadedTCPServer((HOST, PORT), ThreadedTCPRequestHandler)
server_proc = multiprocessing.Process(target=server.serve_forever)
server_proc.daemon = True
server_proc.start()
openServer(server_proc,server,True)
serverOpen = True
except Exception as e:
print("Error occured: ", e)
elif choice == '2': #Terminate the server and close process
openServer(server_proc,server,False)
serverOpen = False
elif choice == '3': #Change port
if serverOpen:
print("Please close the server first.")
if not serverOpen:
print("Please enter a port:")
try:
port = input()
if int(port) > 1024 and int(port) < 65500:
PORT = int(port)
print("Port is now set to: ", PORT)
if int(port) < 1024 or int(port) > 65500:
print("Invalid port, must be a number between 1023 and 65500")
except:
print("Invalid port, must be a number between 1023 and 65500")
elif choice == '4': #Enable or disable debug mode
if debug:
debug = False
print("Debug set to: " ,debug)
continue
if not debug:
debug = True
print("Debug set to: " ,debug)
continue
elif choice == '5': #Terminate server is open and close the program
enabled = False
if (serverOpen):
openServer(server_proc,server,False)
else:
print("Invalid choice")
As you can see, line 87 initiates the server, and line 88 calls the actual server to serve in another process:
server = ThreadedTCPServer((HOST, PORT), ThreadedTCPRequestHandler)
server_proc = multiprocessing.Process(target=server.serve_forever)
How would I go about passing my global variable "debug" into my actual handle(self) function in my server class, which actually does the processing of the incoming message, calls a machine learning model and then returns the result back to the client.
Like I said, I'm pretty new to python so forgive me if there are better ways to do what I'm doing.
About the code:
My main issue is that I need debug mode because I want to be able to enable saving the images I process but doing so takes my total round trip of receiving a message, processing, and returning a result to around 200-250ms, and I need to run in less than 100ms.
When I disable the code within the debug if statement, my total receive/return time is around 40ms which is great, but if the system has issues I want to be able to store the results in image form for debugging camera issues and so on.
Thanks for any help!
I am opening the same program multiple times (10 to be exact) and i they are all trying to solve the random number first. When they solve this number they open a server which all of the other same programs are listening to on separate threads waiting to connect and when they do finally connect i want them all to shutdown.
import random
import os
import socket
import threading
import time
host = '192.168.1.139'
port = 8011
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
def verified():
print('Connection made successfuly')
time.sleep(10)
quit()
def network():
try:
s.connect(('192.168.1.135',8014))
f = s.recv(50)
finished = f.decode('utf-8')
if finished == 'completed':
quit()
except:
pass
def winner():
x = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
x.bind(('192.168.1.135', 8014))
x.listen(10)
con, address = x.accept()
con.send(bytes('completed', 'utf-8'))
def mine():
global guess
time.sleep(.000001)
guess = random.randint(0,1000)
print(guess)
tran = 500
while True:
mine()
if guess == 500:
print("Solved")
winner()
break;
else:
x = threading.Thread(target=network)
x.start()
For some reason it is connecting to the server but it isn't quitting the program, could this be because it is connecting to itself and exiting to fast? Please help, Thank You!
Actually, I was consfused, but apparently when the quit() is in a function it can't end the whole process, so what I would suggest you to do is to make the while loop with a variable that network would be able to change (or even use guess):
guessing = True
while guessing:
mine()
if guess == 500:
print("Solved")
winner()
break;
else:
x = threading.Thread(target=network)
x.start()
and change the network to:
def network():
try:
s.connect(('192.168.1.135',8014))
f = s.recv(50)
finished = f.decode('utf-8')
if finished == 'completed':
#quit()
global guessing
guessing = False
except:
pass
I saw that the two constants host and port were not used
Unfortunately the winner function is just accepting one answer
(she's a little introvert)
but we can solve that problem:
def winner():
x = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
x.bind(('192.168.1.135', 8014))
x.listen(10)
connected = 0
while connected < 10:
con, address = x.accept()
con.send(bytes('completed', 'utf-8'))
connected += 1
and yay, she is making friends
ok, but now she is in the outer world where she needs to talk to a lot of people
not just limited 10, so she goes to the bus stop (she's going home), she waits a little bit to see if someone will talk to her (for any reason), no one said anything for some time, so, she puts her airpods and starts listening to some good {insert here a music that a computer function likes to listen to}
So, to implement this:
def winner():
x = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
x.settimeout(5) # WAITS FOR FIVE SECONDS
x.bind(('192.168.1.135', 8014))
x.listen()
while True:
try:
con, address = x.accept()
con.send(bytes('completed', 'utf-8'))
except socket.timeout: # IF IN FIVE SECONDS, RECEIVES NO CONNECTION
break
the x.settimeout(5) will make the connections give an socket.timeout error if the time set (in case 5) is exceeded without any response of the other side.
now I remembered that using threading we could push clients to another function and "free" the queue of the clients, but I think that for this special case this solution is better
So I'm trying to write a program that gets a continuous stream of data from a server, in a thread. The data being sent from the server is always very short, but does range in length
I'm currently trying to use the recv function in the socket library to constantly receive data, but for some reason I'm not getting anything at all. I know a common problem with the recv function is that it sometimes splits up the data, but for me it's not receiving anything. I know that the problem doesn't come from the server, because when the client connects it does receive confirmation from the server. Is this because I'm trying to do this in a different thread?
This is the socket part of my code:
client = socket(AF_INET, SOCK_STREAM)
def connectToServer(host, port):
global client
try:
client.connect((host, port))
connectionResult = client.recv(2048).decode()
if connectionResult == 'succesfull connection':
return connectionResult
else:
return 'connection failed'
except:
return 'connection failed'
# This function is ran in a thread (from another module)
def getUpdatesFromServer(updateQueue):
global client
while True:
receivedUpdate = client.recv(10000).decode()
if receivedUpdate == 'server went down':
updateQueue.put('server went down')
And this is the code that starts the Thread:
getUpdatesFromServerThread = Thread(target=ServerConnect.getUpdatesFromServer, args=(GameState.screenUpdateQueue,))
getUpdatesFromServerThread.daemon = True
getUpdatesFromServerThread.start()
The connectToServer function is called here (the first thing that happens when the client is ran):
connectionOutcome = ServerConnect.connectToServer(host, port)
if connectionOutcome == 'succesfull connection':
startGame()
else:
print('\n\nFailed to connect to the server. Please check your internet connection. If your internet connection is okay, it probably means the server is down and you should wait for a while.\n\n')
And here is the startGame function:
def startGame():
print('You have been succesfully connected to the server.')
getUpdatesFromServerThread = Thread(target=ServerConnect.getUpdatesFromServer, args=(GameState.screenUpdateQueue,))
getUpdatesFromServerThread.daemon = True
getUpdatesFromServerThread.start()
screenUpdateThread = Thread(target=doScreenUpdates)
screenUpdateThread.daemon = True
screenUpdateThread.start()
sleep(1)
MainGameScreen.main()
# When the eventloop stops, this is ran and sends a disconnect signal to the server, which closes the connection (which does work)
sleep(0.5)
ServerConnect.sendCommandToServer('disconnect')
Thank you in advance!
Edit: I've found the problem. I thought the server was sending data, but in fact it wasn't, it just didn't give any error message, so I assumed that was working.
Im sure there are easier ways with particular python modules, but for an assignment I need to create a program that can act as a client/server. As of right now I have it working to the point of only being able to send a message if the reciever has responded. I need it to just send and appear on the respective client/server terminal when enter is pressed. Any help would be greatly appreciated!
These are pictures of what happens as of now
https://i.stack.imgur.com/T9CsJ.png
import sys
import socket
import getopt
def usage(script_name):
print('Usage: py' + script_name + '-l' +' <port number>' + '[<server>]')
def sockObj():
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
return sock
def serversockConn(serversocket,port):
serversocket.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
# bind the serversocket to address
serversocket.bind(('',int(port)))
# enable a server to accept connections
serversocket.listen(5)
# wait for a connection and accept it
sock,addr = serversocket.accept()
return sock
def connToServersock(sock,server, port):
# connect to a serversocket
if server:
sock.connect((server, int(port)))
else:
sock.connect(('localhost', int(port)))
return sock
if __name__ == '__main__':
## get the command line arguments
try:
options, non_option_args = getopt.getopt(sys.argv[1:],'l')
except getopt.GetoptError as err:
print(err)
sys.exit(2)
#check if '-l' is present in command line agrument
serverSide = False
for opt,arg in options:
if opt == "-l":
serverSide = True
# port number
port = non_option_args[0]
# server address
server = None
hostLen = len(non_option_args)
if hostLen == 2:
server = non_option_args[1]
# create a communicator object, and make a connection between server and client
# server
if serverSide:
serversocket = sockObj()
sock = serversockConn(serversocket,port)
# client
else:
sock = sockObj()
sock = connToServersock(sock,server,port)
while True:
## read a message from standard input
message = sys.stdin.readline().encode()
if len(message) != 0:
sock.send(message)
return_msg = sock.recv( 1024 )
if return_msg:
print("Message recieved: " + return_msg.decode())
else:
print("Other side shut down")
else:
try:
sock.shutdown(socket.SHUT_WR)
sock.close()
except:
pass
I think your issue is that there are two places in your event loop where you block:
message = sys.stdin.readline().encode()
Here, you block until the user has pressed return -- during this time, your program is unable to respond to any data received over the network, because it is blocked waiting for data from stdin.
... and:
return_msg = sock.recv( 1024 )
Here, you are waiting for data to be received from the network -- during this time, your program is unable to respond to any data received from stdin, because it is blocked waiting for data from the network.
The behavior you'd ideally like to have is for your program to wait for both stdin and network traffic simultaneously -- i.e. have it block until either the user has pressed return, or some network data has been received, whichever comes first.
The easiest way to achieve that behavior is to use select(); its purpose is to block until at least one of several file descriptors is ready to be acted on. (Note, however, that Windows does not support using select() on stdin, so if your program needs to run under Windows you will probably have to spawn a second thread instead).
To implement the event loop using select(), add import select to the top of your script, then replace your event loop with something like this instead:
while True:
## block here until either sock or sys.stdin has data ready for us
readable, writable, exceptional = select.select([sock, sys.stdin], [], [])
if sys.stdin in readable:
## read a message from standard input
message = sys.stdin.readline().encode()
if len(message) != 0:
sock.send(message)
if sock in readable:
## read a message from the network
try:
return_msg = sock.recv( 1024 )
if (return_msg):
print("Message received: " + return_msg.decode())
else:
print("Other side shut down")
break
except:
print("recv() threw an exception")
break
I've tried looking about for an answer but I can't seem to find one that answers my specific problem.
Perhaps I don't know how to articulate the problem correctly.
I think I've pinpointed what it is, but the thing is I just don't know how to fix it.
EDIT: I was trying to use two clients on one TCP Socket. Can't do that. I'll have to think of another way. Solved, I guess.
So what I've got is are
1: Two Clients
2: One Server
The objective is this:
Have the server distribute new usernames to all the clients as they connect.
This is what happens when I run the program:
Server: Define Host, and Port, initialize it. Check
Client 1: Connects to the server. Check
Client 1: Once connected, sends a string to the server. Check
Server: Receives a string, checks if the string is in a list is created. If it is: Pass, if it's not, send to everyone the new string. Check
Client 1: [Now waiting to receive data] Recieves data, checks if the string received matches the one it sent. If it does, print("It's one of ours!"), else, make the new string = to Client 2 Username. Check
Client 2: Connects to server: Check
Server: [If it receives a string, prints it.] (Works) Checks if the new string is in the list. [It isn't] So It sends the new username to everyone, and then prints ("Sent to everyone") Check
But, when client 2 receives the string, it prints it. However, client 1 never recives the string.
And when running client one in IDLE, I noticed something went wrong as Client 1 tried to receive the data. (The while loop that the data = s.recv began looping real fast, instead of waiting)
I've asked around in chat, but it seems nobody's around right now. I've tried looking this up but I really can't find an answer. What I suspect is happening is that when my server sends to 'connection' the second time, it somehow overrides the original client connection.
Here's my server code:
from socket import *
import threading
import os
import csv
Username_List = []
host = input("Host: ")
port = input("Port: ")
ss = socket(AF_INET,SOCK_STREAM)
ss.bind((host,int(port)))
ss.listen(2)
while True:
try:
connection,address = ss.accept()
data = connection.recv(1024)
if data:
translated_data = data.decode()
print(translated_data)
if translated_data in Username_List:
pass
else:
Username_List.append(translated_data)
connection.sendall(translated_data.encode())
print("Sent new username to everyone")
except IOError:
connection.close()
print("An exception with a connected user occured")
break
And here is my client code: [The only difference between client 1 and 2 is I changed the username variable]
# Sample Username Client Service Handler.
from socket import *
import threading
import os
import csv
Username = ("Owatch")
host = input("Host: ")
port = input("Port: ")
try:
ss = socket(AF_INET,SOCK_STREAM)
ss.connect((host,int(port)))
except IOError:
print("Aw no man")
ss.send(Username.encode())
while True:
try:
print("Waiting to Recieve Data")
data = ss.recv(1024)
if data:
translated_data = data.decode()
print(translated_data)
if translated_data == Username:
print("It's one of ours!")
else:
Client_Username = translated_data
print (Client_Username)
except Exception as e:
print (vars(e))
If you could please help I'd be grateful.
If you know of an answer to my question that's already been asked, please tell me and I'll remove this post to avoid breaking rules. Thanks!
Right then I started with what you had then changed it till it worked what I've done is created a client class which starts a thread with each connection and adds it to a list of threads (please if I'm doing something horribly wrong smarter people correct me), the thread runs gets some data checks if that's in the list of user names if its not sends out a message to all the clients in the thread list with that name then the thread just chills out. Anyway on to the code.
SERVER!!!
import csv
class client(threading.Thread):
Username_List = []
def __init__(self, conn):
super(client, self).__init__()
self.conn = conn
def run(self):
print "Client thread started"
data = self.conn.recv(1024)
print "Received: {0}".format(data)
if data in client.Username_List:
self.send_msg("Welcome Back!")
else:
for cnt in threadz:
cnt.send_msg(data)
print("Sent new username to everyone")
client.Username_List.append(data)
while True:
# dont need nothing now
pass
def send_msg(self,msg):
self.conn.send(msg)
host = input("Host: ")
port = input("Port: ")
ss = socket() #AF_INET,SOCK_STREAM)
ss.bind((host,int(port)))
print "Server Opening on port: {0}".format(port)
ss.listen(2)
threadz = []
print "Begining Wait for connections"
while True:
try:
connection, address = ss.accept()
print "Got ONE!"
c = client(connection)
print "Recevied connection from:{0} On port:{1}".format(address[0],address[1])
c.start()
threadz.append(c)
print "Client appended to threadz, currently {0} threadz active".format(len(threadz))
except IOError,KeyboardInterrupt:
connection.close()
print("An exception with a connected user occured")
break
The CLIENT:
# Sample Username Client Service Handler.
from socket import *
import threading
import os
import csv
Username = ("ShyGuy")
host = input("Host: ")
port = input("Port: ")
try:
ss = socket() #AF_INET,SOCK_STREAM)
ss.connect((host,int(port))) #I was using ("localhost",1234) for testing
ss.send(Username)
except IOError:
print("Aw no man")
print("Waiting to Recieve Data")
while True:
try:
data = ss.recv(1024)
if data:
translated_data = data.decode()
print(translated_data)
if translated_data == Username:
print"Name: {0} has been registered on server!".format(translated_data)
else:
Client_Username = translated_data
print "New client name received: {0}".format(Client_Username)
except Exception as e:
print (vars(e))
That works on python 2.7 with two clients locally. Needs to use a semaphore to stop the threads printing at the same time as the main server loop prints: http://en.wikipedia.org/wiki/Semaphore_(programming)
This code does nothing graceful with client disconnects, but once you can work with the exceptions that a raised when that happens I'm sure you'll learn some more.