2011-09-05 11 views
7

Tôi đang cố gắng tìm hiểu mô đun asyncore. Vì vậy, tôi quyết định phát triển một chương trình trò chuyện. Tôi phải nghe mạng và phát các gói udp cùng một lúc. Nhưng vấn đề là trong khi người dùng gõ một tin nhắn, người dùng không thể nhìn thấy các tin nhắn khác được gửi bởi người dùng khác. Tôi nên làm gì? Mã của tôi:Vòng lặp Asyncore và vấn đề raw_input

#!/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:") 
+0

Bạn đã xem [Twisted] (http://www.twistedmatrix.com) chưa? –

+0

Tôi muốn giải quyết vấn đề này bằng cách sử dụng asyncore nếu có thể. – voiceofthesoul

+0

Bạn có thể cho tôi lý do chính đáng không? –

Trả lời

9

Cuộc gọi raw_input đang chặn, nhưng bạn cũng có thể sử dụng asyncore. Bạn cần phải thêm một cầu thủ thứ ba tức là như thế này:

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) 
+0

cảm ơn, đây là câu trả lời tôi muốn :) – voiceofthesoul

+1

Thật không may, nó chỉ có sẵn trên Unix. – erickrf

0
#!/usr/bin/env python 
# -*- coding: utf8 -*- 

import asyncore 
import logging 
import sys 


logging.basicConfig(level=logging.DEBUG, 
        format='[*] %(name)s - %(funcName)16s - %(message)s') 


class ConsoleHandler(asyncore.file_dispatcher): 
    """Enable console interactive for socket read/write. 
    """ 
    def __init__(self, sender, file): 
     asyncore.file_dispatcher.__init__(self, file) 
     self.current_chat = sender 
     self.BUFSIZE = 1024 

    def handle_read(self): 
     self.current_chat.out_buffer += self.recv(self.BUFSIZE) 


class ChatManager(asyncore.dispatcher): 
    """Handle tcp in-connections, ex: send commands to targets. 
    """ 
    def __init__(self, _sock=None, _map=None): 
     self.logger = logging.getLogger('ChatManager') 
     self.BUFSIZE = 1024 

     asyncore.dispatcher.__init__(self, _sock, _map) 
     self.out_buffer = '' 

    def handle_read(self): 
     """Called when the asynchronous loop detects that a read() call on 
      the channel's socket will succeed.""" 
     data = self.recv(self.BUFSIZE) 
     self.logger.debug('%d bytes | client <- server' % len(data)) 
     print(data.strip()) 
     # self.send(data) 
     self.logger.debug('%d bytes | client -> server' % len(data)) 

    def handle_write(self): 
     """Called when the asynchronous loop detects that a writable 
      socket can be written. Often this method will implement the 
      necessary buffering for performance. For example: 
     """ 
     if self.out_buffer != "": 
      sent = self.send(self.out_buffer) 
      self.out_buffer = self.out_buffer[sent:] 

    def handle_error(self): 
     """Called when an exception is raised and not otherwise handled. 
      The default version prints a condensed traceback. 
     """ 
     self.logger.debug('socket exception') 

    def handle_close(self): 
     """Called when the socket is closed. 
     """ 
     self.close() 


class Listener(asyncore.dispatcher): 
    """Start a tcp listener (default: 127.0.0.1:4444), and wait for connections. 
     If a new connection, `ChatManager' will try to handle it. 
    """ 
    def __init__(self, addr=('127.0.0.1', 4444), max_connections=4): 
     self.logger = logging.getLogger('Listener') 

     asyncore.dispatcher.__init__(self) 
     self.logger.debug('create a socket') 
     self.create_socket(asyncore.socket.AF_INET, 
          asyncore.socket.SOCK_STREAM) 

     # socket reuse address 
     self.set_reuse_addr() 

     self.bind(addr) 
     self.logger.debug('bind socket address') 

     self.listen(max_connections) 
     self.logger.debug('listen socket on %s:%s' % addr) 

    def handle_accept(self): 
     client, caddr = self.accept() 
     self.logger.debug('client: %s:%s' % caddr) 
     self.logger.debug('Enter into ChatManager') 
     ConsoleHandler(ChatManager(client), sys.stdin) 


if __name__ == "__main__": 
    Listener() 
    asyncore.loop() 

Hãy xem năng bảo mật bằng sau:

$ python ChatManager.py 
[*] Listener -   __init__ - create a socket 
[*] Listener -   __init__ - bind socket address 
[*] Listener -   __init__ - listen socket on 127.0.0.1:4444 

Hãy kết nối để char máy chủ với:

$ nc -v 127.0.0.1 4444 

Và sau đó, bạn có thể trò chuyện với máy chủ trên thiết bị đầu cuối.