Single character reads on sockets 
Author Message
 Single character reads on sockets

Hi

I am trying to write a client and a server that communicate using the
following simple protocol:
        - length of content-length field (1 character)
        - length of content
        - content
For example, when sending the string 'hello', the message actually sent is:
        211hello there

where the '2' is the length of the '11', and 11 is the length of 'hello
there'.
This allows fixed length reads and writes.

On the both the reader and listener side I have used $| = 1 but to no avail.

On the reader side I do:

    read ( $sock, $lenlen, 1 );
    read ( $sock, $len,      $lenlen );
    read ( $sock, $msg,    $len );

It seems that the first read hangs.

Am I doing things correctly?
Any suggestions? hints? advice? etc?

-TIA
David



Tue, 14 Oct 2003 05:30:07 GMT  
 Single character reads on sockets

Quote:
>     read ( $sock, $lenlen, 1 );
>     read ( $sock, $len,      $lenlen );
>     read ( $sock, $msg,    $len );

> It seems that the first read hangs.

Try using sysread().

Elijah
------
big fan of sysread for fixed length reads



Wed, 15 Oct 2003 01:29:42 GMT  
 Single character reads on sockets

Quote:

> >     read ( $sock, $lenlen, 1 );
> >     read ( $sock, $len,      $lenlen );
> >     read ( $sock, $msg,    $len );

> > It seems that the first read hangs.

> Try using sysread().

Can you explain why you think this would help?

Quote:
> big fan of sysread for fixed length reads

Is this cargo-cult or do you have some reason?

Personally I dislike sysread() for fixed length reads because unless
the length in question is 1 you have to put it in a loop.

