Re: Chat client/server print failed



THanks alot, those scripts are very simple compared to that confusing
script I was trying to write. What I am trying to do is send the user
name to the server so that it can be added to the client list. I dont
quit get how to do this and could use some help.

The client:
#!/usr/bin/perl
use warnings;
use strict;
use Glib qw(TRUE FALSE);
use Gtk2 -init;
use IO::Socket;

#-------------------Global variables-------------------

my $host = 'Deadpickle-hobo';
my $port = 12345;
my $socket;
my $user;

#-------------------Main Window-------------------

my $window = Gtk2::Window->new;
$window->signal_connect( delete_event => sub { exit } );
$window->set_default_size( 300, 200 );

my $vbox = Gtk2::VBox->new;
$window->add($vbox);

my $scroller = Gtk2::ScrolledWindow->new;
$vbox->add($scroller);
my $textview = Gtk2::TextView->new;
$textview ->set_editable (0);
$textview ->can_focus(0);
my $buffer = $textview->get_buffer;
$buffer->create_mark( 'end', $buffer->get_end_iter, FALSE );
$buffer->signal_connect(insert_text => sub {
$textview->scroll_to_mark( $buffer->get_mark('end'), 0.0,
TRUE, 0, 0.5 );
});

$scroller->add($textview);

my $entry = Gtk2::Entry->new();

$vbox->pack_start( $entry, FALSE, FALSE, 0 );
$vbox->set_focus_child ($entry); # keeps cursor in entry
$window->set_focus_child ($entry); # keeps cursor in entry

# allows for sending each line with an enter keypress
my $send_sig = $entry->signal_connect ('key-press-event' => sub {
my ($widget,$event)= @_;
if( $event->keyval() == 65293){ # a return key press
my $text = $entry->get_text;
if(defined $socket){ print $socket $user.'->'. $text,
"\n";}
$entry->set_text('');
$entry->set_position(0);
}
});

#If you store the ID returned by signal_connect, you can temporarily
#block your signal handler with
# $object->signal_handler_block ($handler_id)
# and unblock it again when you're done with
## $object->signal_handler_unblock ($handler_id).

# we want to block/unblock the enter keypress depending
# on the state of the socket
$entry->signal_handler_block($send_sig); #not connected yet
$entry->set_editable(0);

$window->show_all;

#start the dialog window
dialog();
Gtk2->main;
exit;

#-------------------Login Dialog-------------------

sub dialog{

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 $chat_user = Gtk2::Entry->new();
$chat_user->set_text('');
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);

#connect to the server
$dialog_button1->signal_connect( clicked => sub {
$user = $chat_user->get_text;
$dialog_window->destroy;
init_connect();
});

$dialog_window->add($dialog_table);
$dialog_window->show_all;
return;
}

#------------------Connect to server---------------------

