I've been looking around all day, but I haven't been able to fix the problem I've got with my chat client here.
Here's the issue: I recently decided to change the client so that it would allow the user to input any message they wanted without having to wait for a reply first (blocking or something stops my program until a reply is in)
I decided to use the select.select module to do so, but after writing a couple different versions of my client today trying to get it to work, I keep getting stuck at this one point.
Whenever I enter a message, the loop gets stuck somewhere, (probably at .recv data)
how can I fix this? Nothing I try gets it to go by that.
Edit: To be more clear, when I run, I get to the point where I input the message, hit enter and then nothing happens at all. It just stays running like that.
from socket import *
import select
import sys #because why not?
print("New Chat Client Using Select Module")
HOST = input("Host: ")
PORT = int(input("Port: "))
s = socket(AF_INET,SOCK_STREAM)
print("Trying to connect....")
s.connect((HOST,PORT))
s.setblocking(0)
# Not including setblocking(0) because select handles that.
print("You just connected to",HOST,)
# Lets now try to handle the client a different way!
while True:
Incoming_data = [s]
Exportable_data = []
Exceptions = []
User_input = input("Your message: ")
rlist,wlist,xlist = select.select(Incoming_data,Exportable_data,Exceptions)
if User_input == True:
Exportable_data += [User_input]
for i in rlist:
data = i.recv(1024)
if data == "":
continue
for i in wlist:
if Exportable_data is True:
i.send(Exportable_data)
continue
Is there any way I can override the blocking (that I presume is the problem) when it's set to receive data? Won't s.setblocking(0) make it so it won't block(?) (With or without it still gets stuck)
Thanks for taking a look
I think you should have separate thread or process which will interact with your socket and another thread, which will accept user input and print chat messages. Interaction between the threads you can do using 2 queues: for incoming and outgoing messages.
Have a look at threading and queue modules.
Related
i am quite new to Python, i am trying to create a gui interface to a server and a client that shows the user data and web data.
when i try to create a threathing.Thread to the s.recv function it doesnt stop the server from freezing...
how can i make the server not freeze when he arrives to the s.recv function?
Thanks in advance!
some of my code:
def receive_message():
"""
"""
global G
s =socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.bind((UDP_IP, UDP_PORT))
G.insert(INSERT, "Welcome to the 'Sniffer' server")
ROOT.update() # updates the Tkinter form
#time.sleep(1)
G.insert(INSERT, "\n")
while 1:
data = threading.Thread(target=s.recv(BUFFER_SIZE)).start()
if ("ip" not in format(data.decode()) and format(data.decode()).count('$') == 3):
sql = format(data.decode())
sqllist = list(sql.split("$"))
sqllist = [sqllist]
sql_connection(sqllist)
elif ("ip" not in format(data.decode()) and format(data.decode()).count('$') == 4):
sql = format(data.decode())
sqllist = list(sql.split("$"))
sqllist = [sqllist]
sql_connection2(sqllist)
if ("$" not in format(data.decode())):
G.insert(INSERT, format(data.decode()))
ROOT.update() # updates the Tkinter form
time.sleep(1)
G.insert(INSERT, "\n")
if not data:
break
You're almost there. When you call the s.recv function you actually execute it in the main thread and pass the return data to the thread. So, basically, you don't execute the s.recv function in a separate thread and this is what causes the server to freeze.
Instead, call the thread like this with arguments.
data = threading.Thread(target=s.recv, args=(BUFFER_SIZE,)).start()
There was no need to create a thread here because your code (attempts to) consume the data right away. Your problem is that you call s.recv() try to use its return value to make a thread. Its just a byte string, not a function, so nothing happens. But there are other problems. The Thread.start method returns None , not the returned data. In fact, Thread will discard the target's return value. You need a different way to save the data. That is moderately difficult and not needed here.
The solution for this code is to skip the thread entirely. There is one more subtle bug here. You want to specifically define what the encoding for your protol is. If you just use the default, that can be different on different machines. And just decode once, no need to wear out your cpu.
while 1:
data = s.recv(BUFFER_SIZE).decode('utf-8')
...etc...
I have created a chat bot for Twitch IRC, I can connect and create commands etc etc, however I cannot use keyboard-interrupt in the command prompt. I suspect it is because it's stuck in this infinite loop, and I don't know how to fix this? I am new to programming btw!
Here is the code I have in my Run.py, openSocket() is defined in another file, basically connection to the server. s = socket.socket.
First part in the while-loop basically just reads the server messages, I think it's pretty straight forward for you guys!
s = openSocket()
joinRoom(s)
readbuffer = ""
while True:
readbuffer = readbuffer + s.recv(1024).decode("utf-8")
temp = str.split(readbuffer, "\n")
readbuffer = temp.pop()
for line in temp:
if "PING" in line:
s.send("PONG :tmi.twitch.tv\r\n".encode("utf-8"))
print("---SENT PONG---")
printMessage(getUser, getMessage, line)
message = getMessage(line)
for key in commands:
command = key
if command in message:
sendMessage(s, commands[command])
((Edit: I also have this problem where the connection to the server seems to time out for whatever reason. I managed to get it keep connection with ping/pong for about 40-45min, but then it disconnected again.
EDIT:
Sorry the original post was super messy. I have created this pastebin with the least amount of code I could use to recreate the problem.
If the IRC chat is inactive it will disconnect, and I can't get it to send 2 pings in a row without any messages in between, not sure if that's because it disconnects before the 2nd ping or because of the 2nd ping.
On at least one occasion it has disconnected even before I got the first ping from the server.
Pastebin: pastebin.com/sXUW50sS
Part of code that you posted doesn't have much to do with problem you described.
This is a guess (although an educated one). In you socket connection you are probably using try: except: and using Pokemon approach (gotta catch 'em all)
Thing here would be to find a line where you are doing something like this:
except:
pass
and change it to:
except (KeyboardInterrupt, SystemExit):
raise
except:
pass
Obviously I'm not trying to say here that your porgram should catch all exceptions and just pass like if nothing happened. Main point is that you are probably already doing that (for i-have-no-idea-why reasons) and you should have special treatment for system errors.
OK, so i have a pretty simple turn based application (game).
Each user sends a request on the server and then wait for response. The important is, that only ONE user makes the request on the server (send his actions) and all other users are just waiting, if the server sends them some data, so they must always check (in loop) if something is coming from server.
I´m using the built-in module of python "socket" and the way i manage the clients is this: For every user i create one thread, in which runs infinite loop, until the application ends, which checks for request (if it is the turn of the user) or checks if it got anything to sent to the other users. Now let´s move to Clients. Every client has again one thread with infinite loop, waiting for data from server.
The problem is that the GUI is made in PyQt4.4, where i cant get into the loop of the PyQt itself (although i have seen, that it is possible to do this with twisted, but then i would have to rewrite my code) so i have to use the thread, that means i can use classic python threading library or QThread, but QThread sadly doesn´t have any Events, which are pretty crucial because i want always wait after the message from the server for the response of the program, so i can send response to the server again. On the other hand, I am not sure, if i can use Thread from threading to emit signals. So which one is the right one to go?
Btw: is actually ok, to run the infinite client and server side loop? Because in every tutorial I have seen, the client close the connection right after he gets his answer.
EDIT:
here´s some of the code
Server side loop for connection with client:
while self.running:
if self.is_on_turn == p and self.reply is not None:
cmd = conn.recv(1024)
if cmd == '':
conn.close()
return
cmd = eval(cmd)
if self.is_on_turn != p: # User is not on turn
print "END"
conn.sendall("END")
else:
self.queue.put(cmd)
ev.wait() # Here works another program with the message and decide what to do next
ev.clear() #
conn.sendall(str(self.message))
if self.reply:
ev.wait() #
ev.clear() #
if self.reply:
r = conn.recv(1024)
if r == '':
conn.close()
return
self.queue.put(eval(r))
ev.wait() #
ev.clear() #
conn.sendall(str(self.message))
conn.close()
Client side loop:
def main_loop(self, pipe, conn, e, o): #e is event, o is bool (whether the client has to answer back to the server)
is_on_turn = conn.recv(4096)
pipe.send((is_on_turn))
while True:
if is_on_turn == h or o.value and o.value is not None:
conn.send(str(pipe.recv()))
pipe.send(eval(conn.recv(4096)))
e.wait()
e.clear()
The pipe is there, because I made it in multiprocessing at first, there should the emit signal for the PyQt instead, but as I said, I am not sure which approach to use
So the result is, that I have just used QTcpServer and QTcpSocket as sugessted by ekhumoro, which resulted in much cleaner code and easier management :)
I have a problem while trying to build the client side of a chat. I just in the begining, this is my code:
import socket
my_socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
my_socket.connect(("10.10.10.69",1234))
while True:
message=raw_input("your message: ")
if(message=="quit"):
my_socket.close()
break
my_socket.send(message)
data=my_socket.recv(1024)
print "message from server:" , data
The problem is the raw_input. When a user sends a message the other users are stacked on the raw_input so only when they sends a message too they get the new messages.
How can I fix it (without using threads)?
As I commented, use select.select if your chat client is running in Unix.
For example:
import socket
import sys
import select
my_socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
my_socket.connect(("10.10.10.69",1234))
sys.stdout.write('your message: ')
sys.stdout.flush()
while True:
r, w, x = select.select([sys.stdin, my_socket], [], [])
if not r:
continue
if r[0] is sys.stdin:
message = raw_input()
if message == "quit":
my_socket.close()
break
my_socket.send(message)
sys.stdout.write('your message: ')
sys.stdout.flush()
else:
data = my_socket.recv(1024)
print "message from server:" , data
raw_input holds up the thread it's in, so you can't retrieve messages in the same thread while waiting for it. Thus, I recommend using 2 threads, one which receives new messages (say every ten seconds) and one which sends messages (using code similar to the existing code).
If you're not committed to raw_input and are really against threads, you might want to look into the select module.
There are suggestions to use select() for stdin, but seems they aren't fixing the main problem. With select, imagine the local user is entering a line, and in a middle of this process your program outputs another user message, and, the editing of local input will be screwed. Either you don't allow to show new messages during entering the current one (why?) or screen is messed up. If you do this in a terminal, you should go using curses or some more powerful tool; with curses you can at least split input and output into different screen areas. Of course, a graphics library (like wxWidgets) is even more generally suitable for a user interface, if it's allowed in your case.
Okay, so in some experimentation with sockets and networking, I've set up a very basic chat client/server that runs on Unix flawlessly. Now I'm hitting some errors in the translation to win32. In preface, I understand that select.select() on Windows won't accept socket objects and have (I think) compensated coherently by not passing it the socket object, but the socket number. However, the script still hangs on the select.select() function and I have no idea why. The script only hangs until the server receives a message, after which it allows the client to send messages, however the client can't receive messages from the server, no matter what. I'm trying to troubleshoot these two bugs as best as I can, but my research has turned up dry. Here's the problem code, thanks in advance.
while True:
socket_list.append(s)
read_sockets, write_sockets, error_sockets = select.select(socket_list, [], [], 20)
if not (read_sockets or write_sockets or error_sockets):
if afk == False:
s.send('[Status]: '+str(_user)+' has gone afk.\n')
sys.stdout.write('\n[+]: You have gone afk.\n')
afk = True
prompt()
for sock in read_sockets:
print ('Starting for sock in read_sockets') #DEBUG#
if sock == s:
print ('Getting here.') #DEBUG#
data = sock.recv(4096)
if not data:
sys.stdout.write('[!]: Disconnected from chat server by server.\n'+W)
choice = raw_input('[*]: Press Enter to continue.')
_logic()
else:
sys.stdout.write(data)
else:
# Rest of the Program (Runs correctly) #
It sounds like you forgot to set the sockets non-blocking. Like pretty much all status reporting functions, select does not make future guarantees. You also need to handle the case where read returns a "would block" indication. You can't rely on select to predict the results of future read operations.