Socket programming with threading - python

This is a generic code that I have written for V2V communication. My intention is that if there are n number of vehicles in the network, they should be be able to send message to other (n-1) vehicles and also receive from them.
import socket
import threading
ports = [30151,30152,30153]
class V2V_comm(threading.Thread):
global ports
def __init__(self,port):
threading.Thread.__init__(self)
self.host = "127.0.0.1"
self.port = port
self.skt = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
self.skt.bind((self.host,self.port))
self.log_info = []
self.open_server = False
print "Starting server with ports: ",self.port
self.skt.settimeout(0.2)
def run(self):
print "I m here"
message = raw_input("Give a message >>")
while message != "Q":
try:
for port in ports:
if self.port != port:
print "Sending present location and message"
self.skt.sendto(message,(self.host,port))
message = raw_input("Give a message >>")
except:
print "Something is going wrong"
def receiving_data(self):
#while True:
try:
print "Ready to receive data"
data,addr = self.skt.recvfrom(1024)
print "The points received are: ", str(data)
print "The points are received at: ", self.port
self.log_info.append(data)
print self.log_info
except:
print "unable to receive"
V1 = V2V_comm(30151)
V2 = V2V_comm(30152)
V3 = V2V_comm(30153)
V1.start()
V2.start()
V3.start()
V1.receiving_data()
V2.receiving_data()
V3.receiving_data()
But it is not working properly. Can some one suggest any changes ?

Related

My global variable is not changing (Python)

I am making an online flag guessing game using sockets.
Server's code below (sorry for pasting the entire code, I've been testing and have literally no idea what the problem could be):
import socket
import threading
import random
from time import sleep
from func import get_flags
flags = get_flags()
flag_names = [i for i in flags]
current_flag = " "
show_answer = False
errorCounter = 0
HEADER = 64
PORT = 5050
SERVER = socket.gethostbyname(socket.gethostname())
ADDR = (SERVER, PORT)
FORMAT = 'utf-8'
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind(ADDR)
players = []
num_of_players = int(input("Number of players: "))
def handle_client(conn, addr):
global show_answer, current_flag
print(f"[NEW CONNECTION] {addr} connected.")
connected = True
player = ()
while connected:
print(current_flag)
msg_length = conn.recv(HEADER).decode(FORMAT)
if msg_length:
msg_length = int(msg_length)
msg = conn.recv(msg_length).decode(FORMAT)
#print(f"[{addr}] {msg}")
msg = msg.lower()
msg = msg.split(" ")
try:
if msg[0] == "!set_username" and len(msg) > 1:
player = (msg[1], addr)
players.append(player)
elif msg[0] == "!get_flags":
conn.send(str(flags).encode(FORMAT))
elif msg[0] == "!ready":
conn.send(str(len(players) >= num_of_players).encode(FORMAT))
elif msg[0] == "!get_current_flag":
conn.send(current_flag.encode(FORMAT))
elif msg[0] == "!show_answer":
conn.send(str(show_answer).encode(FORMAT))
except Exception:
print("asd")
#conn.send("Msg received".encode(FORMAT))
players.remove(player)
conn.close()
def start():
global show_answer, current_flag
server.listen()
print(f"[LISTENING] Server is listening on {SERVER}:{PORT}")
while len(players) < num_of_players:
conn, addr = server.accept()
thread = threading.Thread(target=handle_client, args=(conn, addr))
thread.start()
print("\nThe game has started.\n")
while True:
sleep(3)
show_answer = False
current_flag = random.choice(flag_names)
sleep(10)
show_answer = True
if __name__ == "__main__":
print("[STARTING] server is starting...")
start()
My problem is:
When I call the start() function, and the lobby fills up, the "game clock" starts, which determines how much time the players have to guess the flag, and the time in which they can see the correct answer. When I change these variables (show_answer and current_flag), they change, but not in in handle_client(). Why is that?
The client is able to connect just fine, but can't see the updated variables.
I am using Python 3.9.5 if that helps.

How can I have client socket continue listening for server in python?

