Python:检查IRC连接是否丢失(PING PONG?)

时间:2011-07-28 01:05:21

标签: python irc

所以我的问题是,如果有一个PING我怎么能让我的机器人听,如果在一分钟的时间间隔内没有ping,它会像连接丢失一样反应。怎么会这样做呢?

编辑:

这是用于注册连接余量的工作代码(虽然重新连接有问题):

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

import sys
import socket
import string
import os
import platform
import time

# Variables
HOST = "irc.channel.net"
PORT = 6667
NICK = "Botname"
IDENT = "Botname"
REALNAME = os.getenv('USER')
CHAN = "##ChannelName"
readbuffer = ""

# Our IRC connection
irc = socket.socket()
irc.settimeout(300)
connected = False
def connection(host, port, nick, ident, realname, chan):
    while connected is False:
        try:
            irc.connect((host, port))
            irc.send("NICK %s\r\n" % nick)
            irc.send("USER %s %s bla :%s\r\n" % (ident, host, realname))
            irc.send("JOIN :%s\r\n" % chan)
            # Initial msg to send when bot connects
            irc.send("PRIVMSG %s :%s\r\n" % (chan, "TehBot: "+ nick + " Realname: " + realname + " ."))
            global connected
            connected = True
        except socket.error:
            print "Attempting to connect..."
            time.sleep(5)
            continue
connection(HOST, PORT, NICK, IDENT, REALNAME, CHAN)

while connected:
    try:
        data = irc.recv ( 4096 )
        # If connection is lost
        if len(data) == 0:
            break
        print data
        # If Nick is in use
        if data.find ( "Nickname is already in use" ) != -1:
            NICK = NICK + str(time.time())
            connection(HOST, PORT, NICK, IDENT, REALNAME, CHAN)
        # Ping Pong so we don't get disconnected
        if data[0:4] == "PING":
            irc.send ( "PONG " + data.split() [ 1 ] + "\r\n" )
    except socket.timeout:
        global connected
        connected = False
        print connected
        break
print "Out of loop"
connection(HOST, PORT, NICK, IDENT, REALNAME, CHAN)

4 个答案:

答案 0 :(得分:5)

last_ping = time.time()
threshold = 5 * 60 # five minutes, make this whatever you want
while connected:
    data = irc.recv ( 4096 )
    # If Nick is in use
    if data.find ( 'Nickname is already in use' ) != -1:
        NICK = NICK + str(time.time())
        Connection()
    # Ping Pong so we don't get disconnected
    if data.find ( 'PING' ) != -1:
        irc.send ( 'PONG ' + data.split() [ 1 ] + '\r\n' )
        last_ping = time.time()
    if (time.time() - last_ping) > threshold:
        break

这将记录每次ping时的时间,如果没有ping的时间太长,则会跳出connected循环。您不需要while connected == True:,只需while connected:做同样的事情。

另外,考虑使用connection而不是Connection,Python的约定只是为类使用大写名称。

答案 1 :(得分:3)

只要您的连接仍然存在,就没有理由做任何花哨的'超时'技巧。如果从recv返回的数据长度为0,则TCP连接已关闭。

data = irc.recv(4096)
if len(data) == 0:
    # connection closed
    pass

我怀疑如果连接没有干净地终止,recv()也会抛出异常。

修改

我不确定你要完成什么。 IRC服务器偶尔会向您发送PING。如果您没有使用PONG回复,则服务器将断开您的连接。当服务器断开连接时,您的recv()调用将返回一个0长度的字符串。

您需要做的就是在获得时回复PING,并在连接关闭时进行处理。

你的逻辑应该是这样的:

keep_trying_to_connect = True
while keep_trying_to_connect:
    # try to connect
    irc = socket.socket()
    # send NICK, USER, JOIN here
    # now we're connected and authenticated start your recv() loop
    while True:
        data = irc.recv(4096)
        if len(data) == 0:
            # disconnected, break out of recv loop and try to reconnect
            break
        # otherwise, check what the data was, handling PING, PRIVMSG, etc.

要记住的另一件事是你需要缓冲任何收到的数据,直到你得到一个\r\n序列,你不会总是同时获得一个完整的消息;你可能得到一半,三,或三等半。

答案 2 :(得分:2)

您不应该使用data.find('PING'),因为它还会在其他消息中找到“PING”。然后你发错了PONG ......

而是尝试这样的事情:

if data[0:4] == "PING":
    irc.send("PONG " + data.split()[1] + "\n")

答案 3 :(得分:0)

你遇到重新连接问题的原因是,一旦你这样做就没有循环来监听传入数据,你很可能ping超时。连接while循环应如下所示:

while connected:
    try:
        ...
    except socket.timeout:
        global connected
        connected = False
        print connected
        connection(HOST, PORT, NICK, IDENT, REALNAME, CHAN)
        continue
print "Out of loop"

现在,当连接超时时,您重新连接并开始侦听传入数据。

注意:既然应用程序没有办法在它上面终止,你必须在命令行中使用[Ctrl] + [C],或者构造一个“!quit”类型命令来关闭套接字和应用程序......首先是套接字。