我有一个IRC客户端,可以在套接字上接收消息。
从这个客户端我创建了几个机器人,可以在抽搐时连接到其他人的聊天频道。 (这些是授权的,而不是垃圾邮件机器人!)。
每个机器人都在一个单独的线程中创建,该线程获取通道名称以及一些其他参数。
我的问题是我的IRC套接字只能绑定到一个端口,它处理所有IRC消息,每条消息都有一个#channel字符串作为第三个字符串,将其指向特定通道。这些消息可以在每个机器人内部处理,因为每个机器人都知道其频道的名称。
我的问题是;如何将通过套接字接收的字符串发送到多个线程?
import time
import socket
import threading
import string
import sys
import os
class IRCBetBot:
#irc ref
irc = None
def __init__(self,IRCRef,playerName,channelName,currencyName):
#assign variables
self.irc = IRCRef
self.channel = '#' + channelName
self.irc.send(('JOIN ' + self.channel + '\r\n') .encode("utf8"))
#create readbuffer to hold strings from IRC
readbuffer = ""
# This is the main loop
while 1:
##readbuffer## <- need to send message from IRC to this variable
for line in temp:
line=str.rstrip(line)
line=str.split(line)
if (len(line) >= 4) and ("PRIVMSG" == line[1]) and (self.channel == line[2]) and not ("jtv" in line[0]):
#call function to handle user message
if(line[0]=="PING"):
self.irc.send(("PONG %s\r\n" % line[0]).encode("utf8"))
def runAsThread(ircref,userName, channelName, currencyPrefix):
print("Got to runAsThread with : " + str(userName) + " " + str(channelName) + " " + str(currencyPrefix))
IRCBetBot(ircref,userName,channelName,currencyPrefix)
# Here we create the IRC connection
#IRC connection variables
nick = 'mybot' #alter this value with the username used to connect to IRC eg: "username".
password = "oauth:mykey" #alter this value with the password used to connect to IRC from the username above.
server = 'irc.twitch.tv'
port = 6667
#create IRC socket
irc = socket.socket()
irc.connect((server, port))
#sends variables for connection to twitch chat
irc.send(('PASS ' + password + '\r\n').encode("utf8"))
irc.send(('USER ' + nick + '\r\n').encode("utf8"))
irc.send(('NICK ' + nick + '\r\n').encode("utf8"))
# Array to hold all the new threads
threads = []
# authorised Channels loaded from file in real program
authorisedChannels = [["user1","#channel1","coin1"],["user2","#channel2","coin2"],["user3","#channel3","coin3"]]
for item in authorisedChannels:
try:
userName = item[0]
channelName = item[1]
currencyPrefix = item [2]
myTuple = (irc,userName,channelName,currencyPrefix)
thread = threading.Thread(target=runAsThread,args = myTuple,)
thread.start()
threads.append(thread)
time.sleep(5) # wait to avoid too many connections to IRC at once from same IP
except Exception as e:
print("An error occurred while creating threads.")
print(str(e))
#create readbuffer to hold strings from IRC
readbuffer = ""
# This is the main loop
while 1:
readbuffer= readbuffer+self.irc.recv(1024).decode("utf-8")
temp=str.split(readbuffer, "\n")
readbuffer=temp.pop( )
#
#Need to send readbuffer to each IRCBetBot() created in runAsThread that contains a while 1: loop to listen for strings in its __init__() method.
#
print ("Waiting...")
for thread in threads:
thread.join()
print ("Complete.")
我需要以某种方式将readbuffer从主循环中获取到在单独的线程中创建的每个IRCBetBot对象中?有什么想法吗?
答案 0 :(得分:1)
这是一个示例,说明如何使用每个线程的队列来执行此操作。我们不是仅仅创建一个线程列表,而是创建一个以通道为键的线程的dict,并存储线程对象和可用于与dict中的线程通信的队列。
#!/usr/bin/python3
import threading
from queue import Queue
class IRCBetBot(threading.Thread):
def __init__(self, q, playerName, channelName, currencyName):
super().__init__()
self.channel = channelName
self.playerName = playerName
self.currencyName = currencyName
self.queue = q
def run(self):
readbuffer = ""
while 1:
readbuffer = self.queue.get() # This will block until a message is sent to the queue.
print("{} got msg {}".format(self.channel, readbuffer))
if __name__ == "__main__":
authorisedChannels = [["user1","#channel1","coin1"],
["user2","#channel2","coin2"],
["user3","#channel3","coin3"]]
threads = {}
for item in authorisedChannels:
try:
userName = item[0]
channelName = item[1]
currencyPrefix = item [2]
myTuple = (userName,channelName,currencyPrefix)
q = Queue()
thread = IRCBetBot(q, *myTuple )
thread.start()
threads[channelName] = (q, thread)
except Exception as e:
print("An error occurred while creating threads.")
print(str(e))
while 1:
a = input("Input your message (channel: msg): ")
channel, msg = a.split(":")
threads[channel][0].put(msg) # Sends a message using the queue object
正如您所看到的,当消息进入套接字时,我们解析出通道(您的代码已经执行了),然后将消息传递到我们的线程字典中的相应队列。
示例输出(略微调整,因此输出不会因并发的print
调用而被加扰):
dan@dantop:~$ ./test.py
Input your message (channel: msg): #channel1: hi there
#channel1 got msg hi there
Input your message (channel: msg): #channel2: another one
#channel2 got msg another one
答案 1 :(得分:0)
一种方法是使一个类似于线程数组的readBuffers数组。然后每个线程基本上都在等待它的特定readbuffer上的数据。
当您获取数据时,您可以将其传递给您感兴趣的线程,或者只是将数据复制到所有读取缓冲区,并让线程处理它们,如果他们感兴趣的话。在这种情况下,观察者模式最有效。