Python chat clients not updating - python-3.x

I am working on a GUI based chat program.
I am using someone else's server which has worked well for many people so I am assuming the problem is with my client's code.
When I run a single instance of the client it works perfectly, but if I run two instances of the client on the same computer the listener stops responding when the 2nd client logs in.
# server is from socket module
# chat_box is a tkinter ListBox
# both are copies of global variable
class listener_thread(threading.Thread):
def __init__(self, server, chat_box):
super(listener_thread, self).__init__()
self.server = server
self.chat_box = chat_box
def run(self):
try:
update = self.server.recv(1024)
msg = update.decode("utf-8")
if msg != "":
self.chat_box.insert(END, msg)
except Exception as e:
print(e)
I've verified that the server is putting each client on a different port. The server is receiving the messages. When 'Michael' logs in and says 'Hi' it updates in his chat_box.
Though, the clients are no longer updating their histories after 'Dave' logs in.
Yet, the server continues to show that it is receiving the messages from both clients.
#This is the server output
#Hi is Michael
#Yo is Dave
#So Michael is still connecting and transmitting after Dave connects
Michael - ('127.0.0.1', 56263) connected
Hi
Dave - ('127.0.0.1', 56264) connected
Yo
Hi
The network connection is working properly. It just locks up the list_box updating threads.
No exceptions are being thrown.

I solved my own problem.
I needed to make the chat_history_listbox as a ListBox initially, instead of None
I needed to put the receive code into a function, with a loop and an exit condition
def receive_func():
global server, chat_history_listbox
while True:
try:
update = server.recv(1024)
except OSError as e:
update = None
break
connect()
msg = update.decode("utf-8")
if msg != "":
chat_history_listbox.insert(END, msg)
I needed to make the thread call a function and make it a daemon
listener = Thread(target=receive_func, daemon=True)
listener.start()
This got it working with multiple clients

Related

How to differentiate between two different socket connections to the same IP?

I have a question. If your socket program is already connected to a user suppose like 192.168.0.25:4545 and in the middle of communication if I run a connect((host,port)) to that ip and port it still accepts the connection.So, is it possible to make something that would connect to the server if a prior connection to that server doesn't already exist. I tried using the router assigned port cuz its unique for each connection, but its getting overly complicated if I do it that way.
Here is the Code dealing with this question
if __name__ == "__main__":
HOST, PORT = "192.168.0.25", 4545
counter_check = 1
while True:
try:
time.sleep(8)
s = Client(HOST, PORT)
s.enable_attempt_reconnect()
if counter_check == 1:
proc = multiprocessing.Process(target=s.start_code)
proc.start() #starting the thread for reverse shell
counter_check += 1
elif proc.is_alive():
proc.terminate() #forcefully close the previous thread
proc = multiprocessing.Process(target=s.start_code)
proc.start() #start a new thread
except Exception:
continue
enable_attempt_reconnect()
def enable_attempt_reconnect(self):
while True:
time.sleep(3)
try:
self.soc.connect((self.host, self.port))
break
except Exception:
continue
Esentially what I am trying to do is if the connection from the client is lost, the client is actively looking for other ways to connect to the server, if another connection comes up, its probably because the current connection one was disconnected, so the client would would proc.terminate() the inital connection and start a newer connection.

PyZMQ segmentation fault, messages not arriving after restart via bash script

im currently facing an issue in which a proxy throws a segmentation error after a random period of time. Restarting the proxy with a bash script leads to messages not arriving.
I was sadly not able to recreate the issue. I am aware that this most likely is related to a partly wrong utilization of zmq and that the error gets thrown by c python.
The System runs 3 diffrent processes.
process, which task is to handle send data, which is a subscriber
context = zmq.Context()
socket = context.socket(zmq.SUB)
socket.connect("tcp://127.0.0.1:8100")
socket.setsockopt(zmq.SUBSCRIBE, b'')
poller = zmq.Poller()
poller.register(socket, zmq.POLLIN)
while True:
try:
socks = dict(poller.poll())
if socket in socks and socks[socket] == zmq.POLLIN:
action, values = socket.recv_pyobj()
##### handling of data #######
except Exception as e:
print(e)
process, being a proxy
def main():
context = zmq.Context()
# Socket facing clients
frontend = context.socket(zmq.XSUB)
frontend.bind("tcp://127.0.0.1:5557")
# Socket facing services
backend = context.socket(zmq.XPUB)
backend.bind("tcp://127.0.0.1:8100")
print("starting broker...")
while True:
try:
zmq.proxy(frontend, backend)
except KeyboardInterrupt:
print("stopping broker...")
frontend.close()
backend.close()
context.term()
quit()
except Exception as e:
print(f"failed with {e}")
if __name__ == "__main__":
main()
process running multiple threads which publish their data.
socket_pub = context.socket(zmq.PUB)
socket_pub.connect("tcp://127.0.0.1:5557")
while True:
# pre processing f.e. outgoing requests
######
# sending results
message = ["Action", {"foo": "bar"}]
socket_pub.send_pyobj(message)
As i was not able to recreate the error and therefor was not able to fix it i am trying to bypass it using a bash script.
The segementation error gets thrown in process nr. 2 (the proxy).
Thus the bash script simply restarts it.
#!/bin/bash
until python3 process2.py; do
echo "bridge broker crashed with exit code $?. Respawning.." >&2
sleep 1
done
The bash script correctly respawns the process if it died due to a segmentation fault.
But notifications from process 3 are not arriving in process 1 anymore.
I was not able to track down why this is happening. I rebuild it localy and if i manually restarted the proxy (without a segmentation fault) the messages directly arrived again.
Does anybody have a clue why this is happening or do i have to find the initial reason for the segmentation fault?

