This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

NDK2.0 Client Issue

Hi,

  I am using DSP/BIOS 5 with NDK2.0.  I am creating a client task.  What I have found is that when I am waiting to receive a packet back from the server side, I never get the received packet unless I specify the exact size of the packet coming back.  Currently I put in the size of the receive buffer as the receive size and it just blocks.  When I put in the exact size of the packet coming back, the software finally see's the packet in the receive buffer and lets me proceed with my code.  This does not seem right.  Do I not have a setting set up correctly?

Will.

  • Hi Will,

    I need a few more details...

    BIOS and NDK versions?

    Device?

    TCP or UDP?

    Can you share your example?

    Todd

  • Todd,

    Bios 5.41.11.38, NDK 2.20.05.33

    Our application is setting up multiple ports with the connection between a computer and the OMAP.  1 port is being used specifically as a server port to the computer.  The purpose of this port is for updating parameters needed by our system.  Another port is a client to send messages back to the computer (alerts, timestamps etc..).  The last port is the port I am having trouble with because its also a client port but I am not just sending data to the computer, I'm also receiving data back.  Here is the code example:

    void cd11Proc(void)
    {
        int err;
        Bool cd11Connected = FALSE;

        // Allocate the file descriptor environment for this task
        fdOpenSession((HANDLE)TSK_self());

        CD11BaseSocket = socket(AF_INET, SOCK_STREAMNC, IPPROTO_TCP);
        // open socket as a stream
        if( CD11BaseSocket == INVALID_SOCKET )
        {
            printf("failed CD11 Base Socket Create (%d)\n",fdError());
        }

        // Configure our Tx and Rx timeout to be 5 seconds
        timeout.tv_sec = 5;
        timeout.tv_usec = 0;
        setsockopt(CD11BaseSocket, SOL_SOCKET, SO_SNDTIMEO, &timeout, sizeof( timeout ) );

        for (;;)
        {
            SEM_pendBinary(&processCD11Flag, SYS_FOREVER);    // Wait for semaphore

    //        getReadBufferAddr(dataBuffer);

    //        writeCD11ToBuffer(gpsTime.process.sec, gpsTime.process.mSec, 1000, (int *)dataBuffer,
    //                SAMPLES_PER_CHANNEL, fepParams.startChannel, fepParams.numChannels );

           cd11Connected = CD11ConnectionRequest();
            if(cd11Connected == TRUE)
            {
                err = send(CD11NewSocket, (char *)cd11BuffPtr, cd11PayloadSize , 0);
                if(err < 0)
                {
                    connectedToCD11Server = FALSE;
                    fdClose(CD11BaseSocket);
                }
            }
        }
    }

    The problem I have is in the connection request function:

    Bool CD11ConnectionRequest(void)
    {
        int result = 0;
        int responseSize;
        int errorCode;
        unsigned int rdpsIpAddr = 0;
        unsigned int tmpVal0, tmpVal1, tmpVal2, tmpVal3 = 0;
        Bool retVal = FALSE;
        char* cd11Ptr;
        int destSize = 0;

        cd11Ptr = (char*)(cd11BuffPtr);

        // Establish initial connection on port 9000
        if(connectedToCD11Server == FALSE)
        {
            // Shift 4 chars of SBC IP Address into an int
            tmpVal0 = fepParams.rdpsIpAddr[0];
            tmpVal0 <<= 24;
            tmpVal0 &= 0xFF000000;
            tmpVal1 = fepParams.rdpsIpAddr[1];
            tmpVal1 <<= 16;
            tmpVal1 &= 0x00FF0000;
            tmpVal2 = fepParams.rdpsIpAddr[2];
            tmpVal2 <<= 8;
            tmpVal2 &= 0x0000FF00;
            tmpVal3 = fepParams.rdpsIpAddr[3];
            tmpVal3 &= 0x000000FF;
            rdpsIpAddr = tmpVal0 | tmpVal1 | tmpVal2 | tmpVal3;

            bzero(&cd11DestAddr, sizeof (cd11DestAddr));

            cd11DestAddr.sin_len = sizeof(cd11DestAddr);
            cd11DestAddr.sin_addr.s_addr = htonl(rdpsIpAddr);
            cd11DestAddr.sin_port =htons(fepParams.cd11Port);
            cd11DestAddr.sin_family = AF_INET;

            destSize = sizeof(cd11DestAddr);
            // connect to server
            errorCode = connect(CD11BaseSocket,(PSA)&cd11DestAddr,destSize);
            if (errorCode < 0)
            {
                printf("failed CD11 Base Socket Connect (%d)\n",fdError());
                connectedToCD11Server = FALSE;
            }

            else
            {
                connectedToCD11Server = TRUE;
            }
        }

        // Now establish connection on port 900x
        if (connectedToCD11Server == TRUE)
        {
            if (connectionComplete == FALSE)
            {
                connReqFrameHeader.frameType = htonl(1);
                connReqFrameHeader.trailerOffset = htonl(DATA_FRAME_HEADER_SIZE + sizeof(CD11ConnectionRequestPkt));
                memcpy(connReqFrameHeader.frameCreator, fepParams.frameCreator, sizeof(fepParams.frameCreator));
                memcpy(connReqFrameHeader.frameDestination, fepParams.frameDestination, sizeof(fepParams.frameDestination));
                connReqFrameHeader.sequenceNumber = 0;
                connReqFrameHeader.series = htonl(1);
                memcpy(cd11Ptr, &connReqFrameHeader, DATA_FRAME_HEADER_SIZE);
                cd11Ptr += DATA_FRAME_HEADER_SIZE;

                connReqFrame.majorVersion = htons(1);
                connReqFrame.minorVersion = htons(1);
                connReqFrame.stationName[0] = dataChannelString.siteName[0];
                connReqFrame.stationName[1] = dataChannelString.siteName[1];
                connReqFrame.stationName[2] = dataChannelString.siteName[2];
                connReqFrame.stationName[3] = dataChannelString.siteName[3];
                connReqFrame.stationName[4] = dataChannelString.siteName[4];
                connReqFrame.stationName[5] = '\0';
                connReqFrame.stationName[6] = '\0';
                connReqFrame.stationName[7] = '\0';
                strcpy(connReqFrame.stationType, "E");
                strcpy(connReqFrame.serviceType, "TCP");
                connReqFrame.ipAddress = 0;
                connReqFrame.port = 0;
                connReqFrame.secondIpAddress = 0;
                connReqFrame.secondPort = 0;

                memcpy(cd11Ptr, &connReqFrame, sizeof(connReqFrame));
                cd11Ptr += sizeof(connReqFrame);

                connReqFrameFooter.authKey = 0;
                connReqFrameFooter.authSize = 0;
                connReqFrameFooter.commVerification = 0;

                memcpy(cd11Ptr, &connReqFrameFooter, sizeof(connReqFrameFooter));
                cd11Ptr += sizeof(connReqFrameFooter);

                result = send(CD11BaseSocket, (unsigned char *) cd11BuffPtr, DATA_FRAME_HEADER_SIZE + sizeof(CD11ConnectionRequestPkt) + sizeof(CD11Footer) , 0);
                if (result < 0)
                {
                    fdClose(CD11BaseSocket);
                    fdCloseSession((HANDLE)TSK_self());

                    // Allocate the file descriptor environment for this task
                    fdOpenSession((HANDLE)TSK_self());

                    // Allocate socket as a stream
                    CD11BaseSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
                    if( CD11BaseSocket == INVALID_SOCKET )
                    {
                        printf("failed CD11 Base Socket Create (%d)\n",fdError());
                    }

                    // Configure our Tx and Rx timeout to be 5 seconds
                    timeout.tv_sec = 5;
                    timeout.tv_usec = 0;
                    setsockopt(CD11BaseSocket, SOL_SOCKET, SO_SNDTIMEO, &timeout, sizeof( timeout ) );
                }


                responseSize = recv(CD11BaseSocket, rdpsRecvBuffPtr, 84, MSG_WAITALL);

    This is a code snippit of the connection.  This is a CD11 connection which is a 2 step connection, establish a connection on port9000 and then the computer will tell the DSP which port to move to and then the DSP re-establishes the connection on the new port.  WHat I have found is that the recv function only works when the exact size of 84 is specified.  When I put the size of the receive buffer (8192) in, the recv never works.  Any thoughts?

    Will

  • Will,

    Are you always specifying MSG_WAITALL in the recv? Assuming you have not, have you tried created the socket without the no-copy (SOCK_STREAMNC) flag?

    Todd

  • Todd,

     I am always specifying MSG_WAITALL.  I found a work-around for this issue.  Since I know I am getting a packet back from the computer when I send the request, I put in this code prior to calling the recv function:

                while (results == 0)
                {
                    errorCode = fdStatus(CD11BaseSocket, FDSTATUS_RECV, &results);
                    TSK_sleep(10);
                }

                responseSize = recv(CD11BaseSocket, rdpsRecvBuffPtr, results, MSG_WAITALL);

    I realize this is a band-aid.  I did try the recvnc and it didn't work either.  Do I need seperate receive buffers for each socket?  I just created 1 transmit buffer and 1 recv buffer, each 8192 in size and share them with all the sockets. The memory buffers are created in the .cfg file and I set up the ptr's to each following the BIOS API's.

    Will

  • Will,

    I thought your initial question was that you had to specific the exact size in the recv? When you use MSG_WAITALL, the recv waits until the buffer is full. Here's a snippet from the NDK Reference Guide

    MSG_WAITALL Requests that the operation block until the full request is
    satisfied. However, the call may still return less data than
    requested if an error or disconnect occurs, or the next data to be
    received is of a different type than that returned.

    If you don't want to specify the exact size, don't use the MSG_WAITALL flag.

    Todd

  • Todd,

      I re-tried the recvnc function and it worked.  I thought the MSG_WAITALL waited until the entire packet was received, not the total buffer size.  I guess I will use the recvnc with the SOCKETNC since it seems to work well.

    THanks,

    Will

  • Todd,

    I have looked at the NDK ref guide and  I was wondering if there was a way to make the connection timeout be less than a second.  Basically I want the connection to timeout after 5ms.  This is because I have a 1 second epoch.  Is a 1 second timeout the fastest connection timeout possible with the NDK Stack?

    Will

  • Todd,

      I an able to speed up the conect timeout once the computer is connected to the omap using the setsockopt function seen below:

            timeout.tv_sec = 0;
            timeout.tv_usec = 5000;
            setsockopt(newSocket, SOL_SOCKET, SO_SNDTIMEO, &timeout, sizeof( timeout ) );
            setsockopt(newSocket, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof( timeout ) );


    The time I need to speed up is when the computer is not connected to the omap.  The way I was able to change the connect timeout under this condition was:

        rc = 1;
        CfgAddEntry( hCfg, CFGTAG_IP, CFGITEM_IP_SOCKTIMECONNECT,CFG_ADDMODE_UNIQUE,
                    sizeof(uint), (UINT8 *)&rc, 0);

    This sets a 1 second timeout if not connected but I need this time to be about 5ms as well.  Is 1 second the fastest?



  • Will,

    Yes, the minimum connect time is 1000ms. The following dictates this in sock.c (or sock6.c if it is IPv6).

    if( !FdWaitEvent( ps, FD_EVENT_WRITE, SOCK_TIMECONNECT*1000 ) )

    This timeout is evidentally passed into a SemPend (in fdint_waitevent()) and the unit for SemPend is milliseconds. You could change the above line (and add a big comment!) and rebuild the NDK.

    Todd

  • Todd,

    I am trying to rebuild the NDK following the wiki and for some reason, when I try to import the ndk_core_build project, it acts like its importing but nothing shows up in the project explorer window.  IS there anyone I can talk to about this?

    Will

  • Todd,

    Sorry for all the messages.  So I found the issue and its because I was not importing the project as a c/c++ makefile.  WIth that said, im working through the rest of the steps to get it working.  Thanks for all the support.

    Will