Group chat in Python - python

I am writing a group chat code, which is consisted of server.py and client.py. Basically, any message sent by any client is visible to all clients. It runs normal until one of the clients close the connection. When a client closes the connection, server cannot accept new clients. I get the following error: Connected by ('127.0.0.1', 11142)
Exception: [WinError 10038] An operation was attempted on something that is not
a socket
Code for server.py
from socket import *
import select
import sys
import threading
QUIT = False
class Server:
def __init__(self):
self.host = "127.0.0.1"
self.port = 9999
self.threads = []
self.backlog = 10
def run(self):
all_good = False
while not all_good:
try:
all_good = False
self.sock = socket(AF_INET, SOCK_STREAM)
self.sock.bind((self.host, self.port))
self.sock.listen(self.backlog)
all_good= True
print("Server started at "+self.host+":"+str(self.port))
break
except Exception as err:
print('Socket connection error... ')
self.sock.close()
try:
while not QUIT:
try:
client, addr = self.sock.accept()
except socket.timeout:
continue
new_thread = Client(client)
print("Connected by ", addr)
msg = ("Connected by %s at %s" %(new_thread.name, addr)).encode()
for each in self.threads:
each.client.send(msg)
self.threads.append(new_thread)
new_thread.start()
for thread in self.threads:
if not thread.isAlive():
self.threads.remove(thread)
thread.join()
except KeyboardInterrupt:
print("Terminating by Ctrl+C")
except Exception as err:
print("Exception: %s\nClosing" %err)
for thread in self.threads:
thread.join()
self.sock.close()
class Client(threading.Thread):
def __init__(self, client):
threading.Thread.__init__(self)
self.client = client
def run(self):
global QUIT
done = False
while not done:
try:
cmd = self.client.recv(1024).decode()
if cmd.startswith("/name"):
self.client.send("Enter your username: ".encode())
old_name = self.name
self.name = self.client.recv(1024).decode()
msg = "%s has changed his username to %s" %(old_name, self.name)
for each in server.threads:
if each != self and each.isAlive():
each.client.send(msg.encode())
self.client.send(("Your username has been changed to %s" %self.name).encode())
elif cmd == "/quit":
self.client.send("exit".encode())
server.threads.remove(self)
for each in server.threads:
each.client.send(("%s Disconnected" %self.name).encode())
QUIT = True
done = True
else:
msg = "%s===>%s" %(self.name, cmd)
for each in server.threads:
if each != self:
each.client.send(msg.encode())
except Exception as e:
print("Connection lost", e)
self.client.close()
done = True
continue
self.client.close()
return
if __name__ == "__main__":
server = Server()
server.run()
print("Terminated")
Code for client.py
from socket import *
import sys
import threading
host = "127.0.0.1"
port = 9999
class listen(threading.Thread):
def __init__(self, client):
threading.Thread.__init__(self)
self.client = client
self.setDaemon(True)
def run(self):
while(True):
data = self.client.recv(1024)
if data.decode() == "exit":
sys.exit(1)
print(data.decode())
if __name__ == "__main__":
try:
clientSocket = socket(AF_INET, SOCK_STREAM)
clientSocket.connect((host, port))
print("Welcome to chat!")
print("Type your message and press 'Enter' to send.")
print("Send '/name' command to change your username.")
print("Send '/quit' command to quit.")
except error as e:
if clientSocket:
clientSocket.close()
print("Could not open a socket: "+ str(e))
sys.exit(1)
l = listen(clientSocket)
l.start()
message = input()
while message!="/quit":
#sys.stdout.flush()
clientSocket.send(message.encode())
#data = self.clientSocket.recv(1024)
#data = data.decode()
#print("Recieved: "+str(data))
message= input()
clientSocket.close()

Related

How can I have client socket continue listening for server after a server is closed in python?

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

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

socket chat room - python

