A RetroSearch Logo

Home - News ( United States | United Kingdom | Italy | Germany ) - Football scores

Search Query:

Showing content from https://stackoverflow.com/questions/79715289/why-does-python-socketio-sio-emit-not-work below:

sockets - Why does python socketio sio.emit() not work?

I need help with my Python desktop app.

The issue is that I have set up the clipboard_button from the main.py to trigger the send_message_test function in the Server class. The function has clearly run since the output from the two print functions ([server] ran send_message_test and [server] done running send_message_test) appears, and the self.connected_sid that is also printed out appears to valid and correct.

However, the self.sio.emit("test", "test", room=self.connected_sid) doesn't seem to do anything, the connection is valid, and the file-ack emit works just fine! I already searched everywhere for a solution and tried many different ways, but none seemed to help.

main.py:

import sys
import threading
import time
import json
import qrcode
import pyperclip
from PIL.ImageQt import ImageQt
from PySide6.QtCore import (
    Qt, Property, QEasingCurve, QPropertyAnimation, Signal, QSize
)
from PySide6.QtGui import QCursor, QColor, QEnterEvent, QFont, QFontDatabase, QIcon, QPixmap
from PySide6.QtWidgets import (
    QApplication, QWidget, QPushButton, QLabel,
    QHBoxLayout, QVBoxLayout
)
from server import Server
from win10toast import ToastNotifier
from PySide6.QtWidgets import QLabel

toaster = ToastNotifier()



class AnimatedButton(QPushButton):
    def __init__(self, text):
        super().__init__(text)
        self._color = QColor("#4C4C4C")
        self.setStyleSheet(f"background-color: {self._color.name()}")
        self.animation = QPropertyAnimation(self, b"bgColor")
        self.animation.setDuration(140)
        self.animation.setEasingCurve(QEasingCurve.InOutQuad)

    def enterEvent(self, event: QEnterEvent):
        self.animate_to(QColor("#2D2D2D"))
        super().enterEvent(event)

    def leaveEvent(self, event):
        self.animate_to(QColor("#4C4C4C"))
        super().leaveEvent(event)

    def animate_to(self, color):
        self.animation.stop()
        self.animation.setStartValue(self._color)
        self.animation.setEndValue(color)
        self.animation.start()

    def get_bg_color(self):
        return self._color

    def set_bg_color(self, color):
        self._color = color
        self.setStyleSheet(f"background-color: {color.name()};")

    bgColor = Property(QColor, get_bg_color, set_bg_color)

