Commits

Atsushi Odagiri committed bbee2e9 Draft

first commit

  • Participants

Comments (0)

Files changed (2)

+import sys
+import asyncore
+import socket
+import pickle
+import threading
+try:
+    from queue import Queue, Empty
+except ImportError:
+    from Queue import Queue, Empty
+try:
+    import tkinter
+except ImportError:
+    import Tkinter as tkinter
+
+
+if hasattr(__builtins__, 'raw_input'):
+    input = raw_input
+
+class ChatClient(asyncore.dispatcher_with_send):
+    def __init__(self, name):
+        asyncore.dispatcher_with_send.__init__(self)
+        self.postbox = Queue()
+        self.messagebox = Queue()
+        self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
+        self.connect(('localhost', 8080))
+        self.name = name
+
+    def handle_read(self):
+        data = self.recv(8192)
+        self.messagebox.put(data)
+
+    def handle_connect(self):
+        print('connected')
+
+    def handle_write(self):
+        data = self.postbox.get_nowait()
+        if not isinstance(data, Empty):
+            self.send(data)
+
+    def writable(self):
+        w = not self.postbox.empty()
+        return w
+
+
+    def submit_message(self, message):
+        message = (self.name, message)
+        self.postbox.put(pickle.dumps(message))
+
+    def get_new_message(self):
+        return pickle.loads(self.messagebox.get())
+
+class TaskService:
+
+    def __init__(self, root, client):
+        self.client = client
+        self.listeners = [] 
+        self.root = root
+        self.poll()
+
+    def poll(self):
+        try:
+            asyncore.loop(count=1, timeout=0.5)
+            if not self.client.messagebox.empty():
+                self.notify_recept_message()
+        finally:
+            self.root.after(500, self.poll)
+
+    def notify_recept_message(self):
+        for l in self.listeners:
+            l()
+
+    def add_listener(self, listener):
+        self.listeners.append(listener)
+
+class ChatView(tkinter.Frame):
+    def __init__(self, master):
+        tkinter.Frame.__init__(self, master)
+        self.mainframe = tkinter.Frame(self)
+        self.listbox = tkinter.Listbox(self.mainframe)
+        self.listbox.pack(expand=True, fill=tkinter.BOTH, side=tkinter.LEFT)
+        self.yscroll = tkinter.Scrollbar(self.mainframe, command=self.listbox.yview)
+        self.yscroll.pack(side=tkinter.LEFT, expand=True, fill=tkinter.Y)
+        self.listbox.configure(yscrollcommand=self.yscroll.set)
+        self.mainframe.pack(fill=tkinter.BOTH, expand=True)
+        self.entry = tkinter.Entry(self)
+        self.entry.pack(side=tkinter.BOTTOM, fill=tkinter.X, expand=True)
+
+    @property
+    def message(self):
+        return self.entry.get()
+
+    @message.setter
+    def message(self, message):
+        self.entry.delete(0, tkinter.END)
+        self.entry.insert(0, message)
+
+    def bind(self, presenter):
+        self.entry.bind('<Return>', presenter.on_message_submited)
+
+    def show_message(self, message):
+        self.listbox.insert(tkinter.END, message)
+        self.listbox.see(tkinter.END)
+
+class ChatPresenter:
+    def __init__(self, view, model):
+        self.view = view
+        self.model = model
+        self.view.bind(self)
+
+    def on_message_submited(self, event):
+        if not self.view.message:
+            return
+
+        message = self.view.message
+        self.model.submit_message(message)
+        self.view.message = ""
+
+    def on_message_received(self):
+        message = self.model.get_new_message()
+        name, message = message
+        self.view.show_message("[{0}] {1}".format(name, message))
+
+
+def main():
+    root = tkinter.Tk()
+    name = sys.argv[1]
+    client = ChatClient(name)
+
+    view = ChatView(root)
+    presenter = ChatPresenter(view, client)
+
+    service = TaskService(root=root, client=client)
+    service.add_listener(presenter.on_message_received)
+
+    view.pack(expand=True, fill=tkinter.BOTH)
+    sys.exit(root.mainloop())
+
+if __name__ == '__main__':
+    main()
+import asyncore
+import pickle
+
+
+class EchoHandler(asyncore.dispatcher_with_send):
+
+    def __init__(self, socket, server):
+        super(EchoHandler, self).__init__(socket)
+        self.server = server
+
+    def handle_read(self):
+        print('read')
+        data = self.recv(8192)
+        print('data {0}'.format(data))
+        if data:
+            self.server.notify(data)
+
+
+class EchoServer(asyncore.dispatcher):
+
+    def __init__(self, host, port):
+        asyncore.dispatcher.__init__(self)
+        self.create_socket()
+        self.set_reuse_addr()
+        self.bind((host, port))
+        self.listen(5)
+        self.handlers = []
+
+    def handle_accepted(self, sock, addr):
+        print('Incoming connection from %s' % repr(addr))
+        handler = EchoHandler(sock, self)
+        self.handlers.append(handler)
+
+    def notify(self, data):
+        for client in self.handlers:
+            client.send(data)
+
+def main():
+    server = EchoServer('localhost', 8080)
+    asyncore.loop()
+
+if __name__ == '__main__':
+    main()