Me and a friend of mine are doing a chat room with python, basically he's doing the server part and I'm doing the GUI and Client part, I don't know why the app just stop to work without any reason showing the Windows message "Python is not responding"
This is the Server code:
#max name length=9999
#max message types=100
#max groupmsg recipients = 9999
#max msg length =8191 characters
import socket
import threading
import sys
def find_users(): #Continously Searches For New Clients
while True:
user, client_address = connector.accept()
threading.Thread(target=new_user, args=(user,)).start()
def new_user(identity):
while True:
print(identity)
name_length=identity.recv(4).decode() #max user name length =9999
username=identity.recv(int(name_length)).decode()
password=identity.recv(8192).decode()
if username in user_details and password == user_details[username]: #correct credentials
client_details[usename]=identity
identity.sendall('y'.encode())
break
elif username in user_details: #incorrect password
print('Please Re-enter The User Details')
identity.sendall('n'.encode())
else: #New user
user_details[username]=password
client_details[username]=identity
identity.sendall('y'.encode())
break
pubmsg(username+' has connected')
active_users.append(username)
identity.settimeout(5)
try:
while True: #waits for incoming messages
msgtype= identity.recv(2).decode() #identifies message type, max types =100
if msgtype == '01': #public message
communication = identity.recv(8192).decode()
pubmsg(str(username + ' >>> ' + communication))
elif msgtype == '02': #private message
direction=[]
recipno=identitiy.recv(4) #defines max group msg recipients
for y in range(0,recipno): #repeats once per recipient
recip_name_length=identity.recv(4).decode()
recip_name=identity.recv(recip_name_length).decode()
direction.append(recip_name)
gmsg=identity.recv(8192).decode()
groupmsg(gmsg,direction)
except Exception as e:
active_users.remove(username)
del client_details[username]
pubmsg(username+' disconnected')
identity.close()
sys.exit()
def pubmsg(Group_message):
print(Group_message)
for person in client_details:
client_details[person].sendall(Group_message.encode())
def groupmsg(Direct_message,recipients,sender):
gmsg=sender +' (to '
for person in recipients: #repeats once per recipient
gmsg+=person+', '
gmsg=gmsg.rstrip(', ')
gmsg=gmsg + ')' + ' >>> ' + Direct_message
for person in recipients:
client_details[person].sendall(gmsg)
user_details={}
client_details={}
active_users=[]
connector = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
print ('Launching Server')
connector.bind(('localhost', 5000)) #Links socket to server address
connector.listen(10)
threading.Thread(target=find_users).start()
For the client and the GUI I'm putting here only the function called by the button "Connect" of the GUI (the ones that are creating problems), the GUI uses the QT Libraries
This is the code called by the button:
def client_connect(self):
ip_address = str(self.ipText.toPlainText())
port = int(self.portText.toPlainText())
nickname = self.nameText.toPlainText()
password = 'hello'
connect = threading.Thread(target = connection_thread, args = (ip_address, port, nickname, password))
connect.start()
This is the thread function:
def connection_thread(address, port, nickname, password):
nickname = nickname.encode()
password = password.encode()
while True:
try:
c = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
c.connect((address, port))
c.sendall('{0:0=4d}'.format(len(nickname)).encode())
c.sendall(nickname)
c.sendall(password)
answr = c.recv(2).decode()
if answr == 'y':
msg_box("CONNECTED", "Now you are connected to the server.")
while True:
time.sleep(2)
c.sendall('03'.encode())
message_received =c.recv(8192).decode()
self.chatList.addItem(message_received)
except Exception as e:
msg_box("CONNECTION FAILED", "Connection to server failed, try again.")
break
From the server code the connection of my client arrives but, the client stop working without showing the msg_box that says that we are connected.
When you say connect.join() you wait for the thread connect to finish, but it is in an infinite loop, so it is not done until the connection closes.
Related
I've been trying to create a chat room using python and the socket module, but I have run into a bug which I don't know how to fix.
At the moment, when I send a message through one of the clients, the message will be outputted again in the terminal of the person who sent it. E.g. column 3, rows 1 & 3 (column 3 is Jim's).
This is the code I wrote for the clients (Re. receiving/sending data):
# Receive data from server
def receive_data():
while True:
try:
mes = client.recv(1024).decode('ascii')
# If the message is 'name', send name to server
if mes == 'name':
client.send(name.encode('ascii'))
# If the message comes from the same person, don't show it
elif name == mes[0:(len(name)+1)]:
pass
# Otherwise it will print the message
else:
print(mes)
except:
# Close the connection
print(f"{colours.Colours.red}An error occurred!{colours.Colours.end}")
client.close()
break
# Send data to server
def send_data():
while True:
message_to_send = input("You : ")
mes = f"\n{name} : {message_to_send}"
client.send(mes.encode('ascii'))
I wrote this for the server. After it was all setup, the receive function was run. By the way, the protocol is TCP.
# Handling clients
def handle_clients(client):
while True:
try:
# Broadcasting messages
mes = client.recv(1024)
broadcast(mes)
except:
# Removing clients
name = clients[client]
broadcast(f"{colours.Colours.red}{name} has left!{colours.Colours.end}".encode('ascii'))
del clients[client]
break
# Recieving data
def recieve():
while True:
# Accept connection
conn, addr = server.accept()
print(f"{colours.Colours.green}Connected with {addr}!{colours.Colours.end}")
# Request & store name
conn.send("NAME".encode('ascii'))
name = conn.recv(1024).decode('ascii')
clients.update({conn : name})
# Start handling thread for client
thread = threading.Thread(target=handle_clients, args=(conn,))
thread.start()
How can I solve this?
Sam
SOLVED
After going over it a bit, I figured out what the problem was. It was more about the server relaying it, instead of the client.
This is my new server code (that I changed):
# If the name of the sender is the same as in the message, return True
def check_name(name, client_name):
client_name = client_name[0]
if name == client_name:
return True
else:
return False
# Send message to all clients
def broadcast(message, ignore=False):
for client, name in clients.items():
if not ignore:
client.send(message.encode('ascii'))
else:
if check_name(ignore, name):
pass
else:
client.send(message.encode('ascii'))
# Handling clients
def handle_clients(client):
while True:
try:
# Decode message
mes = client.recv(1024).decode('ascii')
if not mes:
break
# Get the name of the sender
name = mes.split(" : ")
name = name[0]
name = name.replace('\n', '')
name = name.strip()
mes = mes.replace('\n', '')
# Broadcast
broadcast(mes, ignore=name)
except:
# Removing clients
name = clients[client]
broadcast(f"{colours.Colours.red}{name} has left!{colours.Colours.end}".encode('ascii'))
del clients[client]
break
This is my new client code:
# Recieve data from server
def receive():
while True:
try:
mes = client.recv(1024).decode('ascii')
# If the message is 'NAME', send the name to server
if mes == 'NAME':
client.send(name.encode('ascii'))
# Otherwise it will print the message
else:
print(mes)
except:
# Close the connection
print(f"{colours.Colours.red}An error occurred!{colours.Colours.end}")
client.close()
break
# Send data to server
def send():
while True:
message_to_send = input("You : ")
mes = f"\n{name} : {message_to_send}"
client.send(mes.encode('ascii'))
keep getting a session timeout, can't figure out why, the server should display the message right back. the code is displayed on the bottom, where the first set of code is the client and the second set is server, the first thing you'll see is the output, that is where is shown that there is a session timeout.
Client-Server
All Uppercase
All Lowercase
Initial Caps
Exit
Enter Choice: 1
Enter the sentence: the kid had sicknesss
Session timed out
This is the client:
import socket
from socket import AF_INET, SOCK_DGRAM
import time
# Address of UDP IP
UDP_IP_ADDRESS = '127.0.0.1' #server set as localhost
# UDP port number
UDP_PORT_NO = 9999
# Display the message
# print('Pinging',UDP_IP_ADDRESS,UDP_PORT_NO)
#create the socket
clientSocket = socket.socket(AF_INET,SOCK_DGRAM)
#sets the timeout at 1 sec
clientSocket.settimeout(1)
choice = 1
try:
print("Client-Server")
# Create a while loop to repeat the process continously
while True:
print()
print("1. All Uppercase")
print("2. All Lowercase")
print("3. Initial Caps")
print("4. Exit")
while(True):
choice=input("Enter Choice: ")
if(choice not in ["1","2","3","4"]):
print("Invalid Input!")
else:
break
if choice is "4":
print( 'Thank you!')
break
# Prompt the user to enter the sentence
sentence=input("Enter the sentence: ")
message=choice+"-"+sentence
# Sending sentence and command to the server.
clientSocket.sendto(message.encode('utf-8'),(UDP_IP_ADDRESS, UDP_PORT_NO))
#"Receiving login request from the server"
#print()
updated_sentence, server = clientSocket.recvfrom(4096)
updated_sentence = str(updated_sentence)
updated_sentence = updated_sentence[2:len(updated_sentence)-1]
print("Updated Sentence from the server: "+updated_sentence)
except socket.timeout:
print( 'Session timed out')
Here is the server code:
# The following module to generate randomized lost packets
import random
from socket import *
# Create a UDP socket
# Notice the use of SOCK_DGRAM for UDP packets
serverSocket = socket(AF_INET, SOCK_DGRAM)
# Assign IP address and port number to socket
serverSocket.bind(('', 9999))
print('The server is ready to receive on port: 9999')
# Create a 'while-loop' to run the process continoulsy
while True:
# Receive the client packet along with the address it is coming from
message,address = serverSocket.recvfrom(2048)
message = str(message)
message = message[2:len(message)-1]
command = message[0]
sentence = message[2:]
# Create an if-statement to check the command.
if(command == "1"):
sentence=sentence.upper()
elif(command == "2"):
sentence=sentence.lower()
else:
words=sentence.split()
sentence=""
for word in words:
sentence = sentence + word[0].upper()+word[1:]+" "
# Send the modified sentence to the client.
serverSocket.sendto(sentence.encode('utf-8'), address)
Hello so i have my server with a database (dictironay) and another passworddatabase
import socket
import sys
from _thread import *
host = ""
port = 8000
serversocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
print("Socket Created")
try:
serversocket.bind((host, port))
except socket.error as e:
print(str(e))
sys.exit()
database = {"name1" :{"hair" : "red", "size" : 1.50}}
password_database = {"name1": "1234",
"name2": "4321"}
def client_thread(conn): #threader client
welcome = "Welcome to the server. Type something and hit enter \n"
conn.send(welcome.encode("UTF-8"))
login(conn)
while True: # NOT IMPORTANT KEEP READING
data = conn.recv(24)
reply = data.decode("UTF-8")
if reply == "1":
menu1 = "Menu 1: Buy \n"
conn.send(menu1.encode("UTF-8"))
else:
wrong = "wrong option \n"
conn.send(wrong.encode("UTF-8"))
def login(conn): #MY LOGIC PROBLEM IS HERE
log = "Log in MENU: \n"
logi = log.encode("UTF-8")
conn.send(logi)
us = "Username: \n"
use = us.encode("UTF-8")
conn.send(use)
userr = conn.recv(24)
user = userr.decode("UTF-8")
pa = "Password: \n"
pasw = pa.encode("UTF-8")
conn.send(pasw)
passr = conn.recv(24)
passw = passr.decode("UTF-8")
tries = 0
while tries < 3:
if user in passwordDictionary and passwordDictionary[user] == passw:
print("Logged in")
menu()
else:
print("Wrong Username Or Password \n")
tries += 1
print("You failed the login too many times, blocking you out")
conn.close()
while 1: # NOT IMPORTANT
conn, addr = serversocket.accept()
print("Connected with " + addr[0] + ":" + str(addr[1]))
start_new_thread(client_thread, (conn, ))
serversocket.close()
Whats working:
The server is working fine, i'm having troubles doing the login on the client side.
client.py ==> client DOESNT go into the if data == Log in menu
is there a better way to do this?
#! /usr/bin/python3
import socket
clientsocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
clientsocket.connect(('localhost', 8000))
print("Connected")
datae = clientsocket.recv(24)
data = datae.decode("UTF-8")
clientsocket.send(datae)
while data != "!q":
if data == "Log in MENU: \n":
usere = input()
user = usere.encode("UTF-8")
clientsocket.send(user)
What would be the best way to create an log in interaction with the server?
the server has the usernames and passwords, i need to log in and then i need to edit the database depending on what user was chossen, but i'm having a hard time doing the algorithm
theres problems with the code you provided... however ill assume it actually works for you somehow and rather than copy paste you manually typed it
you are recieveing the first message here
datae = clientsocket.recv(24)
data = datae.decode("UTF-8") # GOT A MESSAGE
You then have the message datae = b'Welcome to the server. '
which does not match "Log in MENU: \n", and data != "!q" so it goes back into your loop and checks if data == "Log in MENU: \n" it doesnt so it repeats ... but you never get the next message instead try something like this second message
data = ""
while data != "!q":
if data == "Log in MENU: \n":
usere = input()
user = usere.encode("UTF-8")
clientsocket.send(user)
data = clientsocket.recv(24).decode("UTF-8") # GET THE NEXT MESSAGE!
but even then you are going to have problems because your server continues to write so you will get something like "Log in MENU: \nUsername" or something .... basically you need to work out a better message passing scheme than recv(24)
To avoid Errors try using a header with something like 64 Bytes wich always is the first message send. This Header is then used to send the actual length of the following message to the server. For example:
def send_response(conn, msg):
message = msg.encode(FORMAT)
send_length = len(str(len(message)).encode(FORMAT))
res_len = bytes(len(message)) + (b' ' * (HEADER - send_length))
print(f"[SENDING MESSAGE] {msg}")
conn.send(res_len)
conn.send(response)
I'm trying to create a simple chat application using sockets (python). Where a client can send a message to server and server simply broadcast the message to all other clients except the one who has sent it.
Client has two threads, which are running forever
send: Send simply sends the cleints message to server.
receive: Receive the message from the server.
Server also has two threads, which are running forever
accept_cleint: To accept the incoming connection from the client.
broadcast_usr: Accepts the message from the client and just broadcast it to all other clients.
But I'm getting erroneous output (Please refer the below image). All threads suppose to be active all the times but Some times client can send message sometimes it can not. Say for example Tracey sends 'hi' 4 times but its not broadcasted, When John says 'bye' 2 times then 1 time its message gets braodcasted. It seems like there is some thread synchronization problem at sever, I'm not sure. Please tell me what's wrong.
Below is the code.
chat_client.py
import socket, threading
def send():
while True:
msg = raw_input('\nMe > ')
cli_sock.send(msg)
def receive():
while True:
sen_name = cli_sock.recv(1024)
data = cli_sock.recv(1024)
print('\n' + str(sen_name) + ' > ' + str(data))
if __name__ == "__main__":
# socket
cli_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# connect
HOST = 'localhost'
PORT = 5023
cli_sock.connect((HOST, PORT))
print('Connected to remote host...')
uname = raw_input('Enter your name to enter the chat > ')
cli_sock.send(uname)
thread_send = threading.Thread(target = send)
thread_send.start()
thread_receive = threading.Thread(target = receive)
thread_receive.start()
chat_server.py
import socket, threading
def accept_client():
while True:
#accept
cli_sock, cli_add = ser_sock.accept()
uname = cli_sock.recv(1024)
CONNECTION_LIST.append((uname, cli_sock))
print('%s is now connected' %uname)
def broadcast_usr():
while True:
for i in range(len(CONNECTION_LIST)):
try:
data = CONNECTION_LIST[i][1].recv(1024)
if data:
b_usr(CONNECTION_LIST[i][1], CONNECTION_LIST[i][0], data)
except Exception as x:
print(x.message)
break
def b_usr(cs_sock, sen_name, msg):
for i in range(len(CONNECTION_LIST)):
if (CONNECTION_LIST[i][1] != cs_sock):
CONNECTION_LIST[i][1].send(sen_name)
CONNECTION_LIST[i][1].send(msg)
if __name__ == "__main__":
CONNECTION_LIST = []
# socket
ser_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# bind
HOST = 'localhost'
PORT = 5023
ser_sock.bind((HOST, PORT))
# listen
ser_sock.listen(1)
print('Chat server started on port : ' + str(PORT))
thread_ac = threading.Thread(target = accept_client)
thread_ac.start()
thread_bs = threading.Thread(target = broadcast_usr)
thread_bs.start()
Ok I lied in my comment earlier, sorry. The issue is actually in the broadcast_usr() function on the server. It is blocking in the recv() method and preventing all but the currently selected user from talking at a single time as it progresses through the for loop. To fix this, I changed the server.py program to spawn a new broadcast_usr thread for each client connection that it accepts. I hope this helps.
import socket, threading
def accept_client():
while True:
#accept
cli_sock, cli_add = ser_sock.accept()
uname = cli_sock.recv(1024)
CONNECTION_LIST.append((uname, cli_sock))
print('%s is now connected' %uname)
thread_client = threading.Thread(target = broadcast_usr, args=[uname, cli_sock])
thread_client.start()
def broadcast_usr(uname, cli_sock):
while True:
try:
data = cli_sock.recv(1024)
if data:
print "{0} spoke".format(uname)
b_usr(cli_sock, uname, data)
except Exception as x:
print(x.message)
break
def b_usr(cs_sock, sen_name, msg):
for client in CONNECTION_LIST:
if client[1] != cs_sock:
client[1].send(sen_name)
client[1].send(msg)
if __name__ == "__main__":
CONNECTION_LIST = []
# socket
ser_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# bind
HOST = 'localhost'
PORT = 5023
ser_sock.bind((HOST, PORT))
# listen
ser_sock.listen(1)
print('Chat server started on port : ' + str(PORT))
thread_ac = threading.Thread(target = accept_client)
thread_ac.start()
#thread_bs = threading.Thread(target = broadcast_usr)
#thread_bs.start()
I tried to get around the bug you said #Atinesh. The client will be asked a username once and this 'uname' will be included in the data to be sent. See what I did to the 'send' function.
For easier visualization, I added a '\t' to all received messages.
import socket, threading
def send(uname):
while True:
msg = raw_input('\nMe > ')
data = uname + '>' + msg
cli_sock.send(data)
def receive():
while True:
data = cli_sock.recv(1024)
print('\t'+ str(data))
if __name__ == "__main__":
# socket
cli_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# connect
HOST = 'localhost'
PORT = 5023
uname = raw_input('Enter your name to enter the chat > ')
cli_sock.connect((HOST, PORT))
print('Connected to remote host...')
thread_send = threading.Thread(target = send,args=[uname])
thread_send.start()
thread_receive = threading.Thread(target = receive)
thread_receive.start()
You also have to modify your server code accordingly.
server.py
import socket, threading
def accept_client():
while True:
#accept
cli_sock, cli_add = ser_sock.accept()
CONNECTION_LIST.append(cli_sock)
thread_client = threading.Thread(target = broadcast_usr, args=[cli_sock])
thread_client.start()
def broadcast_usr(cli_sock):
while True:
try:
data = cli_sock.recv(1024)
if data:
b_usr(cli_sock, data)
except Exception as x:
print(x.message)
break
def b_usr(cs_sock, msg):
for client in CONNECTION_LIST:
if client != cs_sock:
client.send(msg)
if __name__ == "__main__":
CONNECTION_LIST = []
# socket
ser_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# bind
HOST = 'localhost'
PORT = 5023
ser_sock.bind((HOST, PORT))
# listen
ser_sock.listen(1)
print('Chat server started on port : ' + str(PORT))
thread_ac = threading.Thread(target = accept_client)
thread_ac.start()
The things that changed in the server side are: the user who connected and the user who spoke is not seen anymore. I don't know if it would mean that much if your purpose is to connect clients. Maybe if you want to strictly monitor clients via the server, there could be another way.
so right now in order to receive your message you need to receive one
my teachers instructions are (in the main)"Modify the loop so that it only listens for keyboard input and then sends it to the server."
I did the rest but don't understand this, ... help?
import socket
import select
import sys
import threading
'''
Purpose: Driver
parameters: none
returns: none
'''
def main():
host = 'localhost'
port = 5000
size = 1024
#open a socket to the client.
try:
clientSock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
clientSock.connect((host,port))
#exit on error
except socket.error, (value,message):
if clientSock :
clientSock.close()
print "Could not make connection: " + message
sys.exit(1)
thread1 = ClientThread()
thread1.start()
while True:
#wait for keyboard input
line = raw_input()
#send the input to the server unless its only a newline
if line != "\n":
clientSock.send(line)
#wait to get something from the server and print it
data = clientSock.recv(size)
print data
class ClientThread(threading.Thread):
'''
Purpose: the constructor
parameters: the already created and connected client socket
returns: none
'''
def __init__(self, clientSocket):
super(ClientThread, self).__init__()
self.clientSocket = clientSocket
self.stopped = False
def run(self):
while not self.stopped:
self.data = self.clientSocket.recv(1024)
print self.data
main()
I assume your purpose is to create a program that starts two threads, one (client thread) receives keyboard input and sends to the other (server thread), the server thread prints out everything it received.
Based on my assumption, you first need to start a ServerThread listen to a port (it's not like what your 'ClientThread' did). Here's an example:
import socket
import threading
def main():
host = 'localhost'
port = 5000
size = 1024
thread1 = ServerThread(host, port, size)
thread1.start()
#open a socket for client
try:
clientSock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
clientSock.connect((host,port))
except socket.error, (value,message):
if clientSock:
clientSock.close()
print "Could not connect to server: " + message
sys.exit(1)
while True:
#wait for keyboard input
line = raw_input()
#send the input to the server unless its only a newline
if line != "\n":
clientSock.send(line)
# Is server supposed to send back any response?
#data = clientSock.recv(size)
#print data
if line == "Quit":
clientSock.close()
break
class ServerThread(threading.Thread):
def __init__(self, host, port, size):
super(ServerThread, self).__init__()
self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.sock.bind((host, port))
self.sock.listen(1)
self.data_size = size
self.stopped = False
def run(self):
conn, addr = self.sock.accept()
print 'Connected by', addr
while not self.stopped:
data = conn.recv(self.data_size)
if data == 'Quit':
print 'Client close the connection'
self.stopped = True
else:
print 'Server received data:', data
# Is server supposed to send back any response?
#conn.sendall('Server received data: ' + data)
conn.close()
if __name__ == '__main__':
main()
And these are the output:
Connected by ('127.0.0.1', 41153)
abc
Server received data: abc
def
Server received data: def
Quit
Client close the connection
You may check here for more details about Python socket: https://docs.python.org/2/library/socket.html?#example