⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 multiclientserver.c

📁 labwindow 编程的tcp网络开发例程。
💻 C
📖 第 1 页 / 共 2 页
字号:
}

/*---------------------------------------------------------------------------*/
/* Compares two client info data-structures.                                 */
/* Used by the ListFindItem function.                                        */
/*---------------------------------------------------------------------------*/
static int CVICALLBACK CompareClientInfoPtr (void *item1, void *item2)
{
    return ((*(ClientInfoPtr *) item1)->handle 
                - (*(ClientInfoPtr *) item2)->handle);
}

/*---------------------------------------------------------------------------*/
/* Disconnects the client identified by the info data-structure.             */
/*---------------------------------------------------------------------------*/
static int Disconnect (ClientInfoPtr clientInfoPtr, int index, int removeFromList)
{
    int numUIListItems;
    
    /* Signal client's worker thread to stop. */
    clientInfoPtr->stopFlag = 1;
    /* Wait for client's worker thread to stop. */
    CmtWaitForThreadPoolFunctionCompletion (DEFAULT_THREAD_POOL_HANDLE, 
        clientInfoPtr->threadFuncId, OPT_TP_PROCESS_EVENTS_WHILE_WAITING);
    /* Release the client's worker thread function. */
    CmtReleaseThreadPoolFunctionID (DEFAULT_THREAD_POOL_HANDLE, 
        clientInfoPtr->threadFuncId);

    /* Disconnect the client conversation handle. */
    DisconnectTCPClient (clientInfoPtr->handle);
    
    if (removeFromList)
        ListRemoveItem (gClientList, NULL, index);

    /* Remove client entry from user interface and update controls. */
    GetIndexFromValue (gPanel, PANEL_CLIENT_LIST, &index, (int)clientInfoPtr);
    DeleteListItem (gPanel, PANEL_CLIENT_LIST, index, 1);
    GetNumListItems (gPanel, PANEL_CLIENT_LIST, &numUIListItems);
    SetCtrlAttribute (gPanel, PANEL_DISCONNECT, ATTR_DIMMED, numUIListItems == 0);
    SetCtrlAttribute (gPanel, PANEL_SEND, ATTR_DIMMED, numUIListItems == 0);
    SetCtrlAttribute (gPanel, PANEL_DATA, ATTR_DIMMED, numUIListItems == 0);
    
    /* Dispose client information data-structure. */
    free (clientInfoPtr);
    
    return 0;
}

/*---------------------------------------------------------------------------*/
/* Disconnects the client identified by the handle.                          */
/*---------------------------------------------------------------------------*/
static int DisconnectClient (unsigned int handle)
{
    ClientInfo      clientInfo = {0};
    ClientInfoPtr   clientInfoPtr = &clientInfo;
    int             index;
    
    /* Find the client information from TCP conversation handle. */
    clientInfoPtr->handle = handle;
    index = ListFindItem (gClientList, &clientInfoPtr, 
        FRONT_OF_LIST, CompareClientInfoPtr);
    if (index > 0)
        {
        /* Get the stored client information and disconnect the client. */
        ListGetItem (gClientList, &clientInfoPtr, index);
        Disconnect (clientInfoPtr, index, 1);
        }
        
    return 0;
}

/*---------------------------------------------------------------------------*/
/* TCP callback function for the server.                                     */
/*---------------------------------------------------------------------------*/
static int CVICALLBACK ServerCallback (unsigned int handle, int xType, 
                                       int errCode, void *cbData)
{
    if (xType == TCP_CONNECT)
        {
        /* Connect new client. */
        ConnectClient (handle);
        }
    else if (xType == TCP_DISCONNECT)
        {
        /* Client is disconnecting. Update program state. */
        DisconnectClient (handle);
        }
    else if (xType == TCP_DATAREADY)
        {
        ClientInfo      clientInfo = {0};
        ClientInfoPtr   clientInfoPtr = &clientInfo;
        int             index;
    
        /* Find the client information from TCP conversation handle. */
        clientInfoPtr->handle = handle;
        index = ListFindItem (gClientList, &clientInfoPtr, 
            FRONT_OF_LIST, CompareClientInfoPtr);
        if (index > 0)
            {
            /* Get the stored client information. */
            ListGetItem (gClientList, &clientInfoPtr, index);
            
            /*
             * NOTE - Because the reading is done in the worker thread,
             * this thread (the main thread) is not blocked, and will 
             * continue to receive TCP_DATAREADY events, until all the 
             * data is read. This program uses the readingData flag to 
             * ignore these events, until all the data is read by the 
             * worker thread.
             */
            if (!clientInfoPtr->readingData)
                {
                clientInfoPtr->readingData = 1;
                PostDeferredCallToThread (DeferredReceive, clientInfoPtr, 
                    clientInfoPtr->threadId);
                }
            }
        }   

    return 0;
}

