Päässäni on pyörinyt jo muutaman kuukauden ajan ajatus tehdä IRC-botti. Nyt kun sille tuli oikea tarve niin se motivoi vielä enemmän ja päätin sitten aloittaa.
Botin täytyisi tukea useaa verkkoa, eli sen pitäisi pystyä olla yhteydessä moneen eri serveriin samanaikaisesti. Olen nyt toteuttanut tämän siten, että jokaisesta serveristä luodaan uusi thread. Se toimii hyvin, mutta onko uuden threadin luomien jokaisesta serveristä järkevää/kannattavaa? Miten asian voisi tarvittaessa toteuttaa toisin?
Threadien ohjelmoinnista minulle ei ole kokemusta juuri lainkaan, mutta olen havainnut, että tässä tilanteessa ne toimisivat oikein näppärästi (en vain viitsi käyttää niitä jos botti rupeaa syömään konetehoja kun ollaan yhteydessä useaan serveriin).
Lukaseppa läpi IRC-protokollan RFC niin voit toteuttaa tämän kirjoittamalla suoraan sockettiin. Oma toteutukseni on python-pohjainen. Botin rakenne on yksinkertainen. Ensin valmistellaan socketit, sitten silmukalla tutkitaan niiden sisältöä ja suoritetaan tarvittavat toimenpiteet.
Pilkki kirjoitti:
Lukaseppa läpi IRC-protokollan RFC niin voit toteuttaa tämän kirjoittamalla suoraan sockettiin. Oma toteutukseni on python-pohjainen. Botin rakenne on yksinkertainen.
Olen toki IRC:n RFC:n lukenut läpi jo, silmäilin sitä myös uudestaan nyt pikaisesti kun tuo kuulosti mielestäni oudolta. Voitko selventää mitä tarkoitat kirjoittamisella suoraan sockettiin?
Pilkki kirjoitti:
Ensin valmistellaan socketit, sitten silmukalla tutkitaan niiden sisältöä ja suoritetaan tarvittavat toimenpiteet.
Näin minunkin botti tällä hetkellä tekee, sillä poikkeuksella tosin, että silmukkaa pyöritetään threadissa verkkoa kohden.
Esimerkiksi PircBotin IRC API:ssa lukee näin:
http://www2.sys-con.com/itsg/virtualcd/java/archives/0812/
Many people ask (without thinking) whether PircBot supports multiple servers. The answer is yes, of course. This is achieved simply by creating a new instance of PircBot for each server that you wish to connect to.
Ehkä threadien luomien per verkko ei olekaan niin huono ratkaisu...
Väittäisin että bottisi ei tule olemaan niin monessa verkossa, että säikeitten määrästä olisi jotain haittaa.
Toisaalta, sen voi myöskin kääntää niin, ettei siitä tule mitään merkittävää hyötyäkään, koska moniytimiset prossut on muutenki tarpeeksi tehokkaita pyörittämään vaikka millasta bottia. En tosin tiedä miten moneen verkkoon yhdistäminen ilman säikeitä onnistuu / kuinka helposti.
Mutta nyt kun miettii, niin jos botin tekee toimimaan yhdessä verkossa, ja lisää siihen vaan threadit, niin sehnä toimii monessa verkossa samaan aikaan, joten luultavasti paras ratkasu käyttää threadeja, vaikkei niissä _teholtaan_ juuri mitään etua saakkaan.
Periaatteessa se, että luot uuden säikeen per yhteys on melkein sama kuin se että käynnistät jokaista serveriä varten oman botin.
Voit aivan hyvin hoitaa kaikkia yhteyksiä samassa säikeessä. Sinun täytyy vain dataa vastaanottaessasi ensin tarkistaa, onko dataa, ja vastaanottaa vain, jos on.
Ohjelman perusrakenne olisi siis tällainen:
kun ohjelma on käynnissä: jokaiselle yhteydelle: jos on dataa: lue data ja reagoi tee muut toiminnot (mm. ajastetut tapahtumat) nuku hetki ennen seuraavaa kierrosta
Tähän väliin pakollinen mainos:
http://quadcore.homeunix.net/trac_h2/
Tekee juurikin sen mitä Trilog pohtii ja hieman muutakin.
Metabolix kirjoitti:
Voit aivan hyvin hoitaa kaikkia yhteyksiä samassa säikeessä. Sinun täytyy vain dataa vastaanottaessasi ensin tarkistaa, onko dataa, ja vastaanottaa vain, jos on.
Erittäin mahtava vinkki, kiitos siitä. Sain toimimaan tuon esittämälläsi tavalla yhdessä säikeessä ja myös pari ongelmaa, jotka oli säikeiden kanssa jouduttu tekemään monimutkaisesti, poistui.
Ainut vain, että uusi ongelma tuli mieleeni. Jos emme odota dataa saapuvaksi eksplisiittisesti (emme voi tietää, milloin serveri lähettää dataa) ja nukumme silmukan lopussa niin osa datasta voi jäädä pois (kuten jo testailussani kävikin). Onko tähän ongelmaan vielä jotakin kätevää kikkaa?
Jos pythonilla teet, niin heitäpä googleen sellainen taikasana kuin irclib, sen kanssa ei tarvitse yhteyksistä ja niiden ylläpidosta välittää tuon taivaallista.
trilog kirjoitti:
Jos – – nukumme silmukan lopussa niin osa datasta voi jäädä pois – –
Tämäpä kuulostaa omituiselta. Minun tuntemissani socket-järjestelmissä data pysyy odottamassa, kunnes se luetaan. Näin näyttäisi myös Pythonin kanssa olevan.
Tässä ovat olennaiset osat Python-koodista, jolla testasin menetelmän toimivaksi. Joudut tästä korjaamaan rivinvaihdon \r\n:ksi IRC-protokollan mukaan ja tietenkin kääntämään koodin käyttämällesi kielelle; itse koodasin Pythonin kolmosversiolla, kun siinä ovat niin mukavasti string
ja bytes
eri tyyppejä. :)
# Säädetään blokkaus pois päältä. s.setblocking(0) # Alustetaan vastaanotettu data tyhjäksi ja silmukka käyntiin. buf = b"" loop = True while loop: time.sleep(1) # Haetaan kaikki mahdollinen data puskurin jatkoksi. while True: try: buf = buf + s.recv(4096) except socket.error as msg: # Data loppui. break # Jaetaan puskuri rivinvaihtojen kohdalta; IRCissä tietenkin b"\r\n". lines = buf.split(b"\n") # Laitetaan viimeinen (keskeneräinen tai tyhjä) rivi takaisin puskuriin. buf = lines.pop() # Käsitellään saadut rivit järjestyksessä. for str in lines: str = str.decode() print(str) if str == "exit": loop = False lines = None
Edit. Antti toivottavasti joskus lisää Python-väritykseen tuen tabulaattoreille.
Metabolix kirjoitti:
Minun tuntemissani socket-järjestelmissä data pysyy odottamassa, kunnes se luetaan.
Jep, bugihan siellä oli. Kiitos vielä rautalangasta. :)
Aihe on jo aika vanha, joten et voi enää vastata siihen.