ZeroMQ permanent PULL socket

I’ve been using a PUSH/PULL pattern in an application and it works as expected except when I switch off abruptly the computer or remove the ethernet cable in the PULL-side.
The PUSH-side keeps working with other PULL-sockets, but maintains switched off socket as if still were alive.
I have modified TCP-parameters (interval, count...) without results.
Is it possible to avoid this connection even when the host computer is switched off or the ethernet cable removed?
EDIT:
This is a small test i've made
server.py
import zmq
import time
context = zmq.Context()
socket = context.socket(zmq.PUSH)
socket.setsockopt(zmq.RCVHWM, 1)
socket.setsockopt(zmq.SNDHWM, 1)
socket.setsockopt(zmq.LINGER, 0)
socket.setsockopt(zmq.IMMEDIATE, 1)
print(socket.sndtimeo)
socket.sndtimeo = 0
socket.setsockopt(zmq.TCP_KEEPALIVE,1)
socket.setsockopt(zmq.TCP_KEEPALIVE_CNT,1)
socket.setsockopt(zmq.TCP_KEEPALIVE_IDLE,1)
socket.setsockopt(zmq.TCP_KEEPALIVE_INTVL,1)
socket.bind('tcp://*:5555')
count= 0
while True:
print('Sending', count)
try:
socket.send(str(count).encode('utf-8'), zmq.NOBLOCK)
count+= 1
print('Ok')
except zmq.error.Again:
print('Error')
time.sleep(0.1)
client.py
import zmq
import time
import sys
#from common import time_utils
context = zmq.Context()
socket = context.socket(zmq.PULL)
server = '127.0.0.1:5555'
try:
server = sys.argv[1]
except IndexError:
pass
socket.setsockopt(zmq.TCP_KEEPALIVE,1)
socket.setsockopt(zmq.TCP_KEEPALIVE_CNT,1)
socket.setsockopt(zmq.TCP_KEEPALIVE_IDLE,1)
socket.setsockopt(zmq.TCP_KEEPALIVE_INTVL,1)
socket.setsockopt(zmq.RCVHWM, 1)
socket.connect(server)
while True:
# Wait for next request from client
message = socket.recv()
print("Received request: ", message)
Running one instance of the server and 2 clients (one in the same machine that runs the server and one in other computer). Removing the ethernet cable of the second computer results in that the server keeps sending messages to the second client for a while.
As you can see I have tested all setsockopt.
Q : Is it possible to avoid this connection even when the host Computer is switched off?
For connection-oriented transport-classes, you may .setsockopt( zmq.IMMEDIATE, 1 ) so as to avoid storing outgoing messages on the PUSH-side for a dead connection.
As an additional step, one may add another, explicit ACK/NACK signalling-flow, that may help independently and explicitly detect any such event of a dead-man not responding on the ACK/NACK-loop(s).
Try using the ZMTP ping/pong options. These should detect the connection being lost as it runs at a higher level than the TCP sockets (which can be held open after the connection is down)
ZMQ_HEARTBEAT_IVL, ZMQ_HEARTBEAT_TIMEOUT and ZMQ_HEARTBEAT_TTL
http://api.zeromq.org/4-3:zmq-setsockopt

python client recv only reciving on exit inside BGE

