Created
January 6, 2026 00:58
-
-
Save eros18123/62e88fc31f5c354f78c39ccd60350970 to your computer and use it in GitHub Desktop.
chat pc servidor x pc cliente rede interna
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #agente servidor.pyw | |
| # agente.py (Versão Final com Notificação Customizada e 100% Confiável) | |
| import socket | |
| import subprocess | |
| import sys | |
| import os | |
| import threading | |
| import queue | |
| import time | |
| from PIL import Image, ImageDraw | |
| from pystray import MenuItem as item, Icon | |
| # --- Configurações --- | |
| MEU_PAPEL = 'servidor' # <-- MUDE AQUI CONFORME O PC ('servidor' ou 'cliente') | |
| # Portas de comunicação de rede | |
| PORTA_CHAT = 55555 | |
| PORTA_COMANDO_REMOTO = 50001 | |
| PORTA_PRESENCA = 50000 | |
| # Portas de comunicação local (Agente <-> GUI) | |
| PORTA_GUI_LOCAL = 50003 | |
| # Comandos e Mensagens | |
| COMANDO_INICIAR_SERVIDOR = b'INICIE_O_SERVIDOR_DE_CHAT' | |
| MSG_PRESENCA_SERVIDOR = b'SERVIDOR_ONLINE' | |
| # Caminhos dos scripts | |
| base_path = os.path.dirname(os.path.realpath(sys.argv[0])) | |
| caminho_script_servidor = os.path.join(base_path, 'servidor.py') | |
| caminho_script_cliente = os.path.join(base_path, 'cliente.py') | |
| caminho_script_notificador = os.path.join(base_path, 'notificador.py') # <<< NOVO CAMINHO | |
| HISTORICO_CHAT_ARQUIVO_SERVIDOR = os.path.join(base_path, "chat_history.log") | |
| HISTORICO_CHAT_ARQUIVO_CLIENTE = os.path.join(base_path, "chat_history_client.log") | |
| # --- Variáveis Globais de Estado --- | |
| icon = None | |
| socket_remoto = None | |
| socket_gui = None | |
| fila_para_gui = queue.Queue() | |
| fila_mensagens_offline = [] | |
| # --- Funções de Persistência --- | |
| def salvar_mensagem_no_historico(mensagem): | |
| arquivo = HISTORICO_CHAT_ARQUIVO_SERVIDOR if MEU_PAPEL == 'servidor' else HISTORICO_CHAT_ARQUIVO_CLIENTE | |
| try: | |
| with open(arquivo, "a", encoding="utf-8") as f: | |
| f.write(mensagem) | |
| except Exception as e: | |
| print(f"!!! ERRO AO SALVAR HISTÓRICO: {e}") | |
| # --- Funções da Bandeja do Sistema (pystray) --- | |
| def criar_imagem_estrela(): | |
| width, height = 64, 64 | |
| image = Image.new('RGBA', (width, height), (0, 0, 0, 0)) | |
| dc = ImageDraw.Draw(image) | |
| dc.polygon([(32, 0), (40, 24), (64, 24), (44, 40), (52, 64), (32, 48), (12, 64), (20, 40), (0, 24), (24, 24)], fill='red') | |
| return image | |
| def iniciar_programa_chat(ignore_arg1=None, ignore_arg2=None): | |
| script_path = caminho_script_servidor if MEU_PAPEL == 'servidor' else caminho_script_cliente | |
| print(f"Iniciando GUI: {script_path}...") | |
| subprocess.Popen(['pythonw', script_path]) | |
| def fechar_agente(icon, item): | |
| print("Fechando agente...") | |
| icon.stop() | |
| os._exit(0) | |
| # --- Funções de Notificação --- | |
| # <<< FUNÇÃO TOTALMENTE REESCRITA PARA USAR NOSSO PRÓPRIO NOTIFICADOR >>> | |
| def mostrar_notificacao(titulo, mensagem): | |
| try: | |
| print(f"--- CHAMANDO NOTIFICADOR CUSTOMIZADO: Título='{titulo}' ---") | |
| # Executa o script notificador.py em segundo plano, passando o título e a mensagem | |
| subprocess.Popen(['pythonw', caminho_script_notificador, titulo, mensagem]) | |
| except Exception as e: | |
| print(f"!!!!!!!!!! ERRO CRÍTICO AO CHAMAR O SCRIPT NOTIFICADOR: {e} !!!!!!!!!!") | |
| # --- LÓGICA DE REDE PRINCIPAL (código restante sem alterações) --- | |
| def logica_servidor(): | |
| global socket_remoto | |
| servidor = socket.socket(socket.AF_INET, socket.SOCK_STREAM) | |
| servidor.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) | |
| servidor.bind(('0.0.0.0', PORTA_CHAT)) | |
| servidor.listen(1) | |
| print("Lógica do Servidor iniciada. Aguardando conexões...") | |
| threading.Thread(target=anunciar_presenca_servidor, daemon=True).start() | |
| while True: | |
| conn, addr = servidor.accept() | |
| print(f"Cliente {addr[0]} conectou.") | |
| socket_remoto = conn | |
| if fila_mensagens_offline: | |
| for msg in fila_mensagens_offline: | |
| try: | |
| socket_remoto.send(msg.encode('utf-8')) | |
| time.sleep(0.1) | |
| except Exception as e: | |
| print(f"Erro ao enviar msg offline: {e}") | |
| fila_mensagens_offline.clear() | |
| threading.Thread(target=receber_mensagens_remotas, args=(conn,), daemon=True).start() | |
| def anunciar_presenca_servidor(): | |
| with socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP) as sock: | |
| sock.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1) | |
| while True: | |
| if not socket_remoto: | |
| sock.sendto(MSG_PRESENCA_SERVIDOR, ("<broadcast>", PORTA_PRESENCA)) | |
| time.sleep(3) | |
| def logica_cliente(): | |
| global socket_remoto | |
| while True: | |
| servidor_ip = None | |
| try: | |
| with socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as s: | |
| s.settimeout(3) | |
| s.bind(('', PORTA_PRESENCA)) | |
| dados, addr = s.recvfrom(1024) | |
| if dados == MSG_PRESENCA_SERVIDOR: | |
| servidor_ip = addr[0] | |
| except socket.timeout: | |
| with socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP) as sock: | |
| sock.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1) | |
| sock.sendto(COMANDO_INICIAR_SERVIDOR, ("<broadcast>", PORTA_COMANDO_REMOTO)) | |
| time.sleep(5) | |
| continue | |
| if servidor_ip: | |
| try: | |
| sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) | |
| sock.connect((servidor_ip, PORTA_CHAT)) | |
| socket_remoto = sock | |
| print("Conectado ao servidor.") | |
| receber_mensagens_remotas(sock) | |
| except Exception as e: | |
| print(f"Falha ao conectar: {e}. Tentando novamente em 5s.") | |
| socket_remoto = None | |
| time.sleep(5) | |
| def receber_mensagens_remotas(sock): | |
| global socket_remoto | |
| while True: | |
| try: | |
| msg = sock.recv(1024).decode('utf-8') | |
| if not msg: break | |
| print(f"Mensagem remota recebida: {msg}") | |
| titulo = "Nova Mensagem do Cliente" if MEU_PAPEL == 'servidor' else "Nova Mensagem do Servidor" | |
| mostrar_notificacao(titulo, msg) | |
| prefixo = "Cliente: " if MEU_PAPEL == 'servidor' else "Servidor: " | |
| mensagem_completa = f"{prefixo}{msg}\n" | |
| fila_para_gui.put(mensagem_completa) | |
| salvar_mensagem_no_historico(mensagem_completa) | |
| except: | |
| break | |
| print("Conexão remota perdida.") | |
| socket_remoto = None | |
| sock.close() | |
| def servidor_gui_local(): | |
| global socket_gui | |
| with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: | |
| s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) | |
| s.bind(('127.0.0.1', PORTA_GUI_LOCAL)) | |
| s.listen(1) | |
| print(f"Agente escutando a GUI local na porta {PORTA_GUI_LOCAL}.") | |
| while True: | |
| conn, addr = s.accept() | |
| print("GUI conectou ao agente.") | |
| socket_gui = conn | |
| threading.Thread(target=enviar_para_gui, daemon=True).start() | |
| threading.Thread(target=receber_da_gui, daemon=True).start() | |
| def enviar_para_gui(): | |
| while socket_gui: | |
| try: | |
| msg = fila_para_gui.get(timeout=1) | |
| socket_gui.sendall(msg.encode('utf-8')) | |
| except queue.Empty: | |
| continue | |
| except Exception as e: | |
| print(f"Erro ao enviar para GUI: {e}") | |
| break | |
| def receber_da_gui(): | |
| global socket_gui | |
| while True: | |
| try: | |
| msg_bytes = socket_gui.recv(1024) | |
| if not msg_bytes: break | |
| msg = msg_bytes.decode('utf-8') | |
| print(f"Recebido da GUI para enviar: {msg}") | |
| mensagem_completa = f"Você: {msg}\n" | |
| fila_para_gui.put(mensagem_completa) | |
| salvar_mensagem_no_historico(mensagem_completa) | |
| if socket_remoto: | |
| socket_remoto.sendall(msg_bytes) | |
| else: | |
| fila_mensagens_offline.append(msg) | |
| fila_para_gui.put(f"Você (guardado): {msg}\n") | |
| except Exception as e: | |
| print(f"Erro ao receber da GUI: {e}") | |
| break | |
| print("GUI desconectou.") | |
| socket_gui = None | |
| def escutar_comandos_remotos(): | |
| with socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as s: | |
| s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) | |
| s.bind(('', PORTA_COMANDO_REMOTO)) | |
| while True: | |
| dados, _ = s.recvfrom(1024) | |
| if dados == COMANDO_INICIAR_SERVIDOR and MEU_PAPEL == 'servidor': | |
| iniciar_programa_chat() | |
| if __name__ == '__main__': | |
| threading.Thread(target=servidor_gui_local, daemon=True).start() | |
| if MEU_PAPEL == 'servidor': | |
| threading.Thread(target=logica_servidor, daemon=True).start() | |
| threading.Thread(target=escutar_comandos_remotos, daemon=True).start() | |
| elif MEU_PAPEL == 'cliente': | |
| threading.Thread(target=logica_cliente, daemon=True).start() | |
| else: | |
| print("ERRO: MEU_PAPEL deve ser 'servidor' ou 'cliente'.") | |
| sys.exit(1) | |
| menu = (item('Abrir Chat', iniciar_programa_chat, default=True), item('Fechar', fechar_agente)) | |
| icon = Icon("ChatApp", criar_imagem_estrela(), f"Chat App ({MEU_PAPEL})", menu) | |
| icon.run() |
Author
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
#agente cliente.pyw
#obs: é so copiar do agente servidor.pyw e mudar onde tem servidor para cliente
pode ser necessario algumas instalaçoes via cmd, alem do python
pip install pystray Pillow win10toast-persist
py -m pip uninstall win10toast-persist
py -m pip install win10toast-persist
py -m pip install --upgrade pip