[jcifs] Problem reading multiple writes from named pipe

Michael B.Allen Michael_B_Allen at ml.com
Wed Apr 9 12:31:54 EST 2003


On Mon, 7 Apr 2003 17:01:38 -0400
"Eric Sword" <ericsword at grouplogic.com> wrote:

> I am having a problem reading data from a pipe when it was written using
> more than one WriteFile call in a C++ app.  The setup is pretty standard
> - I'm am using slightly modified copies of the sample apps createnp and
> CallNamedPipe.  The Java app reads from stdin, sends to the C++ app, and
> the C++ app echos it back in 2 sends.  The first send contains only an
> int which is the length of the second send (matching an existing
> protocol I am working with).  
> 
> I have tried multiple ways of setting up the pipe (just PIPE_TYPE_RDWR,
> PIPE_TYPE_RDWR | PIPE_TYPE_CALL, and PIPE_TYPE_RDWR |
> PIPE_TYPE_TRANSACT), properly changing the pipe URL for each.  Each way,
> I can send data over the pipe just fine and I get back the int from the
> first send, but block indefinitely waiting for the info from the second
> message.

I don't think it makes sense to use PIPE_TYPE_CALL or PIPE_TYPE_TRANSACT
because those send a message and get a response on *one round trip*
whereas without PIPE_TYPE_CALL or PIPE_TYPE_TRANSACT you try to read
which blocks and then write and get a write response and finally the
read returns with the result. If you do not use PIPE_TYPE_CALL or
PIPE_TYPE_TRANSACT what you describe works. I modified createnp.c to
write a 0xFF byte for each message read like:

    154     while(ReadFile(inFile, buf, bufferSize, &bytesRead, NULL) > 0) {
    155         char b = 0xFF;
    156         int tmp;
    157         WriteFile(outFile, &b, 1, &tmp, NULL);
    158         WriteFile(outFile, buf, bytesRead, &bytesRead, NULL);
    159     }

ran it with:

    C:\Temp> createnp \\.\pipe\foo

and took a capture of the following PipeTalk:

    $ java -Djcifs.properties=jcifs.prp PipeTalk "smb://miallen2/IPC$/foo"
    hello
    hello
    ÿ
    hello
    yoyoyo
    yoyoyo
    ÿ
    yoyoyo

and I can see that two separate packets are sent in the response for
the WriteFile calls. So it works.

> [code snippet]
> 
> //first read the length of the message - stored in the first 4 bytes
> length = sd_istream.readInt();
> System.out.println("Message Length: " + length);
> 
> //now read the message
> int numRead = in.read(temp);
> String tempString = new String(temp, 0, numRead);
> 
> [end snippet]
> 
> If I just do the single in.read, it will also only find 4 bytes to read
> in.  
> 
> Suggestions?

If you want to use PIPE_TYPE_CALL or PIPE_TYPE_TRANSACT you cannot
write each field separately. This is generally true of any network
programming. Instead you must encode the message format into a buffer
and write the entire buffer in one write call. Actually I have a library
written in C that could help you with this. I describe how one might
use it in this message:

  http://groups.google.com/groups?selm=20021117.034856.502278611.10307%40eskimo.com

I think this might apply to you.

Mike



More information about the jcifs mailing list