Following are a few code snippets. Note, of course, that we're using the BSD front-end calls to the Palm NetLib stuff. The call "getProgress()" tells us whether the network operation is being monitored by a progress dialog, which causes us to do things quite differently at a low level. In actual testing, it was always true (we turned out to have no need for a version of net I/O *without* a progress monitor). Also note that this code was developed on and for Palm OS 3.5; I don't know whether it would have turned out differently with a later OS.

--Greg Lutz

--------------------------------------------------------------

    // Connect to the server.
    //

    //  Sorry to be doing this at such a low level, but it's really
    //  necessary for this code to know whether we're doing a Progress
    //  dialog.  If we are, immediately put the socket into nonblocking
    //  mode in the interests of user responsiveness.

if (getProgress() != NULL) {

        if (setSocketNonblocking(mSocketDescriptor, true) < 0)
            err = getLastError();
        else
            showProgressMessage(/*M*/"Connecting to server");
    }

if (err == errNone) {

while (true) {

            err = connect(
                mSocketDescriptor,
                (NetSocketAddrType*)&mServiceAddress,
                sizeof(NetSocketAddrType) );

            //  Even though they're not documented *anywhere*, I'm
            //  guessing that
            //
            //      netErrAlreadyInProgress
            //      netErrWouldBlock
            //      netErrSocketBusy
            //
            //  all just mean that we're waiting on the connect call.
            //
            if (err == netErrWouldBlock ||
                err == netErrSocketBusy ||
                err == netErrAlreadyInProgress)
            {
                if (checkCancel(true))
                    err = getLastError();
                else
                    continue;
            }

            if (err == netErrSocketAlreadyConnected)
                err = errNone;
            break;
        }
    }

--------------------------------------------------------------

/*
 * readN()
 *
 * Read "n" bytes from a descriptor.
 * Use in place of read() when fd is a stream socket.
 *
 * If the socket is in non-blocking mode, the logic is less
 * straightforward than might be wished.
 */

Int16
PalmNetTCP::readNBinary( register Char *pOutBuf, register UInt16 nbytes)
{
    Int16   nleft, nread;


nleft = nbytes; while (nleft > 0) {

nread = read( mSocketDescriptor, pOutBuf, nleft );

if (nread < 0) {

            if (getLastError() == netErrWouldBlock &&
                !checkCancel(true))
            {
                continue;
            }
            return nread;       // error, return < 0

        } else if (checkCancel(false)) {
            return -1;
        }

        if (nread == 0)
            break;              // we're done

        nleft -= nread;
        pOutBuf += nread;
        updateReadProgress(nread);
    }

    return nbytes - nleft;      // return >= 0
}

--------------------------------------------------------------

bool
PalmNetProgress::checkCancel(bool wait)
{
    ASSERT(mpPrg != NULL);

    //  We only check for user cancel requests every so often
    //  (mCancelCheckInterval), or when caller says to force the issue
    //  ("wait").  The check involves sitting and waiting a while
    //  (mCancelCheckTimeout ticks) to give the user a chance to hit
    //  the Cancel button.  If we do get a cancel, paranoidly flush any
    //  further entries from the event queue (I'm afraid of the
    //  possibility that otherwise, queued-up events will end up
    //  dismissing the subsequent information alert, and possibly
    //  triggering more mischief after that).
    //
    //  Note that the responsiveness of the Cancel button is critical to
    //  the usability of the operation, and that the particular logic
    //  being applied here is the result of rampant empiricism, i.e.,
    //  it's not understood why it works (or better, why other sequences
    //  don't work).

    UInt32 now = TimGetTicks();
    bool canceled = false;

    if (wait || now - mLastCancelCheckTime >= mCancelCheckInterval) {
        mLastCancelCheckTime = now;

        Int32 timeout = mCancelCheckTimeout;
        EventType event;

        do {
            EvtGetEvent(&event, timeout);
            timeout = 0;
            if (!canceled && !PrgHandleEvent(mpPrg, &event))
                canceled = PrgUserCancel(mpPrg);
        } while (event.eType != nilEvent || EvtEventAvail());
    }

    return canceled;
}






At 12:21 AM 7/16/2003, you wrote:


Hello Greg,

Yes, could you give some more details please? You got  netErrWouldBlock and
what the next steps for you?

Regards,
Murad

----- Original Message -----
From: "Greg Lutz" <[EMAIL PROTECTED]>
To: "Palm Developer Forum" <[EMAIL PROTECTED]>
Sent: Wednesday, July 16, 2003 11:31 AM
Subject: Re: NetLib: Nonblocking socket calls
>
> Well, we took a somewhat different approach: use nonblocking sockets, but
> don't use NetLibSelect().  I did some experimentation with select(), and
> never got it to do anything useful.  Instead, we take advantage of
> netErrWouldBlock returns from socket read and write calls to look for user
> input.  It took much fiddling to get the timers tuned right, remaining
> reasonably responsive to user actions while not bogging down the data
> transfer. Our main test configuration was TCP/IP over a standard cell
phone
> connection (a Kyocera 6035 Smartphone, Palm OS 3.5).
>
> If details of this approach are of interest, let me know, and I can send
> you more.
>




--
For information on using the Palm Developer Forums, or to unsubscribe, please see http://www.palmos.com/dev/support/forums/




--
For information on using the Palm Developer Forums, or to unsubscribe, please see 
http://www.palmos.com/dev/support/forums/

Reply via email to