class MainWindow(QWidget):
    file_received_signal = Signal(dict)
    clipboard_received_signal = Signal(str)
    text_received_signal = Signal(str)
    test_button_clicked_signal = Signal(any)

    def __init__(self):
        super().__init__()
        self.server = server
        self.setWindowTitle("Connection Button")
        self.setFixedSize(846, 520)

        # Status bar unfinished
        # self.status_bar = QWidget()
        # self.status_bar.setObjectName("status_bar")
        # self.status_bar.setFixedSize(758, 112)
        # self.status_bar_layout = QHBoxLayout(self.status_bar)
        # self.status_label = QLabel("Status: Waiting...")
        # self.status_label.setAlignment(Qt.AlignCenter)
        # self.status_bar_layout.addWidget(self.status_label)

        # Clipboard button
        self.clipboard_button = AnimatedButton("Clipboard")
        self.clipboard_button.setObjectName("clipboardButton")
        self.clipboard_button.setFixedSize(352, 112)
        self.clipboard_button.setCursor(QCursor(Qt.PointingHandCursor))
        self.clipboard_button.setIcon(QIcon("assets/icons/Paperclip.svg"))
        self.clipboard_button.setIconSize(QSize(32, 32))
        self.clipboard_button.setLayoutDirection(Qt.RightToLeft)

        


        # Filesharing button
        self.filesharing_button = AnimatedButton("Filesharing")
        self.filesharing_button.setObjectName("filesharingButton")
        self.filesharing_button.setFixedSize(352, 112)
        self.filesharing_button.setCursor(QCursor(Qt.PointingHandCursor))
        self.filesharing_button.setIcon(QIcon("assets/icons/file.svg"))
        self.filesharing_button.setIconSize(QSize(32, 32))
        self.filesharing_button.setLayoutDirection(Qt.RightToLeft)

        # Share text button
        self.text_button = AnimatedButton("Share text")
        self.text_button.setObjectName("textButton")
        self.text_button.setFixedSize(352, 112)
        self.text_button.setCursor(QCursor(Qt.PointingHandCursor))
        self.text_button.setIcon(QIcon("assets/icons/placeholder.svg"))
        self.text_button.setIconSize(QSize(32, 32))
        self.text_button.setLayoutDirection(Qt.RightToLeft)

        # QR box
        self.qrbox = QWidget()
        self.qrbox.setObjectName("box")
        self.qrbox.setFixedSize(382, 382)
        self.qrbox_layout = QVBoxLayout(self.qrbox)


        # Layout
        buttons_layout = QVBoxLayout()
        buttons_layout.addWidget(self.clipboard_button)
        buttons_layout.addWidget(self.filesharing_button)
        buttons_layout.addWidget(self.text_button)
        buttons_layout.setSpacing(24)

        button_box_layout = QHBoxLayout()
        button_box_layout.addWidget(self.qrbox)
        button_box_layout.addLayout(buttons_layout)
        button_box_layout.setSpacing(24)
        button_box_layout.setAlignment(Qt.AlignCenter)

        layout = QVBoxLayout(self)
        # layout.addWidget(self.status_bar)
        layout.setAlignment(Qt.AlignCenter)
        layout.addSpacing(24)
        layout.addLayout(button_box_layout)

        #signals
        self.file_received_signal.connect(self.handle_file)
        self.clipboard_received_signal.connect(self.handle_clipboard)
        self.text_received_signal.connect(self.handle_text)
        
        self.test_button_clicked_signal.connect(self.server.send_message_test)
            
        self.clipboard_button.clicked.connect(self.test_button_clicked_signal) 
        # self.clipboard_button.clicked.connect(self.text_received_signal)
    def send_clipboard_to_phone(self):
        text = pyperclip.paste()
        if text: 
            # self.server.send_clipboard(text=text)
            pass
        else:
            print("clipboard is empty")


    def handle_callback(self, msg_type, content):
        if msg_type == "file":
            self.file_received_signal.emit(content)
        elif msg_type == "clipboard":
            self.clipboard_received_signal.emit(content)
        elif msg_type == "text":
            self.text_received_signal.emit(content)
        else:
            print(f"Unknown type: {msg_type}")

    def handle_file(self, file_info):
        fname = file_info.get("filename", "unknown")
        ftype = file_info.get("filetype", "unknown")
        toaster.show_toast(f"Received {ftype}", fname)

    def handle_clipboard(self, text):
        pyperclip.copy(text)
        toaster.show_toast("Copied to clipboard", text)
        while toaster.notification_active(): time.sleep(0.1)

    def handle_text(self, text):
        print(f"UI: Text received - {text}")

    def update_qr(self, data: dict,
                  fill_color: str = "#000",
                  back_color: str = "#000"):
        for i in reversed(range(self.qrbox_layout.count())):
            w = self.qrbox_layout.itemAt(i).widget()
            if w:
                w.setParent(None)
        payload = json.dumps(data, separators=(',', ':'))
        qr = qrcode.QRCode(
            version=1, error_correction=qrcode.constants.ERROR_CORRECT_L,
            box_size=10, border=4
        )
        qr.add_data(payload)
        qr.make(fit=True)
        pil_img = qr.make_image(fill_color=fill_color, back_color=back_color).convert("RGB")
        qt_img = ImageQt(pil_img)
        pix = QPixmap.fromImage(qt_img)
        lbl = QLabel(alignment=Qt.AlignCenter)
        lbl.setPixmap(pix.scaled(400, 400, Qt.KeepAspectRatio))
        lbl.setStyleSheet("background: transparent;")
        self.qrbox_layout.addWidget(lbl)



if __name__ == "__main__":

    server = Server()
    app = QApplication(sys.argv)
    font_id = QFontDatabase.addApplicationFont("assets/fonts/poppins-v23-latin-700.ttf")
    if font_id != -1:
        app.setFont(QFontDatabase.applicationFontFamilies(font_id)[0])
    with open("styles/theme.qss", "r") as f:
        app.setStyleSheet(f.read())
    win = MainWindow()
    win.update_qr({"ip": server.ip_address, "port": server.port, "authToken": server.token, "name": "pc"},
                  fill_color="#2D2D2D", back_color="#D3D3D3")
    print(server.ip_address)
    server.start()
    server.register_callback('file', win.handle_file)
    server.register_callback('message', win.handle_callback)
    win.show()
    sys.exit(app.exec())

