in reply to Simple question regarding Bidirectional socket programming

It is interesting that you are sending data from server to client, what mechanism are you using for that? Normally the client contacts the server first, not the other way around.

Maybe you are using DGRAM sockets? In that case there is effectively little difference between client and server, and accept is not used. If using STREAM sockets then accept is used only for the initial connection, it gives the socket to be used for the conversation (NEWSOCKET in the perldoc).
  • Comment on Re: Simple question regarding Bidirectional socket programming

Replies are listed 'Best First'.
Re^2: Simple question regarding Bidirectional socket programming
by sajanagr (Acolyte) on Jun 15, 2010 at 08:48 UTC
    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: $!";

      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?