Receiving messages off the same socket in different threads - Python - python

I'm looking to build a chat room in python at the moment and am struggling with direct messages as I'm using client.recv(2048) function in both my thread listening for messages from the server and trying to use client.recv() in my main function to receive a list of active users on the server. It seems the program will work sometimes and others will shift to the clientreceive function.
Thread started
# Starts thread for client receive
receive_thread = threading.Thread(target=client_receive)
receive_thread.start()
receive block
def client_receive():
while True:
try:
message = client.recv(2048).decode()
print(message)
except:
client.close()
break
main method (DM)
if msg_type == "DM":
# Sends C DM message to server
dm_msg = "C DM"
client.send(dm_msg.encode())
# Receives list of online users from server in client_receive
users = client.recv(2048).decode()
print(users)
# Client inputs username and message to server
target = input("Select user: ")
chat = input("> ")
chat_msg = "D " + target + "|||||" + chat
I attempted using locks in my main method, which did not seem to work. I expected my method to stay with my socket when I used lock.acquire(), however it still broke to the clientreceive function
Thanks

Related

How can I let my code send messages simultaneously?

I'm trying to do UDP socket programming in Python, and I want both the client and the server to be able to send messages without the need to wait for the other party to send a message first.
Here is my server code:
import socket
sock=socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
sock.bind(('127.0.0.1',12345))
while True:
data,addr=sock.recvfrom(4096) #byte size
print("Client says: ")
print(str(data))
message = bytes(input("Enter message here: ").encode('utf_8'))
sock.sendto(message,addr)
and here is my client code:
import socket
client_socket=socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
while True:
msg=input("Enter your message here: ")
client_socket.sendto(msg.encode('utf_8'),('127.0.0.1',12345))
data,addr=client_socket.recvfrom(4096) #byte size
print("Server says")
print(data)
What should I edit in my code to make this work?
You need to create two functions to handle listening and sending.
Then you start them as threads so they run in parallel.
Each function has its own loop. The receive thread waits for messages and the send thread waits for user input
def client_receive():
while True:
data,addr=client_socket.recvfrom(4096) #byte size
print("Server says")
print(data)
def send_chat_message():
while True:
msg=input("Enter your message here: ")
client_socket.sendto(msg.encode('utf_8'),('127.0.0.1',12345))
receive_thread = threading.Thread(target=client_receive)
receive_thread.start()
send_thread = threading.Thread(target=send_chat_message)
send_thread.start()
The above code will not really work at this point. But there are good tutorials out there. Search for python socket chat threaded tutorial
Often they are not based on a server handling inputs, but multiple clients connecting to a server. If you understand the concept, you'll have no problem adjusting the server to allow inputs there aswell.

Using multi threading in python to create a basic chatroom

I've been given a summer assignment to create a chat room on python using sockets, using a main socket as the server that connects to all the other "client" sockets, each time a client sends a message to the server, the server sends it to everyone else but the client that sent it. The catch is that I need to make it so you can write messages and receive them at the same time, which is something I have no idea how to do so I took my friend's advice and tried to do it using multi-threading.
This is what I have right now, it's supposed to get more complicated but this is the very basic part:
client
import socket
import thread
import time
def receive_messages(recieve_socket):
while True:
print recieve_socket.recv(1024)
def send_messages(send_socket):
while True:
data = raw_input()
send_socket.send(data)
def main():
my_socket = socket.socket()
my_socket.connect(('127.0.0.1', 8822))
thread.start_new_thread(send_messages, (my_socket, ))
thread.start_new_thread(receive_messages, (my_socket, ))
time.sleep(1) #this delay lets the threads kick in, otherwise the thread count is zero and it crashes
while thread._count() > 1:
pass
if __name__ == '__main__':
main()
server
import socket
import select
waiting_messages = []
users = []
def add_new_user(user_socket):
new_socket, address = user_socket.accept()
users.append(new_socket)
print "A new user has joined"
def remove_user(user_socket):
users.remove(user_socket)
print "A user has left"
def send_waiting_messages(wlist):
for message in waiting_messages:
receiving_socket, data = message
if receiving_socket in wlist:
receiving_socket.send(data)
waiting_messages.remove(message)
def spread_messages(message, sending_user):
receiving_list = users
receiving_list.remove(sending_user)
for user in receiving_list:
waiting_messages.append((user, message))
print "A user has sent a message"
def main():
server_socket = socket.socket()
server_socket.bind(('0.0.0.0', 8822))
server_socket.listen(5)
# users = []
# messages_to_send = []
while True:
rlist, wlist, xlist = select.select([server_socket] + users, users, [])
for current_socket in rlist:
if current_socket is server_socket:
add_new_user(server_socket)
else:
data = current_socket.recv(1024)
if data == "quit":
remove_user(current_socket)
else:
spread_messages(data, current_socket)
send_waiting_messages(wlist)
if __name__ == '__main__':
main()
The issue is when I try to run it, the first message works fine, but after the second message the server just sends a lot of blank messages and stops sending the messages I send it.
I'd really appreciate help in the matter.
Thanks for the help guys, in the end I asked a friend of mine and he told me to use threading instead of select on the server and it worked great! I'll post the code later if anyone's interested.

