I'm finally getting it (I'm a little slow). Here is a Gtk2 script that loads the client GUI and asks for a username. But I have ran into a problem, I receive this error: *** unhandled exception in callback:
*** Undefined subroutine &main:: called at chat-client.pl line 54.
*** ignoring at chat-client.pl line 54. This error seems to stem from the wait_for_msg timer that I have added and the error references the Gtk2->main loop. When the timer is commented out the program works fine. What can I do.
#!/usr/bin/perl
use warnings;
use strict;
use Gtk2 -init;
use Glib qw/TRUE FALSE/;
use IO::Socket::INET;
use Tie::RefHash;
use IO::Select;
#global variables
my $buffer;
my $host = "Deadpickle-hobo";
my $port = 6666;
my $conn_stat = 'idle';
my %inbuffer = ();
my %outbuffer = ();
my %ready = ();
my $select;
#my $timer_waiting = Glib::Timeout->add(100, wait_for_msg());
#the main chat widget
my $main_window = Gtk2::Window->new("toplevel");
$main_window->signal_connect(delete_event => sub {Gtk2->main_quit;});
$main_window->set_default_size(250, 200);
my $table = Gtk2::Table->new(4, 2, FALSE);
$buffer = Gtk2::TextBuffer->new;
my $button = Gtk2::Button->new("Send");
my $entry = Gtk2::Entry->new();
my $label = Gtk2::Label->new("Chat Client Test");
my $textview = Gtk2::TextView->new_with_buffer($buffer);
$textview->set_cursor_visible (FALSE);
my $swindow = Gtk2::ScrolledWindow->new( undef, undef);
$swindow->set_policy( 'automatic', 'automatic');
$swindow->set_shadow_type( 'etched-out');
$swindow->add( $textview);
$table->attach_defaults($label, 0, 1, 0, 1);
$table->attach_defaults($swindow, 0, 2, 1, 3);
$table->attach_defaults($entry, 0, 1, 3, 4);
$table->attach_defaults($button, 1, 2, 3, 4);
$main_window->add($table);
$main_window->show_all();
#run the login dialog
dialog($buffer);
Gtk2->main;
#-------------------Login Dialog-------------------
sub dialog{
my $buffer = shift;
my $dialog_window = Gtk2::Window->new('toplevel');
$dialog_window->signal_connect(delete_event => sub {Gtk2->main_quit}
+);
my $dialog_table = Gtk2::Table->new(2, 2, FALSE);
my $dialog_label1 = Gtk2::Label->new('Chat Login:');
my $dialog_label2 = Gtk2::Label->new('User:');
my $dialog_label3 = Gtk2::Label->new('Host:');
my $chat_user = Gtk2::Entry->new();
$chat_user->set_text('');
my $server_user = Gtk2::Entry->new();
$server_user->set_text('uas');
my $host = Gtk2::Entry->new();
$host->set_text('updraft.unl.edu');
my $dialog_button1 = Gtk2::Button->new('Connect');
$dialog_table->attach_defaults($dialog_label1, 0, 1, 0, 1);
$dialog_table->attach_defaults($chat_user, 1, 2, 0, 1);
$dialog_table->attach_defaults($dialog_button1, 1, 2, 1, 2);
$dialog_button1->signal_connect("clicked" => sub {my $tag = $chat_us
+er->get_text; $dialog_window->destroy; $buffer->insert(($buffer->get_
+end_iter), "Username: $tag...\n"); connect_server()});
$dialog_window->add($dialog_table);
$dialog_window->show_all;
return 1;
}
#------------------Connect to server---------------------
#establishes connection to the server
sub connect_server{
if ($conn_stat ne 'connected') {
$buffer->insert(($buffer->get_end_iter), "Connecting to Server $ho
+st:$port...\n");
my $conn = IO::Socket::INET->new(PeerAddr => $host, PeerPort => $p
+ort, Proto => 'tcp') or popup_err(1);
if ($conn) {
%inbuffer = ();
%outbuffer = ();
%ready = ();
tie %ready, 'Tie::RefHash';
nonblock($conn);
$select = IO::Select->new($conn);
$conn_stat = 'connected';
$buffer->insert(($buffer->get_end_iter), "Connected!\n");
#my $timer_waiting = Glib::Timeout->add(100, wait_for_msg());
}
}
}
#-------------------Error popup-------------------
# pops up an error message
sub popup_err{
my ($error_code) = @_;
my $error;
if ($error_code == 1) {$error = "Cannot create Socket!"};
$buffer->insert(($buffer->get_end_iter), "$error\n");
my $error_dialog = Gtk2::MessageDialog->new($main_window, 'destroy-w
+ith-parent', 'error', 'ok', "$error");
$error_dialog->run;
$error_dialog->destroy;
}
#-------------------blocking-------------------
# nonblock($socket) puts socket into nonblocking mode
sub nonblock {
my $socket = shift;
$socket->blocking(0);
}
#-------------------Message Waiting-------------------
# Wait for incoming messages from the server relayed from clients
sub wait_for_msg {
if ($conn_stat eq 'connected') {
my ($list_size, $msg);
my $server;
my $rv;
my $data;
# check for new information on the connections we have
# anything to read or accept?
foreach $server ($select->can_read(1)) {
# read data
$data = '';
$rv = $server->recv($data, 'POSIX::BUFSIZ', 0);
unless (defined($rv) && length $data) {
# This would be the end of file, so close the client
delete $inbuffer{$server};
delete $outbuffer{$server};
delete $ready{$server};
$select->remove($server);
close $server;
next;
}
$inbuffer{$server} .= $data;
# test whether the data in the buffer or the data we
# just read means there is a complete request waiting
# to be fulfilled. If there is, set $ready{$client}
# to the requests waiting to be fulfilled.
while ($inbuffer{$server} =~ s/(.*\n)//) {
push( @{$ready{$server}}, $1 );
}
}
# Any complete requests to process?
foreach $server (keys %ready) {
handle($server);
}
}
}
UPDATE: I accidentally clipped the use references. |