in reply to Re: Simple question regarding Bidirectional socket programming
in thread Simple question regarding Bidirectional socket programming

To reduce the confusion, I am putting the code below

server.pl

use strict; use Socket; my $port = shift || 7890; my $proto = getprotobyname('tcp'); socket(SERVER, PF_INET, SOCK_STREAM, $proto) or die "socket: $!"; setsockopt(SERVER, SOL_SOCKET, SO_REUSEADDR, 1) or die "setsock: $!"; my $paddr = sockaddr_in($port, INADDR_ANY); bind(SERVER, $paddr) or die "bind: $!"; listen(SERVER, SOMAXCONN) or die "listen: $!"; print "SERVER started on port $port\n"; my $client_addr; while ($client_addr = accept(CLIENT, SERVER)) { my ($client_port, $client_ip) = sockaddr_in($client_addr); my $client_ipnum = inet_ntoa($client_ip); my $client_host = gethostbyaddr($client_ip, AF_INET) ; print "got a connection from: $client_host"," [$client_ipnum]\n"; $| = 1; print CLIENT "Hello from the server \n\n "; my $response; # Trying to read client while ( defined ($response = <$client_addr>) ){ print "Response from client : $response" ; } sleep(1); close CLIENT; }
client.pl
#! /usr/bin/perl -w # client1.pl - a simple client use strict; use Socket; my $host = shift || 'sajan.random.com'; my $port = shift || 7890; my $proto = getprotobyname('tcp'); my $iaddr = inet_aton($host); my $paddr = sockaddr_in($port, $iaddr); socket(SOCKET, PF_INET, SOCK_STREAM, $proto) or die "socket: $!"; connect(SOCKET, $paddr) or die "connect: $!"; my $line; while ($line = <SOCKET>) { $| = 1; print $line; # Trying to send something to server print SOCKET "Client says hellooooo toooo !!! "; open my $tfh, " >> /tmp/sajan.tmp"; print $tfh $line; close $tfh } close SOCKET or die "close: $!";

Replies are listed 'Best First'.
Re^3: Simple question regarding Bidirectional socket programming
by almut (Canon) on Jun 15, 2010 at 09:42 UTC

    First, you should read from CLIENT, not from $client_addr:

    while ( defined ($response = <CLIENT>) ){

    Next, you have to flush (or autoflush) when you write something on either side. Otherwise, due to buffering, the messages will not be available on the other side right away, resulting in a deadlock, because both sides will wait for the other side to say something...  One way would be to use IO::Handle:

    use IO::Handle; ... print CLIENT "Hello from the server \n\n "; CLIENT->flush(); ...

    and similarly on the client side.

    Also, as both client and server are in a readline while loop, you'll likely want to have some protocol that defines when to stop reading and terminate the connection.

    Finally, when you read lines on the server side, you also have to print a line on the client side:

    print SOCKET "Client says hellooooo toooo !!! \n"; # ^^ SOCKET->flush();

    Otherwise, the server will hang in $response = <CLIENT>, waiting for the newline...

      Hi almut, your solution worked just perfect for me, the code is working now after your changes.

      I added a condition for break in the while loop for the deadlock.

      There is another doubt, I read that $| variable of perl does flusing, so I had used that in the code above, but it didnt work somehow here and when i used IO::Socket and did CLIENT->flush(), it worked.

      I didn't understand this. Can you elaborate?

        Setting $| applies to the "selected" file handle, which by default is STDOUT. In theory, you could use select (the one argument variant) to have it apply to any other handle (see the example in the docs), but personally, I find the IO::Handle API less cumbersome to use.

        You can use
        use IO::Handle; ... CLIENT->autoflush(1); ... print CLIENT "Hello from the server \n\n"; ...
        instead of
        use IO::Handle; ... print CLIENT "Hello from the server \n\n"; CLIENT->flush(); ...

        The first is the same as calling $|=1; with the CLIENT handle selected.