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

发布于 2024-11-26 20:18:30 字数 1903 浏览 2 评论 0原文

所以我的问题是,如果有 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)

So my question is, how would i get my bot to listen if there is a PING and if there's no ping in an interval of a minute, it will react as though the connection has been lost. How would one go about doing that?

EDIT:

This is the working code for registering the connection fallout (although having trouble with reconnecting):

#!/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)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

感性不性感 2024-12-03 20:18:31
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 循环。您不需要 whileconnected==True:,只需 whileconnected: 做同样的事情。

另外,请考虑使用 connection 而不是 Connection,Python 约定仅对类使用大写名称。

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

This will record the time each time it gets a ping, and if it goes too long without one, break out of the connected loop. You don't need while connected == True:, just while connected: does the same thing.

Also, consider using connection instead of Connection, it's the Python convention to use capitalized names only for classes.

初见终念 2024-12-03 20:18:31

只要您的连接仍然有效,就没有理由执行任何花哨的“超时”技巧。如果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 序列,您不会总是获得一个完整的消息同时;你可能会得到一行的一半,或者三行,或者三行半。

There's no reason to do any fancy 'timeout' tricks as long as your connection is still up. If the length of the data returned from recv is 0, the TCP connection has been closed.

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

I suspect that recv() can also throw an exception if the connection is not terminated cleanly.

Edit:

I'm not sure what you're trying to accomplish. The IRC server will send you a PING occasionally. If you don't respond with a PONG, then the server will disconnect you. When the server disconnects you, then your recv() call will return a 0-length string.

All you have to do is respond to PING when you get it, and handle if the connection happens to close.

Your logic should look something like this:

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.

Another thing to keep in mind is that you need to buffer any received data until you get a \r\n sequence, you will not always get a exactly one complete message at the same time; you might get half of one, or three, or three and a half lines.

给不了的爱 2024-12-03 20:18:31

您不应使用 data.find('PING'),因为它还会在其他消息中查找“PING”。然后你发送了一个不正确的 PONG...

而是尝试这样的事情:

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

You should not use data.find('PING') because it also finds "PING" in other messages. And then you send an incorrect PONG...

Instead try something like that:

if data[0:4] == "PING":
    irc.send("PONG " + data.split()[1] + "\n")
没有你我更好 2024-12-03 20:18:31

重新连接时遇到问题的原因是,一旦重新连接,就没有循环可侦听传入数据,并且很可能会出现 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”类型命令来关闭套接字和应用程序...当然,首先是套接字。

The reason why your having issues reconnecting is because once you do there's no loop to listen to for incoming data once you do, and you'd most likely ping timeout. The connection while loop should look like:

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

Now when the connection times out you reconnect and begin to listen for incoming data.

NOTE: Now that there's no way for the application to terminate on it's on you have to either [Ctrl]+[C] in the command line, or construct a "!quit" type command to close the socket and the application... socket first, of course.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文