I have the following code.
This is for the client.py:
import random
import socket
import threading
import os
def access():
HOST = '127.0.0.1'
PORT = 22262
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((HOST, PORT))
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 for server.py
import socket
HOST = '127.0.0.1'
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'))
For this to work properly I need to have the server continually running to get a response from the client. If I run the client before the server I get presented with the following error:
ConnectionRefusedError: [WinError 10061] No connection could be made because the target machine actively refused it
Can I modify it to have client.py wait for the server to answer in order to connect to it? Basically I want to remove the time out error
connect() will throw an exception if it can't connect. Catch it and retry:
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
while True:
try:
client.connect((HOST, PORT))
break
except Exception as e:
print("retrying: ", e);
time.sleep(1)
print("connected")

Not recieving data python socktes

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).

How to send broadcast data to all clients in a muti-threaded socket server?

I am currently in the process of creating a mutli-threaded chat room in python, however I am having trouble broadcasting data to all of the clients.
I am hoping to create a system where one clients sends data to the server, and the server broadcasts the data to the other clients.
What I am hoping to achieve:
https://i.stack.imgur.com/uvG54.png
Server:
import socket
import threading
import sys
import time
USERNAME = str(input("Enter your username: "))
MAX_CLIENTS = int(input("How many clients: "))
BUFF_SIZE = 1024
HOST = ''
PORT = 9999
lock = threading.Lock()
class Server:
def __init__(self):
self.clients = [] #list of clients
self.messages = [] #messages
self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.host = HOST
self.port = PORT
self.sock.bind((self.host, self.port))
threading.Thread(self.listener()).start()
def conn_handler(self, conn):
while True:
with lock:
self.data = conn.recv(BUFF_SIZE).decode("utf-8")
print(data)
self.messages.append(self.data)
conn.sendall(self.data.encode("utf-8")) #error occurs here, cannot send data to all clients
time.sleep(.01)
def listener(self):
for x in range(MAX_CLIENTS):
self.sock.listen(1)
conn, addr = self.sock.accept()
print("{} has connected!".format(addr))
self.clients.append(addr)
threading.Thread(target=self.clientthread, args=(conn,)).start()
threading.Thread(target=self.conn_handler, args=(conn,)).start()
server = Server()
Client:
import socket
import time
import threading
BUFF_SIZE = 1024
HOST = str(input("Enter Server IP: "))
PORT = 9999
print("Connecting to {} at port {}.\n".format(HOST, PORT))
lock = threading.Lock()
USERNAME = str(input("Enter username: "))
print("""\nClientCommands:
-----------------
\t1. #SHOWINFO --> Shows server info.
\t2. #ARCIVECHAT --> Saves chat into text file.
""")
class Client:
def __init__(self):
self.messages = []
self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.host = HOST
self.port = PORT
self.sock.connect((self.host, self.port))
print("\nConnected to server!\n")
print("Please press <enter> to refresh chat in order to send message.")
_recver = threading.Thread(target=self.recver)
_recver.start()
def recver(self):
while True:
with lock:
data = self.sock.recv(BUFF_SIZE).decode("utf-8")
print(data)
self.messages.append(data)
data = self.sock.recv(BUFF_SIZE).decode("utf-8")
print(data)
self.messages.append(data)
time.sleep(.01)
def get_send_msg(self):
self._msg_to_send = str(input("You - "))
self.msg_to_send = "{} - ".format(USERNAME)+self._msg_to_send
self.messages.append(self.msg_to_send)
try:
if self._msg_to_send == "#SHOWINFO":
self.ShowInfo()
elif self._msg_to_send == "#ARCIVECHAT":
self.Arcive_Chat()
else:
self.sock.send(self.msg_to_send.encode("utf-8"))
except Exception as e:
print("An error has occured:")
print(e)
archiveornot = str(input("Would you like to archive the conversation in a text file(Y/N): "))
if archiveornot == "Y":
archive_name = str(input("Enter file name: "))
f = open(archive_name, "w")
for message in self.messages:
f.write("\n")
f.write(message)
f.close()
print("Exiting program...")
quit()
else:
print("Exiting program...")
time.sleep(2)
quit()
time.sleep(.01)
def ShowInfo(self):
print("Server Info:")
print("--------")
print("Host: {} | Port: {}".format(self.host, self.port))
print("--------")
def Arcive_Chat(self):
archive_name = str(input("Enter file name: "))
f = open(archive_name, "w")
if len(self.messages) >= 1:
for message in self.messages:
f.write("\n")
f.write(message)
f.close()
else:
print("[!]Error, No messages were sent[!]")
client = Client()
def main():
while True:
client.get_send_msg()
if __name__ == "__main__":
main()

Python - Server / Client TCP Chat Console

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()

Categories

Resources