Mike Oliver wrote:

> Okay - I think we're near the finish line here. I'm beginning to understand.
> Thanks for your help John and Wan-Teh. Just a couple of last questions:
> 
> - If I use blocking sockets - I can spawn another thread to handle the
> PR_Read, which will block. The problem is that while that thread is
> blocking, waiting for some data to be sent to the socket, the user might
> shut down the app through the main thread. In the main thread, therefore, I
> try to close the socket w/ PR_Close() before killing the thread itself. The
> problem is that PR_Close blocks indefinitely, assumably because the socket
> is still blocking on the PR_Read call. How do I shut down the socket
> gracefully in this condition??


Closing a PRFileDesc while another thread is reading
from it is incorrect.  It may appear to work fine on
some platforms.  As [EMAIL PROTECTED] pointed out,
PR_Interrupt() is the function designed for this
purpose.

 
> - If I use non-blocking sockets, I am having trouble doing the
> PR_Read/PR_Write operations. My problem earlier about contnually reading
> data from the socket was just my coding problem, but caused because I'm not
> sure exactly how to do a PR_Read/PR_Write with non-blocking sockets. I've
> seen here that I need to use PR_Poll, but how? A small code sample would be
> very helpful. W/ a non-blocking socket, calling PR_Read/PR_Write returns
> a -1 (error WOULD_BLOCK, of course) - how do I use PR_Poll to wait until the
> Read/Write is complete and to check the # of bytes (if any!)


You can look at some of the test programs in
mozilla/nsprpub/pr/tests as code sample.
Alternatively, you can easily convert BSD
socket code sample to use NSPR socket functions.
Our socket API is modeled after the BSD socket
API.

The only thing PR_Poll can tell you is that a
socket is readable or writable.  It cannot tell
you how many bytes can be read or written.
Moreover, with NSPR layered sockets, a read or
write on a socket that PR_Poll reports as readable
or writable may only result in invisible internal
progress and fail with the WOULD_BLOCK error.

Example: Suppose you want to read exactly 1024 bytes
from a socket 'sock' (which can be layered or non-layered),
you would do something like this:
     char buf[1024];
     char *bufp = buf;
     PRInt32 len = sizeof(buf);
     PRInt32 toread = len;
     PRInt32 nread;
     PRPollDesc pfd;
     PRInt32 npoll;

     do {
         nbytes = PR_Read(sock, bufp, toread);
         if (nbytes == 0) break;  /* end of stream */
         if (nbytes == -1) {
             if (PR_GetError() == PR_WOULD_BLOCK_ERROR) {
                 pfd.fd = sock;
                 pfd.in_flags = PR_POLL_READ;
                 npoll = PR_Poll(&pfd, 1, PR_INTERVAL_NO_TIMEOUT);
                 if (npoll > 0) {
                     if (pfd.out_flags & PR_POLL_READ) {
                         continue;  /* retry read */
                     }
                 }
                 break;  /* PR_Poll failed */
             }
             break;  /* a real error */
         }
         /* we read in some bytes */
         bufp += nbytes;
         toread -= nbytes;
     } while (toread > 0);

Typically you will poll and read or write from several
sockets, so the code will be more complidated than this
example.

Hope this helps.

Wan-Teh



Reply via email to