server.py:

import eventlet
from eventlet import wsgi
from urllib.parse import parse_qs
import socket
import socketio
import threading
import json
import base64
import random


class Server:
    def __init__(self):
        # core socket.io server
        self.sio = socketio.Server(cors_allowed_origins='*')
        self.app = socketio.WSGIApp(self.sio)

        # track exactly one connected client
        self.connected_sid = None

        # auth token, IP, port
        self.token = self.generate_token()
        self.ip_address = self.get_local_ip()
        self.port = 5000

        # GUI callbacks (for file/text), registered later
        self._callbacks = {
            'message': None,
            'file': None,
        }

        # ——— event handlers ———
        @self.sio.event
        def connect(sid, environ):
            print(f"[CONNECT] raw sid = {sid}, qs = {environ.get('QUERY_STRING')}")
            query = parse_qs(environ.get('QUERY_STRING', ''))
            token = query.get('token', [None])[0]
            self.sio.emit("test", {}, room=sid)
            if token == self.token:
                self.connected_sid = sid
                print(f"✅ Client {sid} connected with valid token.")
                self.sio.emit("message", {})
                self.sio.emit("wtv", "wtv", room=sid)
                self.sio.emit("test", {}, room=sid)
            else:
                print(f"❌ Client {sid} invalid token: {token}")
                raise socketio.exceptions.ConnectionRefusedError('Unauthorized')
            self.sio.emit("test", {}, room=sid)


        @self.sio.event
        def disconnect(sid):
            print(f"[DISCONNECT] sid = {sid}")
            if sid == self.connected_sid:
                self.connected_sid = None
                print("→ Cleared connected_sid")

        @self.sio.event
        def file(sid, data):
            print(f"[FILE] from {sid}")
            try:
                filename = data.get("name")
                filetype = data.get("type", "application/octet-stream")
                b64 = data.get("data", "")
                content = base64.b64decode(b64)
                with open(filename, "wb") as f:
                    f.write(content)
                print(f"Saved file: {filename}")

                if self._callbacks['file']:
                    self._callbacks['file']({
                        "filename": filename,
                        "filetype": filetype,
                    })

                self.sio.emit(
                    "file-ack",
                    {"status": "received", "filename": filename},
                    room=sid
                )

            except Exception as e:
                print("Error in file handler:", e)

        @self.sio.event
        def message(sid, data):
            print(f"[MESSAGE] raw data from {sid}:", data)
            try:
                if isinstance(data, str):
                    data = json.loads(data)
                msg_type = data.get("type", "text")
                content = data.get("content", "")
                if self._callbacks['message']:
                    self._callbacks['message'](msg_type, content)
            except Exception as e:
                print("Error in message handler:", e)

    def generate_token(self):
        return str(random.randint(1000, 9999))


    def send_message_test(self):
        print("[server] ran send_message_test")
        print(f"[server] self:  {self.connected_sid}")
        self.sio.emit("test", "test", room=self.connected_sid)
        print("[server] done running send_message_test")


    def get_local_ip(self):
        s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        try:
            s.connect(('8.8.8.8', 80))
            return s.getsockname()[0]
        except:
            return '127.0.0.1'
        finally:
            s.close()

    def start(self):
        threading.Thread(
            target=lambda: wsgi.server(
                eventlet.listen(('0.0.0.0', self.port)), self.app
            ),
            daemon=True
        ).start()
        print(f"Server started on {self.ip_address}:{self.port}")
        print(f"Auth token = {self.token}")
        print(f"[server] {self}")

    def register_callback(self, event_name, callback):
        if event_name in self._callbacks:
            self._callbacks[event_name] = callback
        else:
            raise ValueError(f"Unknown event '{event_name}'")

if __name__ == "__main__":
    server = Server()
    server.start()

I'm using expo react native to connect: main.tsx:

//#region
// main.tsx
import * as Clipboard from 'expo-clipboard';
import * as DocumentPicker from 'expo-document-picker';
import * as FileSystem from 'expo-file-system';