I'm running windows 10, python 2.7 using pycharm
I'm doing as an exercise a socket chat room, and I've stumbled on a certain problem:
While running the client and server socket from multiple cmd windows,
When I exit one cmd window abruptly, the server is supposed to forward a message to the remaining client - informing them that a client left (including the client's nick)
For some reason it proves to be a problem, the server seems to retain that client in the client list, raising an error as if I sent him that message (which obviously is problematic, because he is no longer there).
When I tried to fix that - changing the loop to not send the message to that specific client (by saving his socket object) -it doesn't send any message.
As if it doesn't recognize the other clients.
My code:
Server:
import socket
import select
import datetime
server_socket=socket.socket()
server_socket.bind(('127.0.0.1',23))
server_socket.listen(5)
open_client_sockets = []
messages_to_send = []
chat_clients={}
def send_waiting_messages(wlist):
for message in messages_to_send:
(sender,msg)=message
if(msg=='\r'):
continue
elif(msg=='quit'):
pass
else:
nick_len=int(msg[:2])
nick=msg[2:2+nick_len]
chat=msg[2+nick_len:]
chat_clients[sender]=nick
for client in wlist:
if(msg=='quit'):
client.send(('{:02d}:{:02d} {} has left the chat!'.format(datetime.datetime.now().hour,datetime.datetime.now().minute,sender)))
else:
if(client is sender):
client.send('NL')
else:
client.send('{:02d}:{:02d} {}: {}'.format(datetime.datetime.now().hour,datetime.datetime.now().minute,nick,chat))
messages_to_send.remove(message)
while True:
rlist,wlist,xlist=select.select([server_socket] + open_client_sockets,open_client_sockets,[])
for current_socket in rlist:
print wlist
if(current_socket is server_socket):
(new_socket,address)=server_socket.accept()
open_client_sockets.append(new_socket)
chat_clients[new_socket]=''
else:
try:
msg=current_socket.recv(1024)
except socket.error as e:
if e.errno==10054:
msg=''
else:
raise
if(msg=='' or msg=='quit'):
if(msg=='quit'):
messages_to_send.append((chat_clients[current_socket], 'quit'))
current_socket.send('quit')
open_client_sockets.remove(current_socket)
del chat_clients[current_socket]
else:
print '{:02d}:{:02d} {} has left the chat!'.format(datetime.datetime.now().hour,
datetime.datetime.now().minute, chat_clients[current_socket])
messages_to_send.append((current_socket, 'quit'))
else:
print msg
messages_to_send.append((current_socket,msg))
send_waiting_messages(wlist)
Client:
import socket
import select
import datetime
server_socket=socket.socket()
server_socket.bind(('127.0.0.1',23))
server_socket.listen(5)
open_client_sockets = []
messages_to_send = []
chat_clients={}
def send_waiting_messages(wlist):
for message in messages_to_send:
(sender,msg)=message
if(msg=='\r'):
continue
elif(msg=='quit'):
pass
else:
nick_len=int(msg[:2])
nick=msg[2:2+nick_len]
chat=msg[2+nick_len:]
chat_clients[sender]=nick
for client in wlist:
if(msg=='quit'):
client.send(('{:02d}:{:02d} {} has left the chat!'.format(datetime.datetime.now().hour,datetime.datetime.now().minute,sender)))
else:
if(client is sender):
client.send('NL')
else:
client.send('{:02d}:{:02d} {}: {}'.format(datetime.datetime.now().hour,datetime.datetime.now().minute,nick,chat))
messages_to_send.remove(message)
while True:
rlist,wlist,xlist=select.select([server_socket] + open_client_sockets,open_client_sockets,[])
for current_socket in rlist:
print wlist
if(current_socket is server_socket):
(new_socket,address)=server_socket.accept()
open_client_sockets.append(new_socket)
chat_clients[new_socket]=''
else:
try:
msg=current_socket.recv(1024)
except socket.error as e:
if e.errno==10054:
msg=''
else:
raise
if(msg=='' or msg=='quit'):
if(msg=='quit'):
messages_to_send.append((chat_clients[current_socket], 'quit'))
current_socket.send('quit')
open_client_sockets.remove(current_socket)
del chat_clients[current_socket]
else:
print '{:02d}:{:02d} {} has left the chat!'.format(datetime.datetime.now().hour,
datetime.datetime.now().minute, chat_clients[current_socket])
messages_to_send.append((current_socket, 'quit'))
else:
print msg
messages_to_send.append((current_socket,msg))
send_waiting_messages(wlist)
Help would be much appreciated!
I have also been trying trying to make a chat room and I have been successful. You might want to look at my code to find the solution.
Server
import threading
from queue import Queue
import socket
host = ''
port = 5000
client_list = []
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((host, port))
s.listen(1000)
def conn():
while True:
(host, port) = s.accept()
f = len(client_list)
client_list.append(host)
print(client_list)
p1 = threading.Thread(target=clientam, args=str(f))
p2 = threading.Thread(target=threader)
p2.start()
p1.start()
p1.join()
p2.join()
def clientam(client):
size = 3000
client = int(client)
c = client_list[client]
print(c)
c.send("Welcome to the chatroom".encode())
while True:
try:
data = c.recv(size).decode()
if data == "exit":
for l in client_list:
if l == c:
pass
else:
l.send("The other person has left the chatroom".encode())
client_list[client] = ''
print(client_list)
c.close()
break
else:
for l in client_list:
if l == c:
pass
else:
l.send(data.encode())
except Exception:
for l in client_list:
if l == c:
continue
else:
try:
l.send("The other person has left the chatroom".encode())
except Exception:
pass
break
try:
c.close()
except Exception:
break
def threader():
t = threading.Thread(target=conn)
t.start()
t.join()
threader()
client
import socket
import threading
import time
import pickle
host = '127.0.0.1'
port = 5000
s = socket.socket()
d = 0
print_lock = threading.Lock()
def conn():
global d
global s
try:
if d == 1:
s = socket.socket()
s.connect((host, port))
d = 0
elif d == 0:
s.connect((host, port))
except Exception:
conn()
def reciever():
global d
global g
g = False
li = [128, 3, 88, 0, 113, 46]
size = 3000
while True:
try:
data = s.recv(size).decode()
data = str(data)
with open('Data.txt', 'a') as f:
f.write(data)
if str(data) == 'The other person has left the chatroom':
with print_lock:
print(data)
elif str(data) == "Welcome to the chatroom":
g = True
with print_lock:
print(str(data))
else:
try:
int(data)
continue
except Exception:
with print_lock:
print("Other Person:> " + str(data))
except Exception as e:
with print_lock:
print("You have been disconnected")
d = 1
s.close()
with print_lock:
print('Trying to connect to server')
conn()
def sender():
global d
global g
while True:
if g == True:
while True:
with print_lock:
i = input('You:> ')
if i == 'exit':
try:
s.send(i.encode())
with print_lock:
print("You have been disconnected")
d = 1
except Exception:
with print_lock:
print('You have been disconnected')
d = 1
elif i == "connect":
if d == 0:
with print_lock:
print("Server already connected")
elif d == 1:
with print_lock:
print('Server connecting')
conn()
else:
try:
if d == 0:
s.send(i.encode())
elif d == 1:
with print_lock:
print('Server is disconnected')
except Exception:
with print_lock:
print('Server is disconnected')
def threader():
p1 = threading.Thread(target = reciever)
p1.start()
p2 = threading.Thread(target = sender)
p2.start()
p1.join()
p2.join()
conn()
threader()

Automatically reconnect client socket on server shutdown?

So, I've had a problem this morning that I couldn't find any posted answers yet. Basically, I wanted to have my Python client to reconnect everytime the server shuts down.
My previous code looks like this
def fire(self):
self.s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.s.settimeout(5)
while (self.connected):
# create the transmission_struct class
msg = transmission_struct(self.stream, self.CHUNK, self.rate)
# create the Filestream packet
packet1 = msg.structure_msg_fls()
# create the decision packet
packet2 = msg.structure_msg_stm()
# send, first the decision packet
self.s.sendall(packet2)
# send the whole packet one by one
for i in range(len(packet1)):
self.s.sendall(packet1[i])
# timestamp for debugging purposes
ts = time.time()
timestamp = datetime.datetime.fromtimestamp(ts).strftime('%Y-%m-%d %H:%M:%S')
print(timestamp + " size of data sent is " + str(len(packet1)) +
" size of decision is " + str(len(packet2)))
I implemented the reconnection logic through try and exception blocks and a recursion in the attempt function.
def fire(self):
self.s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.s.settimeout(5)
self.attempt_connect()
while (self.connected):
# create the transmission_struct class
msg = transmission_struct(self.stream, self.CHUNK, self.rate)
# create the Filestream packet
packet1 = msg.structure_msg_fls()
# create the decision packet
packet2 = msg.structure_msg_stm()
try:
# send, first the decision packet
self.s.sendall(packet2)
# send the whole packet one by one
for i in range(len(packet1)):
self.s.sendall(packet1[i])
# timestamp for debugging purposes
ts = time.time()
timestamp = datetime.datetime.fromtimestamp(ts).strftime('%Y-%m-%d %H:%M:%S')
print(timestamp + " size of data sent is " + str(len(packet1)) + " size of decision is " + str(len(packet2)))
except socket.error as e:
print(e.errno)
self.connected = False
print("Attempting to connect...")
self.close_open_new_socket()
time.sleep(1)
continue
except IOError as e:
print(e.errno)
self.close_open_new_socket()
continue
except KeyboardInterrupt:
self.s.close()
finally:
self.attempt_connect()
def attempt_connect(self):
while (self.connected is False):
try:
self.result = self.s.connect((self.host, self.port))
if (self.result == None):
self.connected = True
else:
self.connected = False
except socket.error as e:
errorcode = e[0]
print(errorcode)
if (errorcode == 56):
self.connected = True
time.sleep(1)
continue
elif(errorcode == 22):
self.connected = False
print("attempting to reconnect...")
# adding recursive call to attempt connect
# after socket is broken
self.close_open_new_socket()
time.sleep(1)
continue
elif (errorcode == 61):
self.connected = False
print("Server not up, waiting for server and reconnecting...")
time.sleep(1)
continue
elif (errorcode == 32):
self.connected = False
print("Server down, attempting to reconnect...")
time.sleep(1)
continue
else:
self.connected = False
time.sleep(1)
continue
def close_open_new_socket(self):
self.s.close()
self.s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.s.settimeout(5)
self.attempt_connect()

Categories

Resources