Python:检查IRC连接是否丢失(PING PONG?)
我想问的是,怎么让我的机器人监听是否有“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 个回答
2
你不应该用 data.find('PING')
,因为它会在其他消息中也找到“PING”。这样你就可能发送错误的 PONG 了...
相反,可以试试下面这样的做法:
if data[0:4] == "PING":
irc.send("PONG " + data.split()[1] + "\n")
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
的序列。你不一定会同时收到一条完整的消息;你可能会收到一半的消息,或者三条,甚至三条半的内容。
6
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”信号的时间,如果过了很长时间没有收到,就会跳出connected
这个循环。你其实不需要写while connected == True:
,只用while connected:
就能达到同样的效果。
另外,建议使用connection
而不是Connection
,因为在Python中,只有类的名字才会用大写字母开头。