/*---------------------------------------------------------------------------*/
/* Disconnects an item in the connected clients list.                        */
/* Used by the ListApplyToEach function.                                     */
/*---------------------------------------------------------------------------*/
static int CVICALLBACK DisconnectClientListItem (int index, void *itemPtr, 
                                                 void *data)
{
    Disconnect (*(ClientInfo **) itemPtr, index, 0);
    return 0;
}

/*---------------------------------------------------------------------------*/
/* Sends data to client.                                                     */
/*---------------------------------------------------------------------------*/
static void CVICALLBACK DeferredSend (void *data)
{
    int             tcpErr = 0;
    ClientInfoPtr   clientInfoPtr = (ClientInfoPtr) data;
    char            *dataBuf = NULL;
    int             dataBufSize;
    
    /* Get the size of the data to send. */
    GetCtrlAttribute (gPanel, PANEL_DATA, ATTR_STRING_TEXT_LENGTH, &dataBufSize);
    if (dataBufSize > 0)
        {
        /* Allocate a buffer to hold the data. */
        dataBuf = malloc (sizeof (char) * (++dataBufSize));
        if (dataBuf)
            {
            /* Pointer to current data to send. */
            char *currData = dataBuf;
            
            /* Read the data from the user interface. */
            GetCtrlVal (gPanel, PANEL_DATA, dataBuf);
            
            /* Write the data in a loop, until there is no more data to send. */
            while (dataBufSize > 0)
                {
                int bytesSent = ServerTCPWrite (clientInfoPtr->handle, 
                    currData, dataBufSize, 0);
                if (bytesSent >= 0)
                    {
                    /* Subtract number of bytes sent from amount of data left. */
                    dataBufSize -= bytesSent;
                    /* Update current data. */
                    currData += bytesSent;
                    }
                else
                    tcpChk (bytesSent);
                }
                
            /* Free the data buffer. */
            free (dataBuf);
            }
        }
Done:
    return;
}

/*---------------------------------------------------------------------------*/
/* Receives data from client.                                                */
/*---------------------------------------------------------------------------*/
static void CVICALLBACK DeferredReceive (void *data)
{
    ClientInfoPtr   clientInfoPtr = (ClientInfoPtr) data;
    char            dataBuf[256];
    int             bytesRead;
    
    assert (clientInfoPtr->readingData == 1);
    
    /*
     * Disable library error checking as we are going to read until
     * there is no more data left (read call times out).
     */
    DisableBreakOnLibraryErrors ();
    while (1)
        {
        bytesRead = ServerTCPRead (clientInfoPtr->handle, 
            dataBuf, sizeof (dataBuf) - 1, 100);
        if (bytesRead > 0)
            {
            /* Update user interface with the new data. */
            dataBuf [bytesRead] = '\0';
            SetCtrlVal (clientInfoPtr->panel, REC_PANEL_DATA, dataBuf);
            }
        else
            {
            /* No more data to read. Update flag, and exit loop. */
            clientInfoPtr->readingData = 0;
            break;
            }
        }
    /* Enable library error checking. */
    EnableBreakOnLibraryErrors ();
}

/*---------------------------------------------------------------------------*/
/* Report TCP Errors.                                                        */
/*---------------------------------------------------------------------------*/
static void ReportTCPError (int error)
{
    char    messageBuffer[1024];

    if (error < 0)
        {
        sprintf(messageBuffer, 
            "TCP library error message: %s\nSystem error message: %s", 
            GetTCPErrorString (error), GetTCPSystemErrorString());
        MessagePopup ("Error", messageBuffer);
        }
}
/*---------------------------------------------------------------------------*/

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -