Hi This is my first post here. I am making a chatroom in Python using sockets and I have written the code for the server and client side. I am successful in establishing a connection between the server and the clients but I can't send any messages. The client provides a password and username through terminal and the server check if the password is correct and only then the client can send messages. I have not yet implemented the password check yet but the messages are still not being sent. I have made sure I am encoding and decoding correctly. I have also implemented threading to allow multiple users. Here is the server side code:
import socket
import threading
import sys
#TODO: Implement all code for your server here
#usernames = []
def broadcast(message):
for client in clients:
client.send(message)
def handle_client(client_socket, client_address):
try:
password = client_socket.recv(1024).decode()
username = client_socket.recv(1024).decode()
print("user: " + username)
clients.append(client_socket)
while True:
message = username + " joined the chatroom"
print(message)
broadcast(message.encode())
message = client_socket.recv(1024).decode()
if (message != ":Exit"):
print(f"{username}: {message}")
broadcast(message.encode())
else:
print(f"{username} left the chatroom")
clients.remove(client_socket)
client_socket.close()
message = username + " left the chatroom"
broadcast(message.encode())
break
except:
client_socket.close()
def receive():
while True:
client_socket, client_address = server.accept()
print(client_socket)
client_thread = threading.Thread(target=handle_client, args=(client_socket, client_address))
client_thread.start()
# Use sys.stdout.flush() after print statemtents
if __name__ == "__main__":
HOST = '127.0.0.1'
#PORT = int(sys.argv[1])
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind((HOST, 10001))
server.listen(5)
clients = []
print("server is listening")
receive()
Here is the client side:
import socket
import threading
import sys
#TODO: Implement a client that connects to your server to chat with other clients here
HOST = '127.0.0.1'
#PORT = int(sys.argv[1])
client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client_socket.connect((HOST, 10001))
username = sys.argv[1]
password = sys.argv[2]
client_socket.send(password.encode())
client_socket.send(username.encode())
reply = client_socket.recv(1024).decode()
print(reply)
def receive():
while True:
try:
message = client_socket.recv(1024).decode()
if message:
print(message)
except:
continue
def write():
while True:
message = input()
if message == ":Exit":
client_socket.send(message.encode())
client_socket.close()
break
else:
client_socket.send(message.encode())
receive_thread = threading.Thread(target=receive)
receive_thread.start()
write_thread = threading.Thread(target=write)
write_thread.start()
# Use sys.stdout.flush() after print statemtents
if __name__ == "__main__":
pass
I have tried asking my TAs but they were of no help :(.
It looks like you are taking the second and third arguments instead of first and second. Thus if you do not pass 3 arguments with the third being the password then the client will not have a password to send.
Related
I have written a simple server and client py using UDP. The base is working, however I want that every time a user (client) joins, he would receive a chatlog of everything that has been said.
This is my code until now:
Server:
import socket
import threading
import queue
import pickle
messages = queue.Queue()
clients = []
# AF_INET used for IPv4
# SOCK_DGRAM used for UDP protocol
ip = "localhost"
port = 5555
chatlog=[]
UDPServerSocket = socket.socket(family=socket.AF_INET, type=socket.SOCK_DGRAM)
# binding IP and port
UDPServerSocket.bind((ip, port))
def receive():
while True:
try:
message, addr = UDPServerSocket.recvfrom(1024)
messages.put((message, addr))
chatlog.append((message,addr))
except:
pass
def broadcast():
while True:
while not messages.empty():
message, addr = messages.get()
print(message.decode())
if addr not in clients:
clients.append(addr)
for client in clients:
try:
if message.decode().startswith("SIGNUP_TAG:"):
name = message.decode()[message.decode().index(":") + 1:]
UDPServerSocket.sendto(f"{name} joined!".encode(), client)
if len(chatlog)>0:
sending= pickle.dumps(chatlog)
UDPServerSocket.sendto(sending, client)
else:
pass
else:
UDPServerSocket.sendto(message, client)
except:
clients.remove(client)
t1 = threading.Thread(target=receive)
t2 = threading.Thread(target=broadcast)
t1.start()
t2.start()
And the client
import socket
import threading
import random
client= socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
client.bind(("localhost", random.randint(7000, 8000))) # random port for every client
name = "Henk" #test name
def receive():
while True:
try:
message, _ = client.recvfrom(1024)
print(message.decode())
except:
pass
t= threading.Thread(target= receive)
t.start()
#this gives the server the name of the people who have entered the server
client.sendto(f"SIGNUP_TAG: {name}".encode(), ("localhost", 5555))
while True:
message= input("")
if message=="!q":
exit()
else:
client.sendto(f'[{name}]: {message}'.encode(), ("localhost",5555))
So I am actually a bit stuck on how I will approach this. Shall create a text file where every time that a message is written it gets written on the file as well? Or shall I create some kind of string list/database where every message is stored :/
I wanted to create a server-client chatbox room in python, where multiple clients could send messages in the chat box.
This is the server code
import threading
import socket
#setting up the local host and the local port
host = '127.0.0.1'
port = 9879
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind((host, port)) #hosting the server to the host
server.listen() #server listen to incoming connection
#list for client and their nicknames
clients = []
nicknames = []
#broadcast method to send message to all the clients connected to the server
def broadcast(message):
for client in clients:
client.send(message)
def handle (client):
while True:
try:
message = client.recv(1024)
broadcast(message)
except: #if the connection is lost, discard the client
index = clients.index(client)
clients.remove(client)
client.close()
nickname = nicknames[index]
broadcast(f'{nickname} already left the chat!'.encode('ascii'))
nicknames.remove(nickname)
break
#function to receive connection
def receive():
while True:
client, address = server.accept()
print(f"Conncected with {str(address)}")
client.send('NICKNAME'.encode('ascii'))
nickname = client.recv(1024).decode('ascii')
nicknames.append(nickname)
clients.append(client)
print(f'The nickname of the client is {nickname}')
broadcast(f'{nickname} joined the chat!'.encode('ascii'))
client.send('Connected to the server!'.encode('ascii'))
#making thread for every client
thread = threading.Thread(target = handle, args = (client,))
thread.start()
print("Server is waiting for client...")
and this is the client code
import socket
import threading
#nickname prompt
nickname = input("Input your nickname: ")
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
#binding the client to the port
client.connect(('127.0.0.1', 9879))
def receive():
while True:
try:
message = client.recv(1024).decode('ascii')
if message == 'NICKNAME':
client.send(nickname.encode('ascii'))
else:
print(message)
except:
print("An error occurred!")
client.close()
break
def write():
while True:
message = f'{nickname}: {input("")}'
client.send(message.encode('ascii'))
#making the thread
receive_thread = threading.Thread(target = receive)
receive_thread.start()
write_thread = threading.Thread(target = write)
write_thread.start()
However, whenever i inputted the nickname in the command prompt there was an error
Traceback (most recent call last):
File "C:\Users\march\Documents\Programming\Pyhton\client.py", line 8, in <module>
client.connect(('127.0.0.1', 9879))
ConnectionRefusedError: [WinError 10061] No connection could be made because the target machine actively refused it
I wonder what's the problem because the port for both server and client are the same and the port is available.
On your server code you're missing a call to the receive function that runs the while loop and puts the server on accept for connections.
The code becomes
import threading
import socket
#setting up the local host and the local port
host = '127.0.0.1'
port = 9879
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind((host, port)) #hosting the server to the host
server.listen() #server listen to incoming connection
#list for client and their nicknames
clients = []
nicknames = []
#broadcast method to send message to all the clients connected to the server
def broadcast(message):
for client in clients:
client.send(message)
def handle (client):
while True:
try:
message = client.recv(1024)
broadcast(message)
except: #if the connection is lost, discard the client
index = clients.index(client)
clients.remove(client)
client.close()
nickname = nicknames[index]
broadcast(f'{nickname} already left the chat!'.encode('ascii'))
nicknames.remove(nickname)
break
#function to receive connection
def receive():
while True:
client, address = server.accept()
print(f"Conncected with {str(address)}")
client.send('NICKNAME'.encode('ascii'))
nickname = client.recv(1024).decode('ascii')
nicknames.append(nickname)
clients.append(client)
print(f'The nickname of the client is {nickname}')
broadcast(f'{nickname} joined the chat!'.encode('ascii'))
client.send('Connected to the server!'.encode('ascii'))
#making thread for every client
thread = threading.Thread(target = handle, args = (client,))
thread.start()
print("Server is waiting for client...")
receive() # runs the function that accepts for incoming connections
The client code should run the write() function on the main thread and not on another one, because it requires input from the stdin. You can change your code as follows in order to run the receiving routine on another thread and your "writing" function on the main one.
import socket
import threading
#nickname prompt
nickname = input("Input your nickname: ")
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
#binding the client to the port
client.connect(('127.0.0.1', 9879))
def receive():
while True:
try:
message = client.recv(1024).decode('ascii')
if message == 'NICKNAME':
client.send(nickname.encode('ascii'))
else:
print(message)
except:
print("An error occurred!")
client.close()
break
def write():
while True:
message = f'{nickname}: {input("")}'
client.send(message.encode('ascii'))
#making the thread
receive_thread = threading.Thread(target = receive)
receive_thread.start()
# on the main thread
write()
The cause of the Connection refused error was due to the fact that the server code immediately exited since the receive function was never actually called.
i have this server code:
import socket
import threading
host = "host"
port = 55555
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client_list = []
color_list = []
server.bind((host, port))
server.listen()
def broadcast(message):
for client in client_list:
client.send(message.encode("ascii"))
def accept_conn():
while True:
conn, addr = server.accept()
if conn not in client_list:
client_list.append(conn)
conn.send("color".encode("ascii"))
color = conn.recv(1024).decode("ascii")
color_list.append(color)
message = conn.recv(1024).decode("ascii")
color_1 = color_list[client_list.index(conn)]
broadcast("[SERVER]recieved")
print(f"SERVER {host} RUNNING")
thread = threading.Thread(target=accept_conn)
thread.start()
and this client code:
import socket
import threading
host = "host"
port = 55555
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))
color = input("enter the color: ")
def write():
while True:
message = input("")
client.send(message.encode("ascii"))
def recieve():
check = 1
while True:
message = client.recv(1024).decode("ascii")
if message == "color" and check == 1:
client.send(color.encode("ascii"))
check = 0
else:
print(message)
thread = threading.Thread(target=write)
thread2 = threading.Thread(target=recieve)
thread.start()
thread2.start()
now what this is supposed to do is recieve messages from the client and in response send to all connected clients the message recieved from the client.
right now im checking if it sends it to all clients by sending "recieved" from the server the client after every time the server recieves a message from the client.
the output looks like this:
enter the color: red
hi
[SERVER]recieved
im
the problem with this is that when i write the first message the server responds with "recieved" but after that it dosent which seems to me like its only running once.
would like some help on this.
I am trying to create a simple chat program using Python and Socket. The server handles the connection between two clients. Whenever I run the program, for one of the clients, every message after the first one does not send. The message does not even reach the server.
This is on Windows, Python3. I've integrated threading so messages can be sent and received at the same time; however, the problem persists.
Server.py
conns = [] # list that stores both connections
def accept(sk):
while True:
conn, addr = sk.accept()
conns.append(conn)
print(addr, "has connected")
t = threading.Thread(target=accept, args=(sk,))
t.start() #start accept thread
def send(conn):
while True:
message = conn.recv(2048)
print(message)
for conn in conns:
conn.send(message) #sends message to every connection
print("Sent message")
t = threading.Thread(target=send, args=(conn,))
t.start() #start threading for send
Client.py
def recvMessages(s):
while True:
message = s.recv(2048)
print(message)
message = message.decode()
messages.append(message)
os.system("cls")
for message in messages:
print(message)
def sendMessage(s):
while True:
message = input()
message = message.encode()
s.send(message)
s = socket.socket()
host = socket.gethostname()
port = 8080
s.connect((host, port))
messages = []
print("Connected")
connected = True
threading.Thread(target=sendMessage, args=(s,)).start()
threading.Thread(target=recvMessages, args=(s,)).start()
All the messages should be sent from both clients, but one client can never send multiple messages, the other works fine.
Your server code is missing it's socket, and accept is not being run in your example, you also have invalid indentation as James pointed out, next time provide a minimal reproducible example.
I also cleaned up your files a bit, as you followed some bad practice, specifically with broadcasting the messages to all clients "def send" which actually receives, avoid confusing naming :)
in your server code you also sent only to one connection (which in your example doesn't exist) which it should be running the receive and send each time a new message is received
server.py
import socket
import threading
conns = [] # list that stores both connections
def accept(sk):
while True:
conn, addr = sk.accept()
conns.append(conn)
print(addr, "has connected")
# receive from new client
receive_t = threading.Thread(target=receive, args=(conn,))
receive_t.start() # start threading for send
def send(s, msg):
# change message ..
s.send(msg)
def broadcast(msg):
for conn in conns:
send(conn, msg)
def receive(conn):
try:
while True:
message = conn.recv(2048)
if not message: # detects if socket is dead, by testing message
print("client sent Nothing, removing")
conns.remove(conn)
break
broadcast(message) # send to all clients
except ConnectionResetError as e:
print('Could not send must be disconnected ')
conns.remove(conn) # remove dead socket
# added missing socket
sock = socket.socket()
sock.bind(('127.0.0.1', 8080))
sock.listen(1) # needs to bind and listen
t = threading.Thread(target=accept, args=(sock,))
t.start() # start accept thread
client.py
import os
import socket
import threading
messages = []
def recvMessages(s):
while True:
message = s.recv(2048)
message = message.decode()
print('new message= ', message)
messages.append(message)
os.system("cls")
for message in messages:
print(message)
def send_message(s):
while True:
message = input()
message = message.encode()
s.send(message)
s = socket.socket()
host = '127.0.0.1'
port = 8080
s.connect((host, port))
print("Connected")
connected = True
# added missing receive
receive = threading.Thread(target=recvMessages, args=(s,)) # missed receive thread in example
receive.start()
send_message(s)
I'm trying to create a simple python chat interface however when two clients are connected to the server, the first clients console prints blank spaces as quick as possible and causes a max recursion depth error while the second client still works fine. The server code only sends data when its not blank so i'm not sure why it does this.
Server code:
import socket
from threading import Thread
from socketserver import ThreadingMixIn
class ClientThread(Thread):
def __init__(self,ip,port):
Thread.__init__(self)
self.ip = ip
self.port = port
print("[+] New thread started for "+ip+": "+str(port))
def run(self):
while True:
data = conn.recv(1024).decode()
if not data: break
if data == "/exit":
print("Connection for "+ip+" closed.")
data = "Connection closed."
conn.send(data.encode())
break
else:
print("received data: ", data)
if data != " ":
conn.send(data.encode())
print("connection "+ip+" force closed.")
TCP_IP = socket.gethostname()
TCP_PORT = 994
BUFFER_SIZE = 1024
tcpsock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
tcpsock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
tcpsock.bind((TCP_IP, TCP_PORT))
threads = []
while True:
tcpsock.listen(4)
(conn, (ip,port)) = tcpsock.accept()
newthread = ClientThread(ip,port)
newthread.start()
threads.append(newthread)
for t in threads:
t.join()
Client code:
import socket
import threading
from threading import Thread
TCP_IP = socket.gethostname()
TCP_PORT = 994
BUFFER_SIZE = 1024
name = str(input("Input username: "))
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((TCP_IP, TCP_PORT))
def recv():
while True:
data = s.recv(BUFFER_SIZE).decode()
if not data: break
print(data)
recv()
def send():
message = str(input())
if message != "/exit":
message = name + ": " + message
s.send(message.encode())
send()
if __name__ == "__main__":
Thread(target = recv).start()
Thread(target = send).start()
The error is at line 19 in the client code (where its receiving and printing any data sent by the server)
Any help would be greatly appreciated.
The most probable reason is the recursion in your send and receive routines, I changed them to be loops instead.
def recv():
while True:
data = s.recv(BUFFER_SIZE).decode()
if not data: break
print(data)
def send():
while True:
message = str(input())
if message != "/exit":
message = name + ": " + message
s.send(message.encode())
A solution to shutting down these threads is given here: Is there any way to kill a Thread in Python?
But it is not necessary to run send and receive in single threads in this scenario in the clients.
EDIT:
I read again carefully your code. In the client you start the send and receive method as threads. The send thread does not get any input for its message string in the thread and because you loop it, it sends empty messages to the server or (in my case) exits with an error.