import React, { useEffect, useRef, useState } from 'react';
import { Alert, Platform, Pressable, StyleSheet, Text, View } from 'react-native';
import 'react-native-url-polyfill/auto';
import { Socket } from 'socket.io-client';

import Fileicon from '../../assets/images/file.svg';
import ClipboardIcon from '../../assets/images/Paperclip.svg';
import PlaceHolderIcon from '../../assets/images/placeholder.svg';
import WifiIcon from '../../assets/images/wifi.svg';

import { useConnection } from '../(tabs)/test';

export default function MainScreen() {
  const { activeConnection } = useConnection();
  const [message, setMessage] = useState('');
  const socketRef = useRef<Socket | null>(null);
  const [isConnected, setIsConnected] = useState(false);

  useEffect(() => {
  if (!activeConnection || !activeConnection.socket) {
    socketRef.current?.disconnect();
    socketRef.current = null;
    setIsConnected(false);
    return;
  }
  
  
  const socket = activeConnection.socket;
  socketRef.current = socket;


  socket.onAny((event, ...args) => {
  console.log(`📲 [onAny] event=’${event}’, args=`, args);
  console.error(event, args);
  
});

    socket.on('connect', () => {
      console.log('Socket connected');
      setIsConnected(true);
    });

    socket.on('disconnect', () => {
      console.log('Socket disconnected dnwd');
      setIsConnected(false);
    });

    socket.on('connect_error', (err) => {
      console.log('Socket connect error:', err);
      setIsConnected(false);
    });

    socket.on('message', (data: string) => {
      console.log('Received message:', data);
    });

    

    socket.on('test', ()=>{

      
      console.log("test");
      Alert.alert("test");
    }); 


    socket.on('clipboard', (data) => {
      console.log('🐛 Received clipboard event with content:', data);
      if (data && data.content) {
        Alert.alert('Clipboard updated', `Clipboard content: ${data.content}`);
      } else {
        Alert.alert('Clipboard updated', 'Clipboard event received but content empty');
      }
    });
    socket.on('file-ack', (data: { status: string; filename: string }) => {
      console.log('File ACK:', data);
      if (data.status === 'received') {
        Alert.alert('File Uploaded', `${data.filename} was saved on the server.`);
      } else {
        Alert.alert('Upload Failed', `Server responded with status: ${data.status}`);
      }
    });

    return () => {
      // socket.off('connect');
      // socket.off('disconnect');
      // socket.off('connect_error');
      // socket.off('message');
      // socket.off('file-ack');
      // socket.off('clipboard')
      // socket.off('test')
      socket.disconnect();
      socketRef.current = null;
      setIsConnected(false);
    };
  }, [activeConnection]);

  const sendMessage = () => {
    if (!message.trim()) {
      return Alert.alert('Error', 'Please enter a message');
    }
    if (!socketRef.current?.connected) {
      return Alert.alert('Error', 'Not connected to any server');
    }

    socketRef.current.emit('message', message);
    setMessage('');
  };

  const sendClipboard = async () => {
    if (!activeConnection) {
      return Alert.alert('Error', 'Not connected to any server');
    }

    if (!socketRef.current?.connected) {
      return Alert.alert('Error', 'Not connected to any server');
    }

    const clipboardContent = await Clipboard.getStringAsync();
    if (!clipboardContent) {
      return Alert.alert('Clipboard', 'Clipboard is empty');
    }

    socketRef.current.emit(
      'message',
      { type: 'clipboard', content: clipboardContent },
      Alert.alert('clipboard sent successfully')
    );
  };

async function pickAndSendFile() {
    if (Platform.OS === 'web') {
      return Alert.alert("File picking isn't available on web.");
    }

    try {
      const result = await DocumentPicker.getDocumentAsync({
        type: '*/*',
        copyToCacheDirectory: true,
      });

      // If user cancelled
      if (result.canceled === true) {
        return;
      }

      // Ensure assets array exists
      if (!Array.isArray(result.assets) || result.assets.length === 0) {
        return Alert.alert('Error', 'No file selected.');
      }

      const asset = result.assets[0];
      const { uri, name, mimeType } = asset;

      if (typeof uri !== 'string' || typeof name !== 'string') {
        return Alert.alert('Error', 'Invalid file data.');
      }

      await sendFile(uri, name, mimeType ?? 'application/octet-stream');
    } catch (error: any) {
      Alert.alert('Error', 'Failed to pick/send file: ' + error.message);
    }
  }

  async function sendFile(uri: string, filename: string, mimeType: string) {
    if (!socketRef.current?.connected) {
      return Alert.alert('Error', 'Not connected to any server');
    }

    try {
      const base64 = await FileSystem.readAsStringAsync(uri, {
        encoding: FileSystem.EncodingType.Base64,
      });

      socketRef.current.emit('file', {
        name: filename,
        type: mimeType,
        data: base64,
      });
    } catch (error: any) {
      Alert.alert('Error', 'Failed to read and send file: ' + error.message);
    }
  }


  return (
    <View style={styles.container}>
      {/* Connection Status */}
      <Pressable style={[styles.cardBase, activeConnection ? styles.connectionCard : styles.disconnectedCard]}>
        <View style={styles.cardRow}>
          <View>
            <Text style={styles.cardTitle}>
              {activeConnection
                ? `Connected to ${activeConnection.name}`
                : 'Not Connected'}
            </Text>
            <View style={styles.cardDetails}>
              <Text style={styles.cardSub}>
                {activeConnection ? activeConnection.ip : 'XXX.XXX.XX.XXX'}
              </Text>
              <Text style={styles.cardSub}>
                {new Date().toLocaleTimeString([], {
                  hour: '2-digit',
                  minute: '2-digit',
                  second: '2-digit',
                })}
              </Text>
            </View>
          </View>
          <WifiIcon width={28} height={28} />
        </View>
      </Pressable>

      {/* Clipboard */}
      <Pressable onPress={sendClipboard} style={[styles.cardBase, styles.actionCard]}>
        <View style={styles.iconRow}>
          <Text style={styles.buttonText}>Send Clipboard</Text>
          <ClipboardIcon width={28} height={28} />
        </View>
      </Pressable>

      {/* File */}
      <Pressable onPress={pickAndSendFile} style={[styles.cardBase, styles.actionCard]}>
        <View style={styles.iconRow}>
          <Text style={styles.buttonText}>Send File</Text>
          <Fileicon width={28} height={28} />
        </View>
      </Pressable>

      {/* Message */}
      <Pressable onPress={sendMessage} style={[styles.cardBase, styles.actionCard]}>
        <View style={styles.iconRow}>
          <Text style={styles.buttonText}>Send Message</Text>
          <PlaceHolderIcon width={28} height={28} />
        </View>
      </Pressable>

      <Text>{activeConnection?.ip}</Text>
    </View>
  );
}

