pythonloopsraw-inputasyncore

Asyncore loop and raw_input problem


I'm trying to learn asyncore module. So I decided to develop a chat program. I have to listen the network and broadcast udp packages same time. But problem is while user typing a message, user cannot see other messages that sent by another users. What should I do? My code:

#!/usr/bin/python
# -*- coding: utf-8 -*-

import asyncore
import socket

class Listener(asyncore.dispatcher):
    def __init__(self, port):
        asyncore.dispatcher.__init__(self)
        self.port = port
        self.create_socket(socket.AF_INET, socket.SOCK_DGRAM)
        self.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        self.bind(('', self.port))

    def handle_connect(self):
        print "CONNECTED."

    def handle_read(self):
        data, addr = self.recvfrom(1024)
        print str(addr) + " > " + data

    def handle_write(self):
        pass

class Sender(asyncore.dispatcher):
    def __init__(self, port):
        asyncore.dispatcher.__init__(self)
        self.buffer = ""
        self.port = port
        self.create_socket(socket.AF_INET, socket.SOCK_DGRAM)
        self.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
        self.bind(('',0))

    def handle_connect(self):
        print "CONNECTED."

    def handle_read(self):
        pass

    def handle_write(self):
        if self.buffer != "":
            sent = self.sendto(self.buffer, ('<broadcast>', self.port))
            self.buffer = self.buffer[sent:]

    def handle_close(self):
        self.close()

    def serve_forever(self):
        asyncore.loop(count = 10)

if  __name__ == "__main__":
    Listener(50000)
    sender = Sender(50000)

    while True:
        sender.serve_forever()
        sender.buffer += raw_input("Message:")

Solution

  • The raw_input call is blocking, but you can use asyncore on it too. You need to add an third player i.e. like this:

    class CmdlineClient(asyncore.file_dispatcher):
        def __init__(self, sender, file):
            asyncore.file_dispatcher.__init__(self, file)
            self.sender = sender
    
        def handle_read(self):
            self.sender.buffer += self.recv(1024)
    
    import sys
    sender = Sender(50000)
    cmdline = CmdlineClient(sender, sys.stdin)