Re: A Gtk2 IRC Chat Client



On Feb 12, 10:06 am, Ben Morrow <b...@xxxxxxxxxxxx> wrote:
Quoth deadpickle <deadpic...@xxxxxxxxx>:

I noticed a few things:
I tested the program using mIRC. I logged into the channel with the
client and under another name with mIRC. Logging in works fine, I can
see the clients nickname in the channel. What the problem seems to be
is when the MOTD is displayed. It seems that only a few lines of the
MOTD are displayed before the 'in' condition is stopped and the
message stops displaying in the terminal window. When I type in mIRC,
a line of the MOTD is displayed in terminal window. The $input
variable seems to be behind the real-time sending of the messages. I'm
not sure how to remove this lag and I'm looking for ideas.

You are reading the filehandle in buffered mode, which is not compatible
with select (which is used by Glib::IO->add_watch). Either switch to
sysread, or push a :unix layer to switch to unbuffered mode.

Ben

Yep your both right. Adding sysread corrected the problem and now I
have another question. I am trying to complete the IRC Client with
giving the user the ability to disconnect and reconnect to the IRC
server. The problem I am encountering is that when the user
disconnects the Glib::IO tries to read from the closed socket. I tried
to undefine the Glib::IO but that hasent work.

#!/usr/local/bin/perl -w

use strict;
use Gtk2 '-init';
use Glib qw/TRUE FALSE/;
use IO::Socket;

#-------------------Global Variables-------------------
my $chat_state = 'Connect';
my $sock;
my $channel;
my $nick;
my $irc;
my $chat_entry;
my $chat_send_sig;
my $chat_textview;
my $chat_button;
my $watch;

#############################################
#specials that will be input by the efault file
$channel = '#GRRUVI';
$nick = 'Lahowetz';
$irc = 'irc.freenode.net';
my $login = $nick;

#############################################

#-------------------Main Loop-------------------
&chat_build;

Gtk2->main;

