我的IRC机器人不会收到大约一半输入的聊天命令。我在自定义渠道上使用freenode服务器。无论如何我可以改善这个吗?
图:
import sys
import socket
import string
HOST="irc.freenode.net"
PORT=6667
NICK="FedoraCoinBot"
IDENT="CephonBot"
REALNAME="CephonBot"
CHAN="#cephbot"
readbuffer=""
s=socket.socket( )
s.connect((HOST, PORT))
s.send("NICK %s\r\n" % NICK)
s.send("USER %s %s bla :%s\r\n" % (IDENT, HOST, REALNAME))
s.send("JOIN :%s\r\n" % CHAN)
s.send("PRIVMSG %s :%s\r\n" % (CHAN, "Hi! I am a FedoraCoin Bot!"))
s.send("PRIVMSG %s :%s\r\n" % (CHAN, "Designed by Cephon ;)"))
# Loop
while 1:
text=s.recv(2040)
print text
readbuffer=readbuffer+s.recv(1024)
temp=string.split(readbuffer, "\n")
readbuffer=temp.pop( )
if text.find('!help') !=-1:
s.send("PRIVMSG %s :%s\r\n" % (CHAN, "You said help"))
for line in temp:
line=string.rstrip(line)
line=string.split(line)
# Let's make it so that we don't get kicked -.-
if(line[0]=="PING"):
s.send("PONG %s\r\n" % line[1])
答案 0 :(得分:5)
让我们来看看输入处理的一些部分:
text=s.recv(2040)
print text
首先,您会收到一些文字并打印出来。这是您在控制台输出中唯一看到的内容。
readbuffer=readbuffer+s.recv(1024)
接下来,您阅读了更多文本 - 后来从未打印过。所以它不会出现在你的控制台输出中,但是它是唯一考虑用于实际命令解析的文本(你再也不能从上面访问text
)。
temp=string.split(readbuffer, "\n")
你把它分成几行 - 没关系。但要小心,因为您收到了1024个字节,这并不意味着最后行已经是来自服务器的完整响应。它可能会在两者之间中断,所以你应该等到你再收到另一个换行符(即在你读完之前永远不会处理最后一行)。
readbuffer=temp.pop( )
你得到第一行但是把它分配给readbuffer
我认为是包含所有遗留文本的缓冲区?您应该更清楚地了解变量的用途。
if text.find('!help') !=-1:
s.send("PRIVMSG %s :%s\r\n" % (CHAN, "You said help"))
在此,您再次检查text
。因此,只有当!help
恰好位于最初的2040字节时,才会处理它。其中的其他命令将被忽略;此块外的!help
命令也将被忽略。此外,这也将(错误地)处理消息,如“要查看机器人可以做什么,键入!help”等。
for line in temp:
line=string.rstrip(line)
line=string.split(line)
您正在迭代其余行,并修改它们。然后你扔掉了变化。修改line
将不更改temp
列表中的值。
if(line[0]=="PING"):
s.send("PONG %s\r\n" % line[1])
line
将是单行的单个字符串。因此,访问[0]
,第一个字符,永远不会等于四个字符的字符串。
因此,要解决此问题,您应该清理消息解析。您应该始终将新的读取文本附加到同一缓冲区。当你处理一行时,只需从该缓冲区中获取一行(第一行)并处理它。并真正分别处理每一行。像这样:
buffer = ''
while True:
buffer += s.recv(1024)
# are there completed lines we can parse?
if '\n' in buffer:
# only split once, keep the rest of the buffer
line, buffer = buffer.split('\n', 1)
# handle line
if line.startswith('PING'):
s.send('PONG {}\n'.format(line[5:]))
elif line.startswith('PRIVMSG'):
# this is an actual message; parse it, and handle the message
pass
最后,根据我自己的经验,你真的不应该抛出那样的连接命令(NICK
,USER
和JOIN
。许多服务器会在您过早发送它们时忽略它们。而是先等待适当的响应,例如欢迎信息,它会告诉您服务器已准备好接收您的消息。
答案 1 :(得分:0)
你这样做:
text=s.recv(2040)
然后不久:
readbuffer=readbuffer+s.recv(1024)
第一次调用s.recv()将读取奇数编号的消息,而第二次调用s.recv()将读取偶数编号的消息。这就是为什么你只看到一半的消息。除了处理大于读缓冲区的消息时,不要每个循环多次调用s.recv()。