1

我正在尝试将 irc 客户端添加到我正在处理的 django Web 应用程序中。我希望 irc 通信的服务器端代码使用 python 并通过套接字库进行连接。然后,我将使用 gevent-socketio 从 irc 通道向浏览器中的客户端发送和接收数据。到目前为止,我有一个非常基本的 gevent-socketio 服务器和客户端,可用于在多个客户端之间进行实时广播,但是,当我开始将客户端连接到 IRC 时,它们使用从客户端传递的昵称成功连接到 IRC 服务器,但是然后看起来这是正在进行的保持活动/侦听过程正在阻止从客户端发送任何消息。

Python IRC 代码

import socket

class pycli:
    def __init__(self,user):
        self.nick = user
        self.chan = "#testchannel"
        self.owner = "Bluebot"
        self.sock = socket.socket()
        print "irc conn"

    def send_msg(self,message):
        self.sock.send("PRIVMSG " + self.chan + " : " + message + "\r\n")
    ## misc setup
    def keep_alive(self):
        self.sock.connect(("irc.freenode.net",6667))
        self.sock.send("USER " + self.nick + " 0 * :" + self.owner + "\r\n")
        self.sock.send("NICK " + self.nick + "\r\n")
        while 1:
            ## keep checking for data
            data = self.sock.recv(512)
            datalen = len(data.split(" "))
            sender = ""
            msg_type = ""
            msg_rcpt = ""
            message = ""

        ###----------------------------------------------
        ## reply to keep alive pings
            if data[0:4] == "PING":
                self.sock.send(data.replace("PING", "PONG"))
            if data[0]!=':':
                continue
            if data.split(" ")[1] == "001":
                self.sock.send("MODE " + self.nick + " +B\r\n")
                self.sock.send("JOIN " + self.chan + "\r\n")

        ###-----------------------------------------------
        ##split and assign data parts

        ## parse out the actual sender
            send_data = data.split(" ")[0]
            send_data = send_data[1:]
            sender = send_data.split('!')[0]

        ## mode
            msg_type = data.split(" ")[1]

        ## if it exists get the recipient (room or private)
            if datalen > 2:
                msg_rcpt = data.split(" ")[2]

        ## get the actual message body  
            if datalen > 3:
                message = (" ".join(data.split(" ")[3:])).lower()[1:]
            print data

我知道这个功能是超级基本的,但是一旦我通过客户端让它工作,我就可以扩展它。

我的服务器代码的相关部分基本上如下所示:

def on_login(self, nick):
    if self.nick:
        self._broadcast('exit', self.nick)
        self.nick = nick
        self._broadcast('enter', nick)
        self.emit('users',
              [ ns.nick
                for ns in self._registry.values()
                if ns.nick is not None ])
        t = threading.Thread(target=self.make_start_irc(nick),daemon=True)
        t.start()

def on_chat(self, message):
    if self.nick:
        self._broadcast('chat', dict(u=self.nick, m=message)) 
        self._irc_nicks[self.nick].send_msg("this is a test")
    else:
        self.emit('chat', dict(u='SYSTEM', m='You must first login'))

def make_start_irc(self,nick):
    if nick not in self._irc_nicks.values():
        self._irc_nicks[nick] = pycli.pycli(nick)
        print self._irc_nicks
        self._irc_nicks[nick].keep_alive()

def _broadcast(self, event, message):
    for s in self._registry.values():
        s.emit(event, message)

def chat(environ, start_response):
if environ['PATH_INFO'].startswith('/socket.io'):
    return socketio_manage(environ, { '/chat': ChatNamespace })
else:
    return serve_file(environ, start_response)

def serve_file(environ, start_response):
    path = os.path.normpath(
        os.path.join(public, environ['PATH_INFO'].lstrip('/')))
    assert path.startswith(public), path
    if os.path.exists(path):
        start_response('200 OK', [('Content-Type', 'text/html')])
        with open(path) as fp:
            while True:
                chunk = fp.read(4096)
                if not chunk: break
                yield chunk
    else:
        start_response('404 NOT FOUND', [])
        yield 'File not found'


if __name__ == "__main__":
    from gevent import monkey
    monkey.patch_all()
    sio_server = SocketIOServer(
    ('', 8080), chat, 
    policy_server=False)
    t2 = threading.Thread(target=sio_server.serve_forever())
    t2.start()

当我最终放弃并使用 ctrl-C 时,我看到以下堆栈跟踪,这让我相信我的线程方式是阻塞的。

Traceback (most recent call last):
  File "socketio_test.py", line 92, in <module>
    t2 = threading.Thread(target=sio_server.serve_forever())
  File "/Users/andrewscott/Desktop/wham/pycli/wham/lib/python2.7/site-packages/gevent/baseserver.py", line 284, in serve_forever
    self._stop_event.wait()
  File "/Users/andrewscott/Desktop/wham/pycli/wham/lib/python2.7/site-packages/gevent/event.py", line 77, in wait
    result = self.hub.switch()
  File "/Users/andrewscott/Desktop/wham/pycli/wham/lib/python2.7/site-packages/gevent/hub.py", line 338, in switch
    return greenlet.switch(self)
KeyboardInterrupt

如果有人知道如何将 irc 进程更改为非阻塞,或者任何一般性建议,他们将不胜感激。

4

1 回答 1

0

您应该删除呼叫:

t2 = threading.Thread(target=sio_server.serve_forever())

并正确传递方法:

t2 = threading.Thread(target=sio_server.serve_forever)
于 2015-10-28T03:31:18.490 回答