#-------------------chat Build-------------------
sub chat_build {
my $chat_window = Gtk2::Window->new('toplevel');
$chat_window->set_title('Chat Client');
$chat_window->set_position('center');
$chat_window->set_default_size( 300, 200 );
$chat_window->signal_connect(delete_event=> sub{exit});

my $chat_scroll = Gtk2::ScrolledWindow->new;
$chat_textview = Gtk2::TextView->new;
$chat_entry = Gtk2::Entry->new;
my $chat_vbox = Gtk2::VBox->new;

my $chat_buffer = $chat_textview->get_buffer;
$chat_buffer->create_mark( 'end', $chat_buffer->get_end_iter,
FALSE );
$chat_buffer->signal_connect(insert_text => sub {
$chat_textview->scroll_to_mark( $chat_buffer->get_mark('end'),
0.0, TRUE, 0, 0.5 );
});
$chat_button = Gtk2::Button->new;
$chat_button->set_label($chat_state);

$chat_scroll->add($chat_textview);
$chat_vbox->add($chat_scroll);
$chat_vbox->pack_start( $chat_entry, FALSE, FALSE, 0 );
$chat_vbox->pack_start( $chat_button, FALSE, FALSE, 0 );
$chat_window->add($chat_vbox);

# allows for sending each line with an enter keypress
$chat_send_sig = $chat_entry->signal_connect ('key-press-event' =>
sub {
my ($widget,$event)= @_;
if( $event->keyval() == 65293){ # a return key press
my $text = $chat_entry->get_text;
if(defined $sock){ print $sock "PRIVMSG $channel :$text
\r\n";}
$chat_entry->set_text('');
$chat_entry->set_position(0);
post($nick, $text);
}
});

$chat_entry->signal_handler_block($chat_send_sig); #not connected
yet
$chat_entry->set_editable(0);
$chat_textview->set_editable(0);
$chat_textview->set_cursor_visible(0);

$chat_window->show_all;

$chat_button->signal_connect("clicked" => sub {
if ($chat_state eq 'Connect') {
$chat_button->set_label('Disconnect');
$chat_state='Disconnect';
connecting();
}
else {
$chat_button->set_label('Connect');
$chat_state='Connect';
close $sock;
undef $watch;
}
});

return;
}

#-------------------Connect to IRC Server-------------------
sub connecting {
# Connect to the IRC server.
$sock = new IO::Socket::INET(
PeerAddr => $irc,
PeerPort => 6667,
Proto => 'tcp',
) or die "Can't connect\n";

if (defined $sock){
my $sys_msg = "Connected to $irc ...";
post($nick, $sys_msg);
}

# Log on to the server.
print $sock "NICK $nick\r\n";
print $sock "USER $login 8 * :Just a Tester\r\n";

# Read lines from the server until it tells us we have connected.
while (my $input = <$sock>) {
# Check the numerical responses from the server.
if ($input =~ /004/) {
# We are now logged in.
my $sys_msg = "Logged in to $irc ...";
post($nick, $sys_msg);
print $sock "JOIN $channel\r\n";
$watch = Glib::IO->add_watch( fileno $sock, [qw/in hup
err/], \&incoming_data, $sock );
$chat_entry->set_editable(1);
$chat_entry->grab_focus;
$chat_entry->signal_handler_unblock ($chat_send_sig);
last;
}
elsif ($input =~ /433/) {
my $sys_msg = "Nickname is already in use";
post($nick, $sys_msg);
$chat_state = 'Connect';
$chat_button->set_label($chat_state);
$chat_entry->signal_handler_block($chat_send_sig);
close $sock;
last;
}
}

Gtk2->main_iteration while Gtk2->events_pending;
}

#-------------------Watch for IRC Inputs-------------------
sub incoming_data {
my ( $fd, $condition, $fh ) = @_;

if ( $condition eq 'in' ) {
my $input;
sysread $fh, $input, 1000000;
chop $input;

if ($input =~ /^PING(.*)$/i) {
# We must respond to PINGs to avoid being disconnected.
print $sock "PONG $1\r\n";
}
if ($input =~ m/PRIVMSG\s($channel)/) {
print "$input\n";
my @sender = split(/!/, $input);
my @message = split(/:/, $input);
my $length = length($sender[0]);
my $who = substr($sender[0], 1, $length);
post($who, $message[2]);
}
if ($input =~ m/QUIT/) {
print "$input\n";
my @sender = split(/!/, $input);
my $length = length($sender[0]);
my $who = substr($sender[0], 1, $length);
my $sys_msg = "$who has QUIT!";
post($who, $sys_msg);
}
if ($input =~ m/JOIN/) {
print "$input\n";
my @sender = split(/!/, $input);
my $length = length($sender[0]);
my $who = substr($sender[0], 1, $length);
my $sys_msg = "$who has JOINED $channel!";
post($who, $sys_msg);
}
else {
# Print the raw line received by the bot.
print "$input\n";
}
}
return TRUE;
}

#-------------------Post messages in the Window-------------------
sub post{
my ($name, $msg) = @_;

my $chat_buffer = $chat_textview->get_buffer;
$chat_buffer->insert( $chat_buffer->get_end_iter, "$name: $msg
\n" );
}
.



Relevant Pages

  • threads not executing @ same time
    ... Im writing an irc bot to fetch rss ... work just like a sub. ... print $sock "NICK $nick\r\n"; ... # wait for login to be confirmed ...
    (comp.lang.perl.misc)
  • A Gtk2 IRC Chat Client
    ... I am trying to build a chat client that uses IRC and is built in the ... client connects to a server and joins a channel. ... my $sock; ...
    (comp.lang.perl.misc)
  • Re: Help: Open an URL an keep reading from it, non-blocking
    ... I once wrote a IRC bot using only IO::Socket, that connected to an IRC server, ... logged on and executed command when specific strings were sent from the server. ... # When alarm triggers, ... sub timeout { ...
    (comp.lang.perl.misc)
  • Gtk2 IRC Client Sluggish and not Responsive
    ... I am writing a Gtk2 IRC client and have ... my $sock; ... sub chat_build { ...
    (comp.lang.perl.misc)
  • Re: Messaging alert
    ... a file name and other information thru the client socket to then process ... You only need 1 server. ... append fbuffer($sock) ... # You also need a protocol to transfer the filename. ...
    (comp.lang.tcl)