sajanagr has asked for the wisdom of the Perl Monks concerning the following question:

Hi Monks

I am trying to create a simple bidirectional server-client communication using socket and am not using IO::Socket for some reason currently.

The communication between server to client works fine. But, while I print some data from client to server's socket, I am not able to read it at server's side.

I am trying to read the socket from accept function at server's side. But, it gives me nothing.

Can you advise me anything ?

  • Comment on Simple question regarding Bidirectional socket programming

Replies are listed 'Best First'.
Re: Simple question regarding Bidirectional socket programming
by Corion (Patriarch) on Jun 15, 2010 at 08:06 UTC

    accept does not read data.

    You don't show any code, so it's hard to tell you where you're going wrong.

Re: Simple question regarding Bidirectional socket programming
by cdarke (Prior) on Jun 15, 2010 at 08:32 UTC
    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).
      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...