I'm using mosquitto 1.5.7 to run a server on rpi 0 which takes the logs from something, and publish it to a topic:
class LiveLogServer:
def __init__(self, hostname, port, numPos):
self.broker = hostname
self.port = port
self.numPos = numPos
self.status = True
self.stopThread = True
self.topicPublish = '/logServers/logServer{numPos}/live'
self.topicSubscribe = '/logServers/logServer/serials'
self.client = mqtt.Client()
self.connect_mqtt()
self.client.on_message = self.on_message
self.subscribe(self.topicSubscribe)
self.startListen()
#start a log for a specific tid in a thread
def startStreamingLog(self, tid):
os.system('adb logcat -c')
self.p = Popen(['adb', '-t', str(tid), 'logcat', '-v', 'brief', 'example:V', '*:S'],
stdout=PIPE, bufsize=-1, close_fds=ON_POSIX)
self.q = Queue()
self.t = Thread(target=self.process_logline, args=(self.p.stdout, self.q))
self.t.daemon = True # thread dies with the program
self.t.start()
self.logs()
def process_logline(self, out, queue):
for line in iter(out.readline, b''):
queue.put(line)
out.close()
#read all the logs from a camera
def logs(self):
while self.status:
try:
line = self.q.get_nowait() # or q.get(timeout=.1)
except Empty: #queue is empty here, do nothing
continue
else: # got line from log
print(line)
lineTemp = str(line.decode('utf-8').rstrip())
self.publish(lineTemp)
def connect_mqtt(self):
# Set Connecting Client ID
self.client.connect(self.broker, self.port)
self.client.on_connect = self.on_connect
self.client.on_message = self.on_message
return self.client
def on_connect(self, client, userdata, flags, rc):
if rc == 0:
print("Started LiveLogServer for pos [{}]".format(self.numPos))
else:
print("Failed to connect, return code %d\n", rc)
#receive the serial from the client, get the tid for that serial abd start streaming the logs
def on_message(self, client, userdata, msg):
print(msg.payload.decode('utf-8'))
currentID = CameraID().getLatestTID(msg.payload.decode('utf-8'))
print(currentID)
self.startStreamingLog(currentID)
def subscribe(self, topic):
self.client.subscribe(topic)
def publish(self, msg):
publish.single(self.topicPublish, msg, hostname=self.broker)
def startListen(self):
self.client.loop_start()
And I made a GUI with PyQT5 who subscribe to the topic and take the messages, parse them and apply some rules on each line.
class Ui_logWindow(QtCore.QObject):
messageSignal = pyqtSignal(str)
logWindowSignal = pyqtSignal(str)
output_GUI = ''
def showLogs(self):
arg1 = self.lineEdit.text()
arg2 = int(self.lineEdit_2.text())
arg3 = self.lineEdit_3.text()
arg4 = self.lineEdit_4.text()
arg5 = self.lineEdit_5.text()
arg6 = self.lineEdit_6.text()
self.client = ClientLogParser(arg1, arg2, arg3, arg4, arg5, arg6)
self.client.client.on_message = self.onMsgWin
# self.client.client.on_disconnect = self.on_disconnectHere
self.messageSignal.connect(self.appendToLog)
self.appendLogShortcut = self.messageSignal.emit
self.logWindowSignal.connect(self.appendToLogWindow)
self.appendLogWindowShortcut = self.logWindowSignal.emit
self.t = Thread(target = self.client.startListen, args=[])
self.t.daemon = True
self.t.start()
def submit(self):
self.plainTextEdit_2.clear()
self.showLogs()
def on_disconnectHere(self):
print('on disconnect here')
self.client.client.disconnect()
def appendToLog(self,msg):
self.plainTextEdit.appendPlainText(msg)
self.plainTextEdit.moveCursor(QTextCursor.End)
def appendToLogWindow(self,msg):
self.plainTextEdit_2.appendPlainText(msg)
self.plainTextEdit_2.moveCursor(QTextCursor.End)
def onMsgWin(self, client, userdata, msg):
self.listMsg = msg.payload.decode('utf-8').rstrip()
self.appendLogWindowShortcut(self.listMsg)
for line in self.listMsg.split('\n'):
self.client.lp.parseEvent(line)
self.client.rp.evaluateDict(self.client.lp.dictLogs)
self.output_GUI += "COUNT:\n"
for key, val in self.client.lp.dictLogs.items():
self.output_GUI += f"EVT[{key}] COUNT[{val}]\n"
if val > 0:
self.output_GUI += f'------ the event : {key} has been triggered ------\n'
self.output_GUI += "RULES:\n"
for rule_idx in range(len(self.client.rp.dictRulesList)):
if self.client.rp.resultList[rule_idx] == 'critical':
sys.exit(-1)
if self.client.rp.resultList[rule_idx] == 'warning':
self.output_GUI += '----------succes----------\n'
if self.client.rp.resultList[rule_idx] == 'info':
self.output_GUI += '----------succes----------\n'
if self.client.rp.resultList[rule_idx] == 'succes':
self.output_GUI += '----------succes----------\n'
self.output_GUI += f"RULE:[{rule_idx}][{self.client.rp.dictRulesList[rule_idx]}]\n"
self.output_GUI += f"RESULT[{rule_idx}][{self.client.rp.resultList[rule_idx]}]\n"
self.output_GUI += "----ITERATION-END----\n"
self.appendLogShortcut(self.output_GUI)
class ClientLogParser:
def __init__(self, hostname, port, serial, numPos, lp_path, rp_path):
self.broker = hostname
self.port = port
self.serial = serial
self.numPos = numPos
self.lp = LogParserLive(lp_path)
self.rp = ReportParserLive(rp_path)
self.topicPublish = '/logServers/logServer{numPos}/live'
self.topicSubscribe = '/logServers/logServer/serials'
self.client = mqtt.Client(clean_session=True)
self.connect_mqtt()
# self.client.on_message = self.on_message_local
self.publishSerial(serial)
self.subscribe(self.topicPublish)
self.running = False
# self.startListen()
def connect_mqtt(self):
# Set Connecting Client ID
# self.client.reinitialise(clean_session=True)
self.client.connect(self.broker, self.port)
self.client.on_connect = self.on_connect
self.client.on_message = self.on_message
self.client.on_disconnect = self.on_disconnect
return self.client
def on_connect(self, client, userdata, flags, rc):
if rc == 0:
print(f"Started pinServer for pos [{self.numPos}]")
else:
print("Failed to connect, return code %d\n", rc)
def on_disconnect(self, client, userdata, rc):
print('disconnected')
def on_message_local(self, client, userdata, msg):
msg.payload.decode('utf-8')
def subscribe(self, topic):
self.client.subscribe(topic)
def publishSerial(self, msg):
publish.single(self.topicSubscribe, msg, hostname=self.broker)
def startListen(self):
self.running = True
self.client.loop_start()
print('connected')
self.looping()
def looping(self):
while self.running:
sleep(.5)
The thing is the GUI is working as I expect when I click on Submit, after that I click on Stop and it's stopping taking the logs from the server. BUT when I click AGAIN on submit the same log line is doubled, if I do again stop and submit the lines are tripled and so on.
Can anyone help me with this please?
I found the problem, in QT class every time I was instantiate the signals and connect them without disconnect them.
class Ui_logWindow(QtCore.QObject):
messageSignal = pyqtSignal(str)
logWindowSignal = pyqtSignal(str)
So I disconnect them in my disconnect method:
def on_disconnectHere(self):
print('on disconnect here')
self.messageSignal.disconnect()
self.logWindowSignal.disconnect()
self.client.client.disconnect()
Related
How to put packet in socket, when I use socket.recv? I made my TCP server to client network. But in the code, I want to put packet in self.soc.recv(1024). How can I put the packet in socket?
Here's my code
#서버 코드
import threading, socket
class Room: #채팅방
def __init__(self):
self.clients = []#접속한 클라이언트를 담당하는 ChatClient 객체 저장
def addClient(self, c):#클라이언트 하나를 채팅방에 추가
self.clients.append(c)
def delClent(self, c):#클라이언트 하나를 채팅방에서 삭제
self.clients.remove(c)
def sendAllClients(self, msg):
for c in self.clients:
c.sendMsg(msg)
class ChatClient:#텔레 마케터: 클라이언트 1명이 전송한 메시지를 받고, 받은 메시지를 다시 되돌려줌
def __init__(self, id, soc, r):
self.id = id #클라이언트 id
self.soc = soc #담당 클라이언트와 1:1 통신할 소켓
self.room = r #채팅방 객체
def recvMsg(self):
while True:
data = self.soc.recv(1024)
msg = data.decode()
if msg == '/stop':
self.sendMsg(msg) # 클라이언트쪽의 리시브 쓰레드 종료하라고..
print(self.id,'님 퇴장')
break
msg = self.id+': ' + msg
self.room.sendAllClients(msg)
self.room.delClent(self)
self.room.sendAllClients(self.id+'님이 퇴장하셨습니다.')
def sendMsg(self, msg): #담당한 클라이언트 1명에게만 메시지 전송
self.soc.sendall(msg.encode(encoding='utf-8'))
def run(self):
t = threading.Thread(target=self.recvMsg, args=())
t.start()
class ServerMain:
ip = '192.168.55.232'
port = 2500
def __init__(self):
self.room = Room()
self.server_soc = None
def open(self):
self.server_soc = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.server_soc.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
self.server_soc.bind((ServerMain.ip, ServerMain.port))
self.server_soc.listen()
def run(self):
self.open()
print('채팅 서버 시작')
while True:
c_soc, addr = self.server_soc.accept()
print(addr)
msg = '사용할 id:'
c_soc.sendall(msg.encode(encoding='utf-8'))
msg = c_soc.recv(1024)
id = msg.decode()
cc = ChatClient(id, c_soc, self.room)
self.room.addClient(cc)
cc.run()
print('클라이언트', id, '채팅 시작')
def main():
server = ServerMain()
server.run()
main()
I got my packet by wireshark, and I want put packet in soket.recv(). Is any solution that I can get?
Trying to implement some kind of synergy on python using PyAutoGui and socket communication.
The idea is to control mouse and keyboard of another computer on LAN by using mouse/keyboard of a server computer.
By now it's only mouse movement implementaion.
Here are some classes:
Server part:
class Server:
def __init__(self):
self.s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
self.ip = get_ip()
self.port = 3000
self.transfer_mod = False
self.client_address = ""
def start(self):
print("Started server with ip: {}".format(self.ip))
self.s.bind((self.ip, self.port))
self.get_connection()
def get_connection(self):
print("Waiting for connection...")
while True:
request, self.client_address = self.s.recvfrom(4096)
if request:
self.s.sendto(request, self.client_address)
print("{} connected!".format(self.client_address))
break
def enable_transfer(self):
print("Transfer to {} enabled".format(self.client_address))
self.transfer_mod = True
transfer_thread = threading.Thread(target=self.transfer_mouse)
transfer_thread.start()
def disable_transfer(self):
print("Transfer to {} disabled".format(self.client_address))
self.transfer_mod = False
def transfer_mouse(self):
previous_pos = (-1, -1)
while self.transfer_mod:
pos = pyautogui.position()
if pos != previous_pos:
data = pickle.dumps(pos)
self.s.sendto(data, self.client_address)
sleep(0.1)
previous_pos = pos
def close(self):
self.disable_transfer()
self.s.close()
Client part:
class Client:
def __init__(self):
self.s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
self.port = 3000
self.connection = False
def connect(self, server_ip):
request = bytes("Request","utf-8")
self.s.sendto(request, (server_ip, self.port))
received, address = self.s.recvfrom(4096)
if received == request:
print("Connected to {}".format(server_ip))
self.connection = True
threading.Thread(target=self.receive_data).start()
def receive_data(self):
while self.connection:
data, server = self.s.recvfrom(4096)
pos = pickle.loads(data)
self.control_mouse(pos)
def disconnect(self):
print("Disconnected from the server")
self.connection = False
def control_mouse(self, position):
pyautogui.moveTo(position[0], position[1])
def close(self):
self.disconnect()
self.s.close()
So, the problem of that is the speed of mouse movement on client computer is so low. It seems there are too many exceed packets or something like that. So, the question itself: Is it a good way of implementing this idea, if yes, what's the problem of that script, if no, any advises on how to do it more properly?
I am learning python asyncio module and try to write a socks5 server with it. Python docs said:
Called when some data is received. data is a non-empty bytes object
containing the incoming data.
I wonder when client sends 2 bytes data, will data_received(self, data) just receive 1 byte not 2 bytes when it called and the rest 1 byte will call data_received(self, data) again?
#!/usr/bin/env python3
import asyncio
import logging
import socket
import struct
logging.basicConfig(level=logging.DEBUG,
format='{asctime} {levelname} {message}',
datefmt='%Y-%m-%d %H:%M:%S',
style='{')
class Remote(asyncio.Protocol):
def connection_made(self, transport):
self.transport = transport
self.server_transport = None
def data_received(self, data):
self.server_transport.write(data)
class Server(asyncio.Protocol):
INIT, REQUEST, REPLY = 0, 1, 2
def connection_made(self, transport):
client_info = transport.get_extra_info('peername')
logging.info('connect from {}'.format(client_info))
self.transport = transport
self.state = self.INIT
def data_received(self, data):
if self.state == self.INIT:
if data[0] == 5:
amount = data[1] # Authentication amount
if 0 in data[2:]:
self.transport.write(b'\x05\x00')
self.state = self.REQUEST
else:
self.eof_received()
else:
self.eof_received()
elif self.state == self.REQUEST:
ver, cmd, rsv, addr_type = data[:4]
logging.info('addr type: {}'.format(addr_type))
if addr_type == 1: # ipv4
addr = socket.inet_ntoa(data[4:8])
elif addr_type == 3:
addr_len = data[4]
addr = data[5:5+addr_len]
else:
data = b'\x05\x08\x00\x01'
data += socket.inet_aton('0.0.0.0') + struct.pack('>H', 0)
self.transport.write(data)
logging.error('not support addr type')
self.eof_received()
port = struct.unpack('>H', data[-2:])[0]
logging.info('target: {}:{}'.format(addr, port))
asyncio.ensure_future(self.remote(addr, port))
self.state = self.REPLY
elif self.state == self.REPLY:
logging.info('start relay')
self.remote_transport.write(data)
async def remote(self, addr, port):
loop = asyncio.get_event_loop()
transport, _remote = await loop.create_connection(Remote, addr, port)
_remote.server_transport = self.transport
self.remote_transport = transport
bind_addr, bind_port = transport.get_extra_info('sockname')
data = b'\x05\x00\x00\x01'
data += socket.inet_aton(bind_addr) + struct.pack('>H', bind_port)
self.transport.write(data)
if __name__ == '__main__':
loop = asyncio.get_event_loop()
server = loop.create_server(Server, '127.0.0.2', 1089)
loop.run_until_complete(server)
try:
loop.run_forever()
except KeyboardInterrupt:
server.close()
loop.run_until_complete(server.close())
loop.close()
no, data_received will receive as many bytes as are already received by the server. If you need to receive the first 3 bytes to handle the request, then you should implement some buffering in your Protocol to allow you to wait for the rest of the request to arrive before continuing.
It would typically look like this:
def __init__(self, …):
self._buffer = bytearray()
…
def data_received(self, data):
self._buffer += data
if self.state == self.INIT:
# here we need at least 3 bytes.
# if we don't have enough data yet, just wait for the next `data_received` call
if len(self._buffer) < 3:
return
header, self._buffer = self._buffer[:2], self._buffer[2:]
# parse authentication header, switch the state to REQUEST
elif self.state == self.REQUEST:
…
I have set up a socket server with a client and a host.
It works fine until the client has disconnected, with both .shutdown() and .close().
When I then launch the client again, it can't connect.
I presume this is not because of how I've written my code but rather what I haven't written.
How do I make the server truly disconnect the client's connection so that it can connect again?
Server:
import socket, threading, time, json
ONLINE_USERS = []
SESSION = None
class User():
def __init__(user, connection, address):
print('for', address, '{Connection established}')
user.connection = connection
user.address = address
user.character = None
threading.Thread(target=user.process, args=(), daemon=True).start()
def process(user):
time.sleep(1)
user.send("&pLogin\n^^^^^\n")
username = user.send("&iUser>")
password = user.send("&iPass>")
print(user.ping())
print(user.logout())
def send(user, *x):
user.connection.sendall(str.encode(str(x)))
data = user.connection.recv(1024)
return data if data!=b'\x01' else True
def recv(user, x):
user.connection.recv(x)
def ping(user):
start = time.time()
user.connection.sendall(b'\x02')
end = float(user.connection.recv(1024))
return round((end - start) * 1000)
def logout(user):
user.connection.sendall(b'\x04')
return user.connection.recv(4)
class Session():
def __init__(session, host='', port=12345):
session.host = host
session.port = port
session.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
session.socket.bind((host, port))
session.socket.listen(10)
def accept():
conn = User(*session.socket.accept())
session.thread_accept = threading.Thread(target=accept, args=(), daemon=True).start()
def shutdown():
for user in ONLINE_USERS.keys():
ONLINE_USERS[user].connection.sendall(bytes([0xF]))
if __name__ == '__main__':
SESSION = Session()
input('Press heart to continue!\n')
Client:
import socket, sys, threading, time, os
def clear(t=0.5):
time.sleep(t)
os.system('cls')
def tryeval(x, default):
try:
return eval(x)
except:
return default
class Client():
def __init__(client):
try:
server_info = input('IP_ADDRESS:PORT>').split(':')
client.host = server_info[0]
client.port = int(server_info[1])
except:
client.host = 'localhost'
client.port = 12345
client.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.socket.settimeout(10)
try:
client.socket.connect((client.host, client.port))
clear()
client.data_exchange()
finally:
client.shutdown()
def data_exchange(client):
while True:
data = client.socket.recv(1024)
if data:
if data==b'\x02':
client.socket.sendall(str.encode(str(time.time())))
elif data==b'\x04':
client.shutdown()
else:
data = tryeval(data, ())
response = []
for item in data:
try:
prefix, content = item[:2], item[2:]
if prefix=='&p':
print(content, end='')
elif prefix=='&i':
response.append(input(content))
if prefix=='&c':
time.sleep(float(content))
clear()
except:
pass
if len(response)>0:
client.socket.sendall(str.encode(str(tuple(response))))
else:
client.socket.sendall(b'\x01')
time.sleep(0.001)
def shutdown(client):
try:
client.socket.sendall(b'\x04')
except:
pass
print('Shutting down program.')
client.socket.shutdown(socket.SHUT_RDWR)
print('Socket has been shutdown.')
client.socket.close()
print('Socket has been closed.')
print('Exiting program')
time.sleep(1)
sys.exit()
if __name__ == '__main__':
client = Client()
"The server repeatedly calls accept waiting for new incoming connections." No it doesn't. It calls accept once in a thread...which exits. – Mark Tolonen
I want to edit all client QTextBrowser logs when any client sends some message to server.
my intended procedure is this:
[client]enter -> [client]chatUI.handleEnter -> (RFC)[server]exposed_send -> [server]broadcast -> (RFC)[clients]update.emit() -> [clients]listen -> log changed
When I run this code, other clients logs are not changed and only the client that give input to server has an updated log.
How I can solve this to update all clients properly?
chat_server.py
import rpyc
import random
import string
from threading import RLock
users = dict()
callbacks = dict()
user_num = 0
lock = RLock()
buf = dict()
class chatService(rpyc.Service):
def on_connect(self):
global user_num
with lock:
user_num = user_num+1
print ("connect user: %d" % user_num)
def on_disconnect(self):
global user_num
with lock:
user_num = user_num-1
print ("disconnect user: %d" % user_num)
def exposed_accept(self, idt, callback):
with lock:
global users
global callbacks
if not isinstance(idt, str) or len(idt) != 6:
return False
elif idt in users:
return -1
else:
pw = ''.join(random.choice(string.ascii_uppercase + string.digits) for _ in range(32))
users[idt] = pw
callbacks[idt] = rpyc.async(callback)
return pw
def exposed_send(self, target, msg, idt, pw):
print ('here')
name = self.identify(idt, pw)
if name == False:
print ('here2')
return False
else:
print ('here3')
global callbacks
if target == None:
self.broadcast("[%s] %s" % (name, msg))
elif msg.target in callbacks:
self.send("[%s] %s" %(name, msg), target)
else:
return False
def exposed_order(self, msg, idt, pw):
pass
def identify(self, idt, pw):
global users
if users[idt] == pw:
return idt
else:
return False
def broadcast(self, msg):
with lock:
print("bloadcast calls")
global callbacks
global buf
for user, callback in callbacks.items():
if user not in buf or buf[user] == None:
buf[user] = (msg,)
else:
buf[user] = buf[user] + (msg,)
callback()
def send(self, msg, target):
global callbacks
global buf
if user not in buf or buf[user] == None:
buf[target] = (msg,)
else:
buf[target] = buf[target] + (msg,)
callbacks[target]()
def exposed_get_buf(self, user):
global buf
temp = buf[user]
buf[user] = None
return temp
if __name__ == '__main__':
from rpyc.utils.server import ThreadedServer
t = ThreadedServer(chatService, port = 3743)
t.start()
chat_client.py
from chatUI import *
import rpyc
import random
import string
if __name__ == '__main__':
service = rpyc.connect('floating.tk', 3743)
app, chat = UIReady(service)
while True:
idt = ''.join(random.choice(string.ascii_uppercase + string.digits) for _ in range(6))
pw = service.root.accept(idt, chat.update.update.emit)
if pw != False and pw != -1:
break
chat.idt = idt
chat.pw = pw
sys.exit(app.exec_())
chatUI.py
import sys
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
class Updater(QObject):
update = pyqtSignal()
class Chat(QWidget):
log = None
enter = None
def __init__(self, service) :
super().__init__()
self.service = service
self.idt = None
self.pw = None
self.initUI()
self.update = Updater()
self.update.update.connect(self.listen)
def initUI(self):
logLabel = QLabel('chat log')
enterLabel = QLabel('enter')
self.log = QTextBrowser()
self.enter = QLineEdit()
self.enter.returnPressed.connect(self.handleEnter)
layout = QGridLayout()
layout.addWidget(logLabel, 0, 0)
layout.addWidget(self.log, 0, 1, 5, 1)
layout.addWidget(enterLabel, 6, 0)
layout.addWidget(self.enter, 6, 1)
self.setLayout(layout)
self.setWindowTitle('chat')
self.resize(600, 600)
self.show()
def handleEnter(self):
msg = self.enter.text()
self.enter.setText("")
self.service.root.send(None, msg, self.idt, self.pw)
print('get enter')
def listen(self):
msg = self.service.root.get_buf(self.idt)
for m in msg:
self.log.append(m)
def UIReady(service):
app = QApplication(sys.argv)
chat = Chat(service)
return app, chat