sub init_connect{

$socket = IO::Socket::INET->new(
PeerAddr => $host,
PeerPort => $port,
Proto => 'tcp',
);

if( ! defined $socket){
my $buffer = $textview->get_buffer;
$buffer->insert( $buffer->get_end_iter, "ERROR: Can't
connect to port $port on $host as $user: $!\n" );
return;
}

# install an io watch for this stream and
# return immediately to the main caller, who will return
# immediately to the event loop. the callback will be
# invoked whenever something interesting happens.
Glib::IO->add_watch( fileno $socket, [qw/in hup err/],
\&watch_callback, $socket );

#turn on entry widget
$entry->set_editable(1);
$entry->grab_focus;
$entry->signal_handler_unblock ($send_sig);

#send the username to the server for handling
print $socket "$user\n";

Gtk2->main_iteration while Gtk2->events_pending;
}

#-------------------Watch for Events-------------------

sub watch_callback {

my ( $fd, $condition, $fh ) = @_;

if ( $condition >= 'in' ) {
# there's data available for reading. we have no
# guarantee that all the data is there, just that
# some is there. however, we know that the child
# will be writing full lines, so we'll assume that
# we have lines and will just use <>.
my $data = scalar <$fh>;

if ( defined $data ) {
# do something useful with the text.
my $buffer = $textview->get_buffer;
$buffer->insert( $buffer->get_end_iter, $data );
}
}

if ( $condition >= 'hup' or $condition >= 'err' ) {
# End Of File, Hang UP, or ERRor. that means
# we're finished.

# stop ability to send
$entry->set_editable(0);
$entry->signal_handler_block ($send_sig);

my $buffer = $textview->get_buffer;
$buffer->insert( $buffer->get_end_iter, "Server connection
lost !!\n" );

#close socket
$fh->close;
$fh = undef;

#allow for new connection
#$button->set_label('Connect');
#$button->set_sensitive(1);
#$button->grab_focus;
#Gtk2->main_iteration while Gtk2->events_pending;
}

if ($fh) {
# the file handle is still open, so return TRUE to
# stay installed and be called again.
# print "still connected\n";
# possibly have a "connection alive" indicator
return TRUE;
}

else {
# we're finished with this job. start another one,
# if there are any, and uninstall ourselves.
return FALSE;
}
}

the server:
#!/usr/bin/perl
use warnings;
use strict;
use IO::Socket;
use threads;
use threads::shared;

my $user;

$|++;
print "$$ Server started\n";; # do a "top -p -H $$" to monitor server
threads

our @clients : shared;
@clients = ();

my $server = new IO::Socket::INET(
Timeout => 7200,
Proto => "tcp",
LocalPort => 12345,
Reuse => 1,
Listen => 3
);

while (1) {
my $client;

do {
$client = $server->accept;
} until ( defined($client) );

$server->recv($user, 300);

my $peerhost = $client->peerhost();
print "accepted a client $client, $peerhost, username = $user \n";
my $fileno = fileno $client;
push (@clients, $fileno);
#spawn a thread here for each client
my $thr = threads->new( \&process_it, $client, $fileno,
$peerhost )->detach();
}
# end of main thread

sub process_it {
my ($lclient,$lfileno,$lpeer) = @_; #local client

if($lclient->connected){
# Here you can do your stuff
# I use have the server talk to the client
# via print $client and while(<$lclient>)
print $lclient "$lpeer->Welcome to server\n";

while(<$lclient>){
# print $lclient "$lpeer->$_\n";
print "clients-> @clients\n";

foreach my $fn (@clients) {
open my $fh, ">&=$fn" or warn $! and die;
print $fh "$_"
}

}

}

#close filehandle before detached thread dies out
close( $lclient);
#remove multi-echo-clients from echo list
@clients = grep {$_ !~ $lfileno} @clients;

}
.



Relevant Pages

  • Re: Socket switch delay
    ... both at the client and at the server (and why ... would you set the send buffer size to zero on a non-overlapped ... One glaring error is your client does ... So when you use a single socket, ...
    (microsoft.public.win32.programmer.networks)
  • Re: bin/131567: Update for regression/sockets/unix_cmsg
    ... -Usually each test does following steps: create Server, fork Client, ... Sometimes Client sends several ... +If Client sends some ancillary data object, ... Receiving sockcred (listening socket has LOCAL_CREDS) ...
    (freebsd-net)
  • Re: bin/131567: Update for regression/sockets/unix_cmsg
    ... -Usually each test does following steps: create Server, fork Client, ... Sometimes Client sends several ... +If Client sends some ancillary data object, ... Receiving sockcred (listening socket has LOCAL_CREDS) ...
    (freebsd-net)
  • Re: bin/131567: Update for regression/sockets/unix_cmsg
    ... -Usually each test does following steps: create Server, fork Client, ... Sometimes Client sends several ... +in the msg_iov field from struct msghdr. ... Receiving sockcred (listening socket has LOCAL_CREDS) ...
    (freebsd-net)
  • Chat client/server print failed
    ... This is a chat client wrote in perl Gtk2. ... is the print statement in the send_msg_all sub. ... leave the server running for testing purposes. ... # just read means there is a complete request waiting ...
    (comp.lang.perl.misc)