2010-03-29 14 views
0

我想讓自己的Jabber機器人,但我遇到了一點麻煩。但是,如果我嘗試更改機器人的存在,那麼看起來您發送給機器人的所有消息都會延遲。爲什麼我必須在註銷之前將多條消息發送到我的Jabber機器人?

我的意思是當我運行腳本時,我改變了存在,所以我可以看到它在線。然後,當我發送一條消息時,在我爲消息設置的回調子例程被調用之前需要三個消息。發送第三條消息並調用聊天子例程後,它仍會處理我發送的第一條消息。

這實際上不會造成太多的問題,除了當我發送消息「註銷」時它已設置爲註銷,並且必須緊接着兩條消息才能註銷。我不確定我需要做些什麼來解決這個問題,但我認爲它與iq數據包有關,因爲我也有一個iq回調集,並且在設置存在之後它會被調用兩次。

這裏是我的源代碼:

 
#!/usr/bin/perl 

use strict; 
use warnings; 

#Libraries 
use Net::Jabber; 
use DBI; 
use DBD::mysql; 

#--------------- Config Vars ----------------- 
# Jabber Client 
my $jbrHostname = "DOMAINNAME"; 
my $jbrUserName = "USERNAME"; 
my $jbrPassword = "PASSWORD"; 
my $jbrResource = "RESOURCE"; 
my $jbrBoss = new Net::Jabber::JID(); 
$jbrBoss->SetJID(userid=>"USERNAME",server=>$jbrHostname); 

# MySQL 
my $dbHostname = "DOMAINNAME"; 
my $dbName = "DATABASENAME"; 
my $dbUserName = "USERNAME"; 
my $dbPassword = "PASSWORD"; 
#--------------- End Config ----------------- 

# connect to the db 
my $dbh = DBI->connect("DBI:mysql:database=$dbName;host=$dbHostname",$dbUserName, $dbPassword, {RaiseError => 1}) or die "Couldn't connect to the database: $!\n"; 

# create a new jabber client and connect to server 
my $jabberBot = Net::Jabber::Client->new(); 
my $status = $jabberBot->Connect(hostname=>$jbrHostname) or die "Cannot connect ($!)\n"; 
my @results = $jabberBot->AuthSend(username=>$jbrUserName,password=>$jbrPassword,resource=>$jbrResource); 

if($results[0] ne "ok") 
{ 
    die "Jabber auth error @results\n"; 
} 

# set jabber bot callbacks 
$jabberBot->SetMessageCallBacks(chat=>\&chat); 
$jabberBot->SetPresenceCallBacks(available=>\&welcome); 
$jabberBot->SetCallBacks(iq=>\&gotIQ); 

$jabberBot->PresenceSend(type=>"available"); 
$jabberBot->Process(1); 

sub welcome 
{ 
    $jabberBot->MessageSend(to=>$jbrBoss->GetJID(),subject=>"",body=>"Hello There!",type=>"chat",priority=>10); 
    &keepItGoing; 
} 

$jabberBot->MessageSend(to=>$jbrBoss->GetJID(),subject=>"",body=>"Hello There! Global...",type=>"chat",priority=>10); 
#$jabberBot->Process(5); 
&keepItGoing; 

sub chat 
{ 
    print "Chat Called!\n"; 
    my ($sessionID,$msg) = @_; 
    $jabberBot->MessageSend(to=>$msg->GetFrom(),subject=>"",body=>"Chatting!",type=>"chat",priority=>10); 
    if($msg->GetBody() ne 'logout') 
    { 
     print $msg->GetBody()."\n"; 
     &keepItGoing; 
    } 
    else 
    { 
     &killBot($msg); 
    } 

} 

sub gotIQ 
{ 
    print $_[1]->GetID()."\n"; 
    &chat; 
} 

sub keepItGoing 
{ 
    print "Movin' the chains!\n"; 
    my $proc = $jabberBot->Process(1); 
    while(defined($proc) && $proc != 1) 
    { 
     $proc = $jabberBot->Process(1); 
    } 
} 

sub killBot 
{ 
    $jabberBot->MessageSend(to=>$_[0]->GetFrom(),subject=>"",body=>"Logging Out!",type=>"chat",priority=>10); 
    $jabberBot->Process(1); 
    $jabberBot->Disconnect(); 
    exit; 
} 

感謝您的幫助!

+0

我有麻煩搞清楚什麼你的標題有你的問題做。 – mob 2010-03-29 03:19:41

+0

我不知道如何使用perl的XMPP模塊。正如我上面所說的那樣,當我改變存在的時候,它所處理的消息似乎被放入一個隊列中,並且它們仍然能夠處理消息#1,理論上它應該處理#3,處理#2當它處理#4時等等。 – cskwrd 2010-03-29 03:31:13

+0

好的,你正在使用XMPP和Perl來完成這項任務。但是,您的消息並未證明XMPP和Perl是問題所在。也許這是因爲你使用'Net :: Jabber'的方式。也許這與緩衝sockethandles或片狀隊列或100其他事情有關。有人可能能夠向您解釋「XMPP模塊如何在perl中工作」(而不是每個其他模塊如何在perl中工作),但我不清楚這會讓您更接近解決您的問題。如何標題「在Jabber響應之前,爲什麼我必須發送我的消息3次?」 – mob 2010-03-29 05:36:22

回答

0

因爲keepItGoing例程,你已經有資源匱乏。一般來說,嘗試像這樣同步使用XMPP是行不通的。我建議讓你的回調設置,然後在一個循環中調用Process()。用於過程()

文檔說:

Process(integer) - takes the timeout period as an argument. If no 
        timeout is listed then the function blocks until 
        a packet is received. Otherwise it waits that 
        number of seconds and then exits so your program 
        can continue doing useful things. NOTE: This is 
        important for GUIs. You need to leave time to 
        process GUI commands even if you are waiting for 
        packets. The following are the possible return 
        values, and what they mean: 

         1 - Status ok, data received. 
         0 - Status ok, no data received. 
        undef - Status not ok, stop processing. 

        IMPORTANT: You need to check the output of every 
        Process. If you get an undef then the connection 
        died and you should behave accordingly. 

每次呼叫處理(),0以上的回調將閃光。你永遠不知道哪一個,因爲它取決於服務器的時間。如果你希望Process()在發送之前返回,那麼你幾乎總是在同步思考,而不是像在XMPP中那樣殺死你。

就你的情況而言,如果你從chat()中刪除keepItGoing的呼叫,我敢打賭事情會更像你期望的。

+0

@Joe Hildebrand:你能否給出或鏈接到你所說的類似例子?我無法想象解決方案。謝謝! – cskwrd 2010-03-30 17:40:34

+0

@Joe Hildebrand:如果我從'chat()'中刪除'keepItGoing',那麼如何讓腳本持續運行,直到發送像「logout?」這樣的消息。我想我對如何讓機器人「閒置」感到困惑,我認爲這就是我通過「keepItGoing」子例程實現的。在實施你的建議後,我的機器人將最終與服務器斷開連接,因爲腳本退出。 – cskwrd 2010-03-31 05:36:23

0

將行:

$jabberBot->Process(1); 

這些:

while (defined($jabberBot->Process(1))) { 
    # Do stuff here 
} 
相關問題