//#region Styles
const styles = StyleSheet.create({
  container: {
    flex: 1,
    padding: 20,
    paddingTop: 150,
    backgroundColor: '#fff',
    alignItems: 'center',
    fontFamily: 'poppins-regular',
  },
  cardBase: {
    width: '100%',
    borderRadius: 16,
    padding: 16,
    marginBottom: 16,
    height: 112,
    justifyContent: 'center',
  },
  connectionCard: {
    backgroundColor: '#49944E',
  },
  disconnectedCard: {
    backgroundColor: '#D95353',
  },
  cardRow: {
    flexDirection: 'row',
    justifyContent: 'space-between',
    alignItems: 'center',
    paddingHorizontal: 8,
    width: '100%',
  },
  cardTitle: {
    color: '#fff',
    fontSize: 16,
    marginBottom: 6,
    fontFamily: 'poppins-500',
  },
  cardDetails: {
    flexDirection: 'row',
    gap: 16,
  },
  cardSub: {
    color: '#fff',
    fontSize: 12,
    opacity: 0.8,
  },
  actionCard: {
    backgroundColor: '#4C4C4C',
  },
  iconRow: {
    flexDirection: 'row',
    justifyContent: 'space-between',
    alignItems: 'center',
    width: '100%',
    height: '100%',
    paddingHorizontal: 8,
  },
  buttonText: {
    color: '#fff',
    fontSize: 18,
    fontFamily: 'poppins-500',
  },
  response: {
    marginTop: 20,
    fontSize: 16,
    color: '#333',
  },
});
//#endregion

This works just fine besides not receiving said emit, this is very much a debug version.


RetroSearch is an open source project built by @garambo | Open a GitHub Issue

Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo

HTML: 3.2 | Encoding: UTF-8 | Version: 0.7.4