--
     \\   ( )
  .  _\\__[oo

 .  l___\\
  # ll  l\\
 ###LL  LL\\



Wed, 15 Oct 2003 03:08:04 GMT  
 Single character reads on sockets

Quote:
> It seems that the first read hangs.

If read($sock, $lenlen, 1) hangs, it is because there is no data
available to read.  You need to use the select() function to detect
whether data is available, and read only if it is available.  (Note
that there are two unrelated select() functions; you want the one with
four arguments.)


Wed, 15 Oct 2003 03:59:51 GMT  
 Single character reads on sockets

Quote:

> > It seems that the first read hangs.

> If read($sock, $lenlen, 1) hangs, it is because there is no data
> available to read.  You need to use the select() function to detect
> whether data is available, and read only if it is available.

Which is why you need to use sysread() instead of read()

read() uses stdio, and so buffers data. select() will only return
when there is data on the handle ready for reading, it knows nothing
about the stdio buffer.

Graham.



Wed, 15 Oct 2003 05:41:42 GMT  
 Single character reads on sockets

Quote:
> Which is why you need to use sysread() instead of read()

> read() uses stdio, and so buffers data. select() will only return
> when there is data on the handle ready for reading, it knows nothing
> about the stdio buffer.

sysread() also uses stdio.


Wed, 15 Oct 2003 12:05:41 GMT  
 Single character reads on sockets

I inexplicably said:

Quote:
> sysread() also uses stdio.

I thought I remembered that the last time I looked into pp_sysread,
PerlLIO_read actually called fread(), but of course it doesn't and it
couldn't, so I can't imagine where this idea came from.


Wed, 15 Oct 2003 21:35:54 GMT  
 Single character reads on sockets

Quote:

> > Which is why you need to use sysread() instead of read()

> > read() uses stdio, and so buffers data. select() will only return
> > when there is data on the handle ready for reading, it knows nothing
> > about the stdio buffer.

> sysread() also uses stdio.

It does not. All of the sys* bypass stdio and call the system IO functions.

Take a look in pp_sys.c in the perl source. read() will call fread
in C, but sysread will call read()

Graham.



Wed, 15 Oct 2003 14:29:30 GMT  
 Single character reads on sockets

Quote:
> I am trying to write a client and a server that communicate using the

> On the reader side I do:

>     read ( $sock, $lenlen, 1 );
>     read ( $sock, $len,      $lenlen );
>     read ( $sock, $msg,    $len );

> It seems that the first read hangs.

> Am I doing things correctly?
> Any suggestions? hints? advice? etc?

Some further information. After repeated experimentation I've determined
that the problem is actually a result of 'fork()'.
I'm run in AS 5.6.

On the server side I do:

    my $child = fork();

    if ($child == 0) {
       . . .
       read ( $sock, $lenlen, 1 );
       read ( $sock, $len,      $lenlen );
       read ( $sock, $msg,    $len );
       . . .
    }

This hangs.

When I do the 'read' sequence in the parent child, it works. I've sent a
message to AS but have not received a reply yet.

Is there a way to accomplish the 'fork()' properly (in this case I mean:
start a totally new process, Perl Interpreter and all and be able to pass
the socket to it).

-Thanks
David



Thu, 16 Oct 2003 01:19:01 GMT  
 Single character reads on sockets


Quote:
>Some further information. After repeated experimentation I've determined
>that the problem is actually a result of 'fork()'.
>I'm run in AS 5.6.

>On the server side I do:

>    my $child = fork();

>    if ($child == 0) {
>       . . .
>       read ( $sock, $lenlen, 1 );
>       read ( $sock, $len,      $lenlen );
>       read ( $sock, $msg,    $len );
>       . . .
>    }

>This hangs.

>When I do the 'read' sequence in the parent child, it works. I've sent a
>message to AS but have not received a reply yet.

Did you close($sock) in the parent?  You need to make sure the child has
exclusive access to the file handle it intends to read from.

Have you tested to see if the program behaves differently on
Unix/Linux versus Win32?

        -Joe

--
See http://www.inwap.com/ for PDP-10 and "ReBoot" pages.



Thu, 16 Oct 2003 16:33:34 GMT  
 Single character reads on sockets

Quote:
> Did you close($sock) in the parent?  You need to make sure the child has
> exclusive access to the file handle it intends to read from.

The parent closes the socket immediately after the 'fork' (which is the
soonest it can).

When I scrapped the 'fork' and simply did I/O to the accepted socket, things
work just fine. This means that the problem is strictly one of doing socket
I/O from a child under AS Perl.

As an aside, under AS Perl, the fork does not produce another process. Using
Task Manager to monitor, I never saw any new processes being created even
when the child did a sleep for 10 seconds to give me enough time to see it
in TaskMan. It seems that AS Perl uses an internal thread to simulate a
fork.

Quote:

> Have you tested to see if the program behaves differently on
> Unix/Linux versus Win32?

Unfortunately, Linux is not an option here (my customer is committed to
W2K), however, I am certain this would work properly under Linux.


Fri, 17 Oct 2003 22:57:40 GMT  
 Single character reads on sockets

Quote:

> > Try using sysread().
> Can you explain why you think this would help?

Nothing else would be in the loop trying to buffer things.

Quote:
> > big fan of sysread for fixed length reads
> Is this cargo-cult or do you have some reason?

There are times you want buffering, there are times when
it will do you no good. Other people doubtlessly use fixed
length reads at times when buffering will help them (eg
reading multiple consecutive fixed length records from a
stream). This is not the sort of problem I've had to deal
with.

Quote:
> Personally I dislike sysread() for fixed length reads because unless
> the length in question is 1 you have to put it in a loop.

<shrug>

Elijah
------
do you want your data faster in bits, or slower at once?



Sat, 18 Oct 2003 02:12:29 GMT  
 Single character reads on sockets

Quote:
> As an aside, under AS Perl, the fork does not produce another process. Using
> Task Manager to monitor, I never saw any new processes being created even
> when the child did a sleep for 10 seconds to give me enough time to see it
> in TaskMan. It seems that AS Perl uses an internal thread to simulate a
> fork.

Fork on Win32 is implemented with threads. There's no good way to do a
Unix-style fork on Windows, so threads are the next best way to get
what's needed. That there are problems doesn't surprise me. A quick
look in sv.c at sv_gets (the function that handles reading data from
a filehandle) has a couple of spots where it'll fall down and go
bang when running threaded if you're not careful. (Either 5005 threading
or ITHREADS for windows, though the vulnerabilities are less with ITHREADS)
 I don't doubt that simpler things like read will blow chunks as well.

                                        Dan



Sat, 18 Oct 2003 05:31:37 GMT  
 Single character reads on sockets

Quote:
> Fork on Win32 is implemented with threads. There's no good way to do a
> Unix-style fork on Windows, so threads are the next best way to get
> what's needed. That there are problems doesn't surprise me. A quick
> look in sv.c at sv_gets (the function that handles reading data from
> a filehandle) has a couple of spots where it'll fall down and go
> bang when running threaded if you're not careful. (Either 5005 threading
> or ITHREADS for windows, though the vulnerabilities are less with

ITHREADS)