Python 2.7: Multiprocessing not doing anything

I'm trying to make a client in python. I'm trying to use multiprocessing to receive and send objects.
I use this to send messages (Entering nothing is supposed to display the messages sent by other clients):
if __name__ == "__main__":
while True:
wait = 'yes'
message = raw_input('Enter message into chat (enter nothing to refresh chat): ')
if message == '':
wait = 'no'
continue
sock.sendall(message)
And I use this to receive messages:
def listen():
global wait
while True:
data = sock.recv(255)
while True:
if wait == 'yes':
continue
print data
break
And I use this to get listen() working:
q = multiprocessing.Process(target=listen)
q.start()
Am I missing anything or am I doing something wrong. Please help!
At the very least, you need two ends of a connection to be able to communicate. It looks like you have one socket and it's not clear it's connected to anything (you omitted the socket setup code, so hard to say).
Try using socketpair() to get two sockets that are connected:
import socket
client, server = socket.socketpair()
Then use client in the main process and server in the "listening" process (or vice versa, it doesn't really matter). The two sockets are connected and sending using one lets the other receive the data.

Consumer Producer gets stuck on multi-client server

I have an issue. My producer-consumer on this chat server I've built is being stuck. Here's what it does: it gives the clients turns to send their messages, and when that random client(inside race of my computer) sends his message, all the messages clients tried to send before are being sent. I cannot find the issue, maybe someone can spot it?
def run(self):
global condition
global messages
is_running = 1
while is_running:
print "waiting to receive from: " + self.usersock.getpname()
inp = self.sock.recv(8192)
condition.acquire()
parts = inp.split(':-:321')
if parts[0] == "4":
while not noMessagesToSend(messages):
condition.wait()
mes = message.message(str(datetime.datetime.now().time())[:8], self.usersock.id, parts[3],parts[4])
if not mes.getgroup() in messages.keys():
messages.update({mes.getgroup():[]})
messages[mes.getgroup()].append(mes)
condition.notifyAll()
condition.release()
else:
print parts

Python: How to send message to client from server at any time?

I'm building a discussion board style server/client application were the client connects to the server, is able to post messages, read messages, and quit.
See client code below:
import socket
target_host = "0.0.0.0"
target_port = 9996
#create socket object
client = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
#connect the client
client.connect((target_host,target_port))
#receiving user name prompt
print client.recv(1024)
usrname = str(raw_input())
#send username
client.send(usrname)
#check if username was unique
while client.recv(1024) == "NU": #should exit once "ACK" received
print client.recv(1024) #print username promt again
usrname = str(raw_input()) #client enters in another username
client.send(usrname)
#receive user joined message/welcome message/help menu
response = client.recv(1024)
print response
print client.recv(1024)
#loops until client disconnects
while True:
request = str(raw_input("\n\nWhat would you like to do? "))
client.send(request)
if request == "-h":
help_menu = client.recv(1024)
print help_menu
elif request == "-p":
#get subject
subject_request = client.recv(1024)
print subject_request
subject = str(raw_input())
client.send(subject)
#get contents of post
contents_request = client.recv(1024)
print contents_request
contents = str(raw_input())
client.send(contents)
#get post notification
message_post = client.recv(1024)
print message_post
elif request == "-r":
#get id value of post
id_request = client.recv(1024)
print id_request
message_id = str(raw_input())
client.send(message_id)
#get contents of post
message_contents = client.recv(2048)
print message_contents
elif request == "-q":
break
else:
print client.recv(1024)
When a client joins though, I wish to notify all other clients that are connected that a new client has joined, but each client may be at a different point in the code (some may be in the middle of a post, sitting idle at the "what would you like to do?" statement, etc).
So how would I set my client code up that it will be able to accept a message from the server the moment another client joins?
There are many ways to do it. Here an overview of how I would.
Are you familiar with "select" operations? They allow you to listen on multiple file descriptors and get notified whenever one becomes active. I would start by using that to both listen for keyboard inputs and server messages.
Then there are 2 things to be done. Branch depending on the active canal. If it's a keyboard input you can relay the command to the server. If it's a server message, you need to branch again on the message type to act accordingly.
Edit: Never assume what the server message is about. Even though you may have just sent a query, the server may be sending data about something else.

Categories