Kirjautuminen

Haku

Tehtävät

Keskustelu: Ohjelmointikysymykset: Python: Ongelma irkissä pysymisen kanssa

Burton [09.03.2010 20:28:43]

#

Kirjoittelen Pythonilla erään aikaisemman keskustelun innoittamana pientä IRC-bottia lähinnä tutkiakseni, miten irkki käyttäytyy ohjelmoijan käsittelyssä. Loistavan alun ja RFC:n lukemisen jälkeen en kuitenkaan saa bottiani pysymään irkissä kovin kauaa. Connectaaminen onnistuu aivan normaalisti, vaikka serveriltä tuleekin pari "register first"-viestiä, mutta muutaman minuutin kuluttua kanavalle joinimisesta botti putoaa Ping timeout -viestin saattelemana.

Päättelin viestistä, että ongelma on PING-pyyntöön vastaamisessa. Mutta mielestäni olen hoitanut asian aivan oikein, sillä palvelimelle yhdistäessä botti vastaa aivan oikein PING :numerosarja -viestiin (PONG :numerosarja). Botti ei edes tulosta viestiä uudesta PING-pyynnöstä kanavalle liittymisen jälkeen.

Ohjelma pyörii yhdistämisen jälkeen ikuisessa silmukassa vastaanottaen viestejä palvelimelta muodossa viesti = str(irc.recv(4096)), minkä jälkeen viesti-muuttuja tulostetaan. Kun botti on pudonnut, ohjelma pyörii silmukassa ilman mitään viestiä tai reaktiota yhteyttä koskien.

Mikä voisi olla vikana?

jmp [09.03.2010 21:15:12]

#

Jos palvelimelta ei tule muita PING-pyyntöjä, niin kuulostaa siltä, että ensimmäinen PONG-viesti ei mene perille. Päättyyhän PONG-viesti varmasti merkkeihin \r\n? Toinen vaihtoehto saattaisi olla, että viesti menee perille, mutta kun botille tulee toinen PING-pyyntö, se ei parsi palvelimelta tulevaa dataa oikein ja lopulta tippuu irkistä. Vaikea sanoa ilman koodia.

Burton [09.03.2010 21:48:40]

#

Loppuu merkkeihin \r\n. Koko PING-hommeli epäilyttää minua, sillä botti ei missään vaiheessa yhdistämisen jälkeen ilmoita uudesta PING-pyynnöstä.

Tässä hieman koodia.

# yhdistetään palvelimelle
irc = socket.socket()
irc.connect((server, port))

irc.send('NICK '+nick+'\r\nUSER '+user+' "" '+server+' :'+real_name+'\r\n')

...

while 1:
    viesti = str(irc.recv(4096))
    print viesti

    if viesti.find("PING") != -1:
        vList = teksti.split() # en tykkää käyttää merkkijonoja
        pingNumero = ""

        for a in range(len(vList)):
            if vList[a] == 'PING':
                pingNumero = str(vList[a + 1]) # PING-pyyntö saapuu muodossa PING :numerosarja
                break
        irc.send("PONG " + pingNumero + "\r\n")
        print "PONG " + pingNumero + "\r\n"

Siinä oleelliset kohdat.

Vielä ohjelman tuloste:

NOTICE AUTH :*** Looking up your hostname

NOTICE AUTH :*** Checking Ident
NOTICE AUTH :*** Found your hostname
PING :1851782901

PONG :1851782901

:xs4all.nl.quakenet.org 451 NIMIMERKKI NIMIMERKKI :Register first.

:xs4all.nl.quakenet.org 451 NIMIMERKKI NIMIMERKKI :Register first.

:xs4all.nl.quakenet.org 451 NIMIMERKKI NIMIMERKKI :Register first.

:xs4all.nl.quakenet.org 451 NIMIMERKKI NIMIMERKKI :Register first.

:xs4all.nl.quakenet.org 451 NIMIMERKKI NIMIMERKKI :Register first.

:xs4all.nl.quakenet.org 451 NIMIMERKKI NIMIMERKKI :Register first.

NOTICE AUTH :*** No ident response

***QUAKENETIN Message of the Day YNM.***

:xs4all.nl.quakenet.org NOTICE NIMIMERKKI :on 3 ca 1(4) ft 20(20)
:xs4all.nl.quakenet.org 221 NIMIMERKKI +i
:*** MODE NIMIMERKKI +i
:*** JOIN #KANAVA
:xs4all.nl.quakenet.org 353 NIMIMERKKI = #KANAVA :NIMIMERKKEJÄ
:xs4all.nl.quakenet.org 366 NIMIMERKKI #KANAVA :End of /NAMES list.

Tämän jälkeen ohjelma ei tulosta enää mitään, ellei joku puhu #KANAVAlla.

Metabolix [09.03.2010 22:15:44]

#

Kannattaa pitää mielessä, että recv ei suinkaan aina palauta kokonaista riviä: dataa saattaa tulla kerralla enemmän tai vähemmän. Tämän voi huomioida kokoamalla dataa puskuriin ja käsittelemällä vain kokonaiset rivit:

puskuri = ""
while jotain:
  puskuri += yhteys.recv(4096)
  rivit = puskuri.split("\r\n")
  puskuri = rivit.pop()
  for rivi in rivit:
    # Tulkitse ja käsittele rivi.

Tämä ei ilmeisesti kuitenkaan ole ongelmasi, koska koodisi pitäisi tulostaa kaikki liikkuvat viestit.

Burton [09.03.2010 23:49:48]

#

Metabolix kirjoitti:

Kannattaa pitää mielessä, että recv ei suinkaan aina palauta kokonaista riviä: dataa saattaa tulla kerralla enemmän tai vähemmän.

Juu, huomasin. Sen takia PING-pyyntöön vastaaminen käsitellään koodissani niin hankalasti listojen kautta.

EDIT: No kylläpä on omituinen juttu! Kävin kaverin luona kokeilemassa bottiani ja kuin taikaiskusta se toimi moiteettomasti. Mistäköhän tämäkin johtuu... Järjestelmässäni on jotain vikaa ilmeisesti.

mylvari [10.03.2010 16:17:14]

#

Ircin kanssa pelatessa on jokin Wiresharkin kaltainen ohjelma erittäin käytännöllinen, sillä kun saa tutkittua mitä dataa liikkuu serverin ja oman koneen välillä.
Useimmat IRC serverit käyttävät tcp porttia 6667 jolloin wiresharkille kannattaa antaa filtteri "tcp.port==6667", näin muu liikenne ei häiritse tutkimuksia.

Vastaus

Aihe on jo aika vanha, joten et voi enää vastata siihen.

Tietoa sivustosta