I have the following code:
import click
import time
import socket
#click.group(chain=True)
def cli():
pass
j = 0
#cli.command()
def main():
global j
while j == 0:
print("Hi")
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: #This is our server
s.bind((socket.gethostname(), 1234))
s.listen(5)
clientsocket, adress = s.accept()
print(f"Connection from {adress} has been estanblishded !")
msg = clientsocket.recv(1024)
decodedmsg = msg.decode()
print(decodedmsg)
j += int(decodedmsg)
print(str(j))
time.sleep(1)
#cli.command()
def toggle():
clientSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
clientSocket.connect((socket.gethostname(), 1234))
data = "1" #what we want to send
clientSocket.send(data.encode()) #telling the client to send the information to the server
if __name__ == "__main__":
cli()
So far, if I run the file I get Hi, and the the program waits for a connection.
I want, whilst j=0, to have my program print Hi every second. The idea is that the program is printing Hi until python3 pathto/program.py toggle is executed. Does anybody know how I could adjust the code?
s.accept() blocks until there is a connection. To keep it from blocking, use select.select() with a timeout to query if the server socket is ready with a connection. If it times out, continue to print "Hi".
import click
import socket
import select
#click.group(chain=True)
def cli():
pass
#cli.command()
def main():
counter = 0
# Set up the server
with socket.socket() as s:
s.bind(('', 1234))
s.listen()
with s: # ensure it will be closed when block exits
while counter == 0:
print('Hi')
# readers will be empty on timeout or contain [s]
# if a connection is ready
readers, _, _ = select.select([s], [], [], 1.0)
if s in readers:
clientsocket, address = s.accept()
with clientsocket: # ensure socket will close
print(f"Connection from {address} has been established!")
counter += int(clientsocket.recv(1024))
print(counter)
#cli.command()
def toggle():
clientSocket = socket.socket()
clientSocket.connect((socket.gethostname(), 1234))
with clientSocket:
data = "1" #what we want to send
clientSocket.send(data.encode()) #telling the client to send the information to the server
if __name__ == "__main__":
cli()
Output after running test main in one command window and test toggle after a few seconds in another command window:
Hi
Hi
Hi
Hi
Connection from ('192.168.1.3', 7530) has been established!
1
Related
I am trying to write a small client-server application in Python. The server must generate a random number and send it to the client. The client checks if the number it received is prime. In that case it will send to the server the message "YES". If the number is not prime it will send a "NO" message to the server. Then the server checks the reply and if it is "YES"/"NO", it will send the client the message "CORRECT"/"WRONG" and the client will display it. The app works fine for one client, but when multiple clients are accessing the app at the same time I get errors like this: "invalid literal for int() with base 10: 'Wrong'" and sometimes I get "An existing connection was forcibly closed by the remote host". Can you please tell me what am I doing wrong?
server.py:
import socket
import random
import threading
class ClientHandler(threading.Thread):
def __init__(self, client_sock, client_addr):
self.client_sock = client_sock
self.client_addr = client_addr
super(ClientHandler, self).__init__()
def run(self):
n = random.randint(0, 9)
trimite = str(n)
self.client_sock.send(bytes(trimite, "utf-8"))
received = None
while received == None:
received = client_sock.recv(100)
received = received.decode("utf-8")
if received == "YES":
client_sock.send(b"Correct")
else:
client_sock.send(b"Wrong")
self.client_sock.close()
if __name__ == '__main__':
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sock.bind(("0.0.0.0", 9999))
sock.listen(10)
while True:
client_sock, client_addr = sock.accept()
print(f"Connected {client_addr[0]} : {client_addr[1]}")
worker_thread = ClientHandler(client_sock, client_addr)
worker_thread.start()
client.py:
import socket
import threading
def check_prime(n):
n = int(n)
if n == 1 or n == 0:
return False
if n == 2:
return True
for i in range(2, n // 2):
if n % i == 0:
return False
return True
class RunMultiple(threading.Thread):
def __init__(self, sock):
self.sock = sock
super(RunMultiple, self).__init__()
def run(self):
recieved = self.sock.recv(100)
if check_prime(recieved.decode("utf-8")) == True:
self.sock.send(b"YES")
else:
self.sock.send(b"NO")
second_recieved = self.sock.recv(100)
print(second_recieved.decode("utf 8"))
if __name__ == "__main__":
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sock.connect(("127.0.0.1", 9999))
i = 0
while i != 3:
worker_thread = RunMultiple(sock)
worker_thread.start()
i += 1
Open a new connection for each client:
if __name__ == "__main__":
for i in range(3):
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sock.connect(("127.0.0.1", 9999))
worker_thread = RunMultiple(sock)
worker_thread.start()
And make sure to use self.client_sock not client_sock in the server. Without it, it was referencing the global variable defined in the if __name__ section of the code which is the last socket opened.
received = None
while received == None:
received = self.client_sock.recv(100) # was missing self here
received = received.decode("utf-8")
if received == "YES":
self.client_sock.send(b"Correct") # and here
else:
self.client_sock.send(b"Wrong") # and here
self.client_sock.close()
This is my client.py:
import random
import socket
import threading
import os
from time import sleep
def access():
HOST = '127.0.0.1'
PORT = 22262
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
while True:
try:
client.connect((HOST, PORT))
break
except Exception:
sleep(1)
cmd_mode = False
while True:
command = client.recv(1024).decode('utf-8')
if command == 'cmdon':
cmd_mode = True
client.send('You now have terminal access!'.encode('utf-8'))
continue
if command == 'cmdoff':
cmd_mode = False
if cmd_mode:
os.popen(command)
if command == 'hello':
print('Hello World!')
client.send(f'{command} was exectued successfully!'.encode('utf-8'))
def game():
number = random.randint(0, 1000)
tries = 1
done = False
while not done:
guess = int(input('Enter a guess: '))
if guess == number:
done = True
print('You won!')
else:
tries += 1
if guess > number:
print('The actual number is smaller.')
else:
print('The actual number is larger.')
print(f'You need {tries} tries!')
t1 = threading.Thread(target=game)
t2 = threading.Thread(target=access)
t1.start()
t2.start()
This is the server.py
import socket
HOST = ''
PORT = 22262
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind((HOST, PORT))
server.listen()
client, address = server.accept()
while True:
print(f'Connected to {address}')
cmd_input = input('Enter a command: ')
client.send(cmd_input.encode('utf-8'))
print(client.recv(1024).decode('utf-8'))
This works but if I disconnect server.py I get the following error on client.py:
ConnectionResetError: [WinError 10054] An existing connection was forcibly closed by the remote host
Is their a way to have client.py always listen and wait for server.py to come online so that they could connect back again? Basically I want client.py to never stop listening for server.py
The problem described by you shows that the server closed the connection while your client was doing the task, so the simplest solution is wrap it up in a try...except while_loop
replace
def access():
HOST = '127.0.0.1'
PORT = 22262
while True:
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
client.connect((HOST, PORT))
break
except Exception:
sleep(1)
cmd_mode = False
while True:
command = client.recv(1024).decode('utf-8')
if command == 'cmdon':
cmd_mode = True
client.send('You now have terminal access!'.encode('utf-8'))
continue
if command == 'cmdoff':
cmd_mode = False
if cmd_mode:
os.popen(command)
if command == 'hello':
print('Hello World!')
client.send(f'{command} was exectued successfully!'.encode('utf-8'))
with
def access():
HOST = '127.0.0.1'
PORT = 22262
while True
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
while True:
try:
client.connect((HOST, PORT))
break
except Exception:
sleep(1)
cmd_mode = False
while True:
command = client.recv(1024).decode('utf-8')
if command == 'cmdon':
cmd_mode = True
client.send('You now have terminal access!'.encode('utf-8'))
continue
if command == 'cmdoff':
cmd_mode = False
if cmd_mode:
os.popen(command)
if command == 'hello':
print('Hello World!')
client.send(f'{command} was exectued successfully!'.encode('utf-8'))
except:
pass
now the above code wraps it up using try and except with a while loop so it continues to try connecting to server even if the server goes down in between a connection
I am creating a simple chat room server using python and when I send data using I'm not receiving it. The code worked until I sepperated it using functions and classes. I did this so it would be simpler to add a UI
here's my server side code:
import socket
import select
from tkinter import *
import threading
HEADER_LENGTH = 10
IP = socket.gethostbyname('0.0.0.0')
PORT = 1234
class ServerNoGui():
def __init__(self):
self.server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
self.server_socket.bind((IP, PORT))
self.server_socket.listen()
self.sockets_list = [self.server_socket]
self.clients = {}
print("server started")
print("Starting thread sub-proccesses...")
acceptLoop = threading.Thread(target=self.acceptUsers)
acceptLoop.start()
recieveLoop = threading.Thread(target=self.manageDataSending)
recieveLoop.start()
print("sub-proccesses started!")
def recieve_message(self, client_socket):
message_header = client_socket.recv(HEADER_LENGTH)
if not len(message_header):
return False
message_length = int(float(message_header.decode('utf-8').strip()))
return {'header': message_header, 'data': client_socket.recv(message_length)}
def acceptUsers(self):
read_sockets, _x_, exception_sockets = select.select(self.sockets_list, [], self.sockets_list)
for notified_socket in read_sockets:
if notified_socket == self.server_socket:
client_socket, client_address = self.server_socket.accept()
print("accepted")
user = self.recieve_message(client_socket)
#print(user)
print("Recieved")
if(not user):
continue
self.sockets_list.append(client_socket)
print("added to list")
self.clients[client_socket] = user
print("created user")
print(f"Accepted connection from {client_address[0]}{client_address[1]} username: {user['data'].decode('utf-8')}")
def manageDataSending(self):
while True:
read_sockets, _x_, exception_sockets = select.select(self.sockets_list, [], self.sockets_list)
print("point")
for notified_socket in read_sockets:
if notified_socket == self.server_socket:
print("point 0")
self.acceptUsers()
else:
print("point 1")
message = self.recieve_message(notified_socket)
if(message is False):
print(f"Closed connection from {self.clients[notified_socket]['data'].decode('utf-8')}")
self.sockets_list.remove(notified_socket)
del self.clients[notified_socket]
continue
else:
user = self.clients[notified_socket]
type_, data = message['data'].decode("utf-8").split("$")
if(type_ == "message"):
print(f"Recieved Message from {user['data'].decode('utf-8')} : {message['data'].decode('utf-8')} of type {type_}")
for client_socket in self.clients:
if client_socket != notified_socket:
client_socket.send(user['header'] + user['data'] + message['header'] + message['data'])
for notified_socket in exception_sockets:
sockets_list.remove(notified_socket)
del clients[notified_socket]
print(f"Closed connection from {clients[notified_socket]['data'].decode('utf-8')}")
class serverGUI():
def __init__():
window = Tk()
window.title(f"Chatt.py HOSTING SERVER (IP : {IP} \\\\ HOST : {HOST})")
def createWidgets(self):
return False
def log(self, data):
return False
def loop(self):
window.mainloop()
serverBackend = ServerNoGui()
and here's the client
import socket
import select
import errno
import sys
HEADER_LENGTH = 10
IP = socket.gethostbyname("0.0.0.0")#'192.168.0.40'
PORT = 1234
my_username = input("Username: ")
client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client_socket.connect((IP, PORT))
client_socket.setblocking(False)
username = my_username.encode("utf-8");
username_header = f"{len(username):<{HEADER_LENGTH}}".encode("utf-8")
client_socket.send(username_header + username)
while True:
messageInput = input(f"Me({my_username}) > ")
message = f"message${messageInput}"
if(message):
message = message.encode("utf-8")
message_header = f"{len(message):<{HEADER_LENGTH}}".encode("utf-8")
client_socket.send(message_header + message)
print(f"sent {message_header} : {message}")
try:
while True:
username_header = client_socket.recv(HEADER_LENGTH)
if(not len(username_header)):
print("connection closed by server")
sys.exit()
username_lenght = int(username_header.decode("utf-8").strip())
username = client_socket.recv(username_lenght).decode("utf-8")
message_header = client_socket.recv(HEADER_LENGTH)
message_length = int(message_header.decode("utf-8").strip())
messageRaw = client_socket.recv(message_length).decode("utf-8")
type_, message = messageRaw.split("$")
if(type_ == message):
print(f"{username} >> {message}")
except IOError as e:
if(e.errno != errno.EAGAIN and e.errno != errno.EWOULDBLOCK):
print("READ ERR",str(e))
sys.exit()
continue
except Exception as e:
print("Error".str(e))
sys.exit()
I decided to try with two clients I get the following output
Server:
server started
Starting thread sub-proccesses...
sub-proccesses started!
point
point 0
accepted
Recieved
added to list
created user
Accepted connection from 127.0.0.160338 username: test1
point
point 0
accepted
Recieved
added to list
created user
Accepted connection from 127.0.0.160340 username: test2
point
point 1
Recieved Message from test2 : message$hello of type message
point
point 1
Recieved Message from test1 : message$ of type message
point
point 1
Recieved Message from test1 : message$hello of type message
client1:
Username: test1
Me(test1) >
sent b'8 ' : b'message$'
Me(test1) > hello
sent b'13 ' : b'message$hello'
client2:
Username: test2
Me(test2) > hello
sent b'13 ' : b'message$hello'
as you can see the messages are sent and recieved by the server but not displayed (I'm not stupid I hit enter a few times).
Your server code is confusing and probably not doing what you thought. First you create a thread to accept connections giving it acceptUsers as its thread function (call this thread A). However, that function will only run once in that thread, then it will exit after it has visited all of the read_sockets (because there's no while True loop).
Second, your other thread (B) is running in manageDataSending -- also executing select, but when a client connects, it's calling acceptUsers. That means on the first connection to your server, there's a "race" between the two threads. It's questionable what will happen next because both are now destined to execute the acceptUsers code at more or less the same time, so the exact order of operations in the two threads is now indeterminate.
It's possible that thread A could run first, handle the server_socket (accept the connection and do the receive) and quit, before thread B enters the select call in acceptUsers. That would leave thread B waiting in the select (in acceptUsers) until the next time a client connects or sends data.
On the other hand, it's possible that thread A and thread B both get past the select in acceptUsers and both execute the accept call. Then the accept will succeed in one, and block in the other, waiting for a subsequent incoming connection. In either case, your thread B eventually ends up blocked in a place in your code that you didn't expect it to be.
Bottom line: there's no obvious reason for you to have the two separate threads, both doing a select call. It will be much simpler and easier to understand what is going on if create only one thread, and have it execute your socket select in one place, have that place handle the socket notifications for both incoming connections and incoming client data.
One other thing to note: you don't really need to handle the exception_sockets separately. If one of your clients goes away, its entry in the read_sockets list will be signaled as "ready-to-read" and when you attempt to read it, you will get an end-of-file indication (i.e. zero-length buffer returned).
I am currently trying to make a Python program where two computers connected to different servers can send messages to each other.
Below is my code:
Server.py:
import sys
import socket
def main():
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.bind(('', 11111))
s.listen(1)
while True:
(conn, addr) = s.accept()
while True:
received = conn.recv(1024)
if received == '':
break
else:
print(received.decode())
send_msg = input().replace('b', '').encode()
if send_msg == ' ':
break
else:
conn.sendall(send_msg)
print("sent")
if __name__ == '__main__':
main()
Client.py:
import sys
import socket
import select
def main():
if len(sys.argv) is not 3:
print("usage: %s [ip adress][port] " % sys.argv[0] )
return(-1)
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.connect((sys.argv[1], int(sys.argv[2])))
while True:
s_msg = input().replace('b', '').encode('utf-8')
if s_msg == '':
break
else:
s.sendall(s_msg)
r_msg = s.recv(1024)
if r_msg == '':
break
else:
print(r_msg.decode())
if __name__ == '__main__':
main()
When I executed the code by sending a message from server.py, the message was not sent to the client until I try to send a message from the client to the server. Here is the example of the result:
Does anyone know what's wrong with my code?
Please let me know if any extra information is needed. Thank you in advance.
I was able to implement the simple P2P chat program using the code below:
server.py
import sys
import socket
import threading
#TODO: exit program when client ends the connection
def connect(conn):
while True:
received = conn.recv(1024)
if received ==' ':
pass
else:
print(received.decode())
def sendMsg(conn):
while True:
send_msg = input().replace('b', '').encode()
if send_msg == ' ':
pass
else:
conn.sendall(send_msg)
if __name__ == '__main__':
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.bind(('', 11111))
s.listen()
(conn, addr) = s.accept()
thread1 = threading.Thread(target = connect, args = ([conn]))
thread2 = threading.Thread(target = sendMsg, args = ([conn]))
thread1.start()
thread2.start()
thread1.join()
thread2.join()
client.py
import sys
import socket
import threading
#TODO:end connection with 'exit'
def connect(s):
while True:
r_msg = s.recv(1024)
if not r_msg:
break
if r_msg == '':
pass
else:
print(r_msg.decode())
def receive(s):
while True:
s_msg = input().replace('b', '').encode('utf-8')
if s_msg == '':
pass
if s_msg.decode() == 'exit':
print("wan exit")
break
else:
s.sendall(s_msg)
if __name__ == '__main__':
if len(sys.argv) is not 3:
print("usage: %s [ip adress][port] " % sys.argv[0] )
sys.exit(0)
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.connect((sys.argv[1], int(sys.argv[2])))
thread1 = threading.Thread(target = connect, args = ([s]))
thread2 = threading.Thread(target = receive, args = ([s]))
thread1.start()
thread2.start()
thread1.join()
thread2.join()
In your code, input() is a blocking function, meaning the execution stop until you press Enter.
So you need to send a message to execute the receive part.
To deal with is issue, you can use non-blocking input functions as mentioned in this question.
Or maybe using multi-threaded code: one thread read the use input and send, the other thread receive and print.
Edit:
The server can't send messages if he receive nothing due to this line:
received = conn.recv(1024)
if the client is still connected and send nothing, the server will wait on this line. So you need to receive one message on server side to access the send part.
You can try to use non-blocking sockets to prevent this behavior.
I'm trying to make a Host/ClientTCP Chat Console.
I have a little problem with my python script, actually, i can't assign my listenS socket when i'm in server mode.
I want to use the same functions (Send and Recieve) for the Client and Host but i don't know if it is possible, i'm not very good in python so if you guys can help me to solve this
Thanks
Code :
import socket
from threading import Thread
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
Port = 1604
listenS = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
def start():
IP_address = "192.168.1.49"
isserver = input("Server ? (Y/N) : ")
if isserver.lower() == "n":
rIP = input("IP Adress : ")
# str(rIP)
rPort = input("Port : ")
if rPort != "":
Port = int(rPort)
else:
Port = 1604
if isserver.lower() == "n":
listenS.connect((IP_address, Port))
elif isserver.lower() == "y":
Listen()
def Listen():
try:
server.bind(('', Port))
server.listen(10)
listenS, addr = server.accept() # ---- Here is my problem ! -----
except:
print("Connection Timed Out !")
class Send(Thread):
def __init__(self):
Thread.__init__(self)
print("Sender Started...")
def run(self):
while True:
message = input() + "\n"
listenS.send(message.encode('utf-8'))
class Recieve(Thread):
def __init__(self):
Thread.__init__(self)
print("Listener Started...")
def run(self):
while True:
print(listenS)
message = listenS.recv(2048)
print(str(message).replace(r"\n","").replace(r"b'","").replace(r"'",""))
start()
send = Send()
recieve = Recieve()
send.start()
recieve.start()