using python 3, I'm trying to send a file from a server to a client as soon as the client connects to the server, problem is that the client do only continue from recv when I close it (when the connection is closed)
I'm running the client in blender game engine, the client is running until it gets to recv, then it just stops, until i exit the game engine, then I can see that the console is receiving the bytes expected.
from other threads I have read that this might be bco the recv never gets an end, that's why I added "\n\r" to the end of my bytearray that the server is sending. but still, the client just stops at recv until I exit the application.
in the code below I'm only sending the first 6 bytes, these are to tell the client the size of the file. after this i intend to send data of the file on the same connection.
what am I doing wrong here?
client:
import socket
import threading
def TcpConnection():
TCPsocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
TCPsocket.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
server_address = ('localhost', 1338)
TCPsocket.connect(server_address)
print("TCP Socket open!, starting thread!")
ServerResponse = threading.Thread(target=TcpReciveMessageThread,args=(TCPsocket,))
ServerResponse.daemon = True
ServerResponse.start()
def TcpReciveMessageThread(Sock):
print("Tcp thread running!")
size = Sock.recv(6)#Sock.MSG_WAITALL
print("Recived data", size)
Sock.close()
Server:
import threading
import socket
import os
def StartTcpSocket():
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_socket.bind(('localhost', 1338))
server_socket.listen(10)
while 1:
connection, client_address = server_socket.accept()
Response = threading.Thread(target=StartTcpClientThread,args=(connection,))
Response.daemon = True # thread dies when main thread (only non-daemon thread) exits.
Response.start()
def StartTcpClientThread(socket):
print("Sending data")
length = 42
l1 = ToByts(length)
socket.send(l1)
#loop that sends the file goes here
print("Data sent")
#socket.close()
def ToByts(Size):
byt_res = (Size).to_bytes(4,byteorder='big')
result = bytearray()
for r in byt_res:
result.append(r)
t = bytearray("\r\n","utf-8")
for b in t:
result.append(b)
return result
MessageListener = threading.Thread(target=StartTcpSocket)
MessageListener.daemon = True # thread dies when main thread (only non-daemon thread) exits.
MessageListener.start()
while 1:
pass
if the problem is that the client don't find a end of the stream, then how can solve this without closing the connection, as I intend to send the file on the same connection.
Update #1:
to clarify, the print in the client that say "recived" is printed first when I exit the ge (the client is closing). The loop that sends the file and recives it where left out of the question as they are not the problem. the problem still occurs without them, client freeze at recv until it is closed.
Update #2:
here are a image of what my consoles are printing when i run the server and client:
as you can see it is never printing the "Recived" print
when i exit the blender game engine, I get this output:
now, when the engine and the server script is exited/closed/finished i get the data printed. so recv is probably pausing the thread until the socket is closed, why are it doing this? and how can i get my data (and the print) before the socket is closing? This also happens if I set
ServerResponse.daemon = False
here are a .blend (on mediafire) of the client, the server running on python 3 (pypy). I'm using blender 2.78a
Update #3:
I tested and verified that the problem is the same on windows 10 and linux mint. I also made a Video showing the problem:
In the video you can see how I only receive data from the server when i exit blender ge. After some research I besinning to suspect that the problem is related to python threading not playing well with the bge.
https://www.youtube.com/watch?v=T5l9YGIoDYA
I have observed a similar phenomenon. It appears that the Python instance doesn't receive any execution cycles from Blender Game Engine (BGE) unless a controller gets invoked.
A simple solution is:
Add another Always sensor that is fired on every logic tick.
Add another Python controller that does nothing, a no-op.
Hook the sensor to the controller.
I applied this to your .blend as shown in the following screen capture.
I tested it by running your server and it seems to work OK.
Cheers, Jim

Setting and Getting Variables within an imported Class

All, I'm implementing websockets using flask/uWSGI. This is relegated to a module that's instantiated in the main application. Redacted code for the server and module:
main.py
from WSModule import WSModule
app = Flask(__name__)
wsmodule = WSModule()
websock = WebSocket(app)
#websock.route('/websocket')
def echo(ws):
wsmodule.register(ws)
print("websock clients", wsmodule.clients)
while True: # This while loop is related to the uWSGI websocket implementation
msg = ws.receive()
if msg is not None:
ws.send(msg)
else: return
#app.before_request
def before_request():
print ("app clients:",wsmodule.clients)
and WSModule.py:
class WSModule(object):
def __init__(self):
self.clients = list()
def register(self, client):
self.clients.append(client)
Problem: When a user connects using websockets (into the '/websocket' route), the wsmodule.register appends their connection socket, this works fine- printout 'websocket clients' shows the appended connection.
The issue is that I can't access those sockets from the main application. This is seen by the 'app clients' printout which never updates (list stays empty). Something is clearly updating, but how to access those changes?
It sounds like your program is being run with either threads or processes, and a wsmodule exists for each thread/process that is running.
So one wsmodule is being updated with the client info, while a different one is being asked for clients... but the one being asked is still empty.
If you are using threads, check out thread local storage.

Resources