Actually, what I am trying to do is write a simple server that accepts
connections and starts a new perl process to deal with the incoming
connection. Traditionally, things are done with threads, however as far as I
can tell Perl is not yet thread ready. Under Unix, the fork() gets you a new
process so things work well. In the Windows environment (under AS Perl), the
fork() does not really start up a new process so the similarities to a
Unix-based solution go out the window (pun intended).

I don't want this discussion to tangent to one about threads. Under Windows,
threads and forks are not viable.

I'm looking for a simple way, under windows, for one perl process to accept
an incoming socket connection (this I can easily do in Perl) and have it
then cause a new windows process to start AND pass it the socket that was
returned by the 'accept()' call. In the parent process, I would then close
the accepted socket and go back to listen for more connections. In the newly
started process I would do I/O to the socket. Of course, if the new process
somehow inherited all the sockets of the parent process, I would close the
socket the parent is listening under and just keep the accepted socket open.

Any help in this would be greatly appreciated.

-TIA
David



Sat, 18 Oct 2003 08:11:53 GMT  
 Single character reads on sockets
Follows below code from Dave Roth's 'Win32 Perl Scripting, The
Administrator's Handbook' which may help you in getting your problem
resolved.

I have found both of Roth's books to be invaluable in helping me
intergrating Windows into Perl.

jimbo
;-)

#  SocketDaemon2.pl
#  Example: 7.24
#  ----------------------------------------
#  From "Win32 Perl Scripting: Administrators Handbook" by Dave Roth
#  Published by New Riders Publishing.
#  ISBN # 1-57870-215-1
#
#  This script uses Perl v5.6's fork() function to implement a more
efficient
#  version of Example_11_22.pl.

# Forking for Win32 starts with version 5.006
require 5.006;
use IO::Socket;

$iProcessCount = 0;
$Port = 8080;

if( $Socket = IO::Socket::INET->new( LocalPort => $Port, Listen => 5 ) )
{
    while( 1 )
    {
        print "\nListening for a connection...\n";
        last unless ( $Connection = $Socket->accept() );
        $iProcessCount++;
        print STDERR "Server: Connection $iProcessCount\n";

        MyFork( $Connection );
        $Connection->close();
    }

Quote:
}

sub ProcessAsChild
{

    $Socket->send( "Child process $iProcessCount has started at " .
localtime() . "\n" );
    while(1)
    {
        $Socket->recv( $In, 100 );
        last if( $In eq "\n" || $In eq "" );
        $Socket->send( "You entered: $In" );
    }
    print "\tChild $iProcessCount is closing.\n";
    $Socket->close();

Quote:
}

sub MyFork
{

    my $Pid = fork();

    if( 0 == $Pid )
    {
        # We get here only if we are a child process
        $| = 1;
        ProcessAsChild( $Socket );
        exit();
    }

Quote:
}

#  SocketClient.pl
#  Example: 7.23
#  ----------------------------------------
#  From "Win32 Perl Scripting: Administrators Handbook" by Dave Roth
#  Published by New Riders Publishing.
#  ISBN # 1-57870-215-1
#
#  This script is the client that connects to the daemon code in
#  Example_11_22.pl and Example_11_24.pl

use IO::Socket;

$Host = "localhost" unless( $Host = $ARGV[0] );
$Port = 8080;

print "Connecting to $Host:$Port...\n";
if( $Socket = IO::Socket::INET->new( "$Host:$Port" ) )
{
    while( $In = $Socket->getline() )
    {
        print "Socket client: $In";

        my $Data = <STDIN>;
        $Socket->print( $Data );
    }
    $Socket->close();

Quote:
}

else
{
    print "Failed to connect.\n";
Quote:
}



Sat, 18 Oct 2003 18:24:20 GMT  
 
 [ 16 post ]  Go to page: [1] [2]

 Relevant Pages 

1. overiding static methods in Delphi 1.0

2. Is there an equivalent to VB Findkey/findnext in delphi 1.0 ?

3. Single character reads on sockets

4. Read a single character from STDIN (W98)

5. QUESTION: Reading single characters from STDIN

6. Reading single character under SunOS (I know its FAQ)

7. How can I read one single character?

8. Help about reading a single character from the console without hitting enter

9. FILE TRANFERING over IPX network

10. ???? Displaying date in DBGrid ???

11. (Fwd) New Anonymous Remailer

12. Reading a single line from a socket

 

 
Powered by phpBB® Forum Software