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

📄 multiclientserver.c

📁 labwindow 编程的tcp网络开发例程。
💻 C
📖 第 1 页 / 共 2 页
字号:
/*---------------------------------------------------------------------------*/
/*                                                                           */
/* FILE:    MultiClientServer.c                                              */
/*                                                                           */
/* PURPOSE: This TCP server program allows multiple TCP clients to connect   */
/*          to it. The program allows the user to write to any of the        */
/*          connected clients. The program receives and displays any data    */
/*          sent by the clients. The program uses worker threads to manage   */
/*          reading and writing to each client. You can use the TCP client   */
/*          sample program to interact with this server.                     */
/*                                                                           */
/*---------------------------------------------------------------------------*/

/*---------------------------------------------------------------------------*/
/* Include files                                                             */
/*---------------------------------------------------------------------------*/
#include <tcpsupp.h>
#include <ansi_c.h>
#include <utility.h>
#include <toolbox.h>
#include "MultiClientServer.h"

/*---------------------------------------------------------------------------*/
/* Macros and constants                                                      */
/*---------------------------------------------------------------------------*/
#define SERVER_PORT_NUM     10000
#define tcpChk(f) if ((tcpErr=(f))<0) {ReportTCPError(tcpErr); goto Done;} else

/*---------------------------------------------------------------------------*/
/* Type definitions                                                          */
/*---------------------------------------------------------------------------*/
typedef struct ClientInfo
{
    unsigned int    handle;         /* TCP conversation handle */
    unsigned int    threadId;       /* ID of worker thread */
    int             threadFuncId;   /* ID of worker thread function */
    int             stopFlag;       /* Flag used to stop worker thread */
    char            name[256];      /* Descriptive name of client connection */
    int             readingData;    /* Indicates server is reading from client */
    int             panel;          /* Handle of panel to display client data */
} ClientInfo, *ClientInfoPtr;

/*---------------------------------------------------------------------------*/
/* Module-globals                                                            */
/*---------------------------------------------------------------------------*/
static int          gPanel = 0;         /* Main user interface panel handle */
static ListType     gClientList = 0;    /* List of connected clients */

/*---------------------------------------------------------------------------*/
/* Internal function prototypes                                              */
/*---------------------------------------------------------------------------*/
static int ConnectClient (unsigned int handle);
static int DisconnectClient (unsigned int handle);
static int Disconnect (ClientInfoPtr clientInfoPtr, int index, int removeFromList);
static int CVICALLBACK ClientThreadFunction (void *data);
static int CVICALLBACK CompareClientInfoPtr (void *item1, void *item2);
static int CVICALLBACK DisconnectClientListItem (int index, void *itemPtr, 
                                                 void *data);
static int CVICALLBACK ServerCallback (unsigned int handle, int xType, 
                                       int errCode, void *cbData);
static void CVICALLBACK DeferredSend (void *data);
static void CVICALLBACK DeferredReceive (void *data);
static void ReportTCPError (int error);

/*---------------------------------------------------------------------------*/
/* This is the application's entry-point.                                    */
/*---------------------------------------------------------------------------*/
int main (int argc, char *argv[])
{
    int     tcpErr = 0;
    int     unregisterServer = 0;
    
    if (InitCVIRTE(0, argv, 0) == 0)
        return -1;
    
    /* Load user interface */
    if ((gPanel = LoadPanel (0, "MultiClientServer.uir", PANEL)) < 0)
        return -1;

    /* Create list to manage client connections */
    gClientList = ListCreate (sizeof (ClientInfoPtr));
    
    /* Register the server */
    tcpChk (RegisterTCPServer (SERVER_PORT_NUM, ServerCallback, NULL));
    unregisterServer = 1;
    
    DisplayPanel (gPanel);
    RunUserInterface ();

    /* Clean up */
    if (gClientList)
        {
        ListApplyToEach (gClientList, 0, DisconnectClientListItem, 0);
        ListDispose (gClientList);
        }

Done:
    if (unregisterServer)
        UnregisterTCPServer (SERVER_PORT_NUM);
    DiscardPanel (gPanel);
    
    return 0;
}

/*---------------------------------------------------------------------------*/
/* Respond to the panel closure to quit the UI loop.                         */
/*---------------------------------------------------------------------------*/
int CVICALLBACK PanelCallback (int panel, int event, void *callbackData,
        int eventData1, int eventData2)
{
    switch (event)
        {
        case EVENT_CLOSE:
            QuitUserInterface (0);
            break;
        }
    return 0;
}

/*---------------------------------------------------------------------------*/
/* Send data to connected client.                                            */
/*---------------------------------------------------------------------------*/
int CVICALLBACK SendCallback (int panel, int control, int event,
        void *callbackData, int eventData1, int eventData2)
{
    ClientInfoPtr       clientInfoPtr = NULL;
    
    switch (event)
        {
        case EVENT_COMMIT:
            /*
             * Get current client from listbox, and post the call 
             * to its worker thread.
             */
            GetCtrlVal (gPanel, PANEL_CLIENT_LIST, (int *)(&clientInfoPtr));
            PostDeferredCallToThread (DeferredSend, clientInfoPtr, 
                clientInfoPtr->threadId);
            break;
        }
    return 0;
}

/*---------------------------------------------------------------------------*/
/* Disconnect a client.                                                      */ 
/*---------------------------------------------------------------------------*/
int CVICALLBACK DisconnectCallback (int panel, int control, int event,
        void *callbackData, int eventData1, int eventData2)
{
    ClientInfoPtr       clientInfoPtr = NULL;
    int                 index;
    
    switch (event)
        {
        case EVENT_COMMIT:
            /* Get current client from listbox. */
            GetCtrlVal (gPanel, PANEL_CLIENT_LIST, (int *)&clientInfoPtr);
            /* Find the index of the client in the client list. */
            index = ListFindItem (gClientList, &clientInfoPtr, 
                FRONT_OF_LIST, CompareClientInfoPtr);
            /* Disconnect the client. */
            if (index > 0)
                Disconnect (clientInfoPtr, index, 1);
            break;
        }
    return 0;
}

/*---------------------------------------------------------------------------*/
/* Worker thread function for clients.                                       */
/*---------------------------------------------------------------------------*/
static int CVICALLBACK ClientThreadFunction (void *data)
{
    ClientInfoPtr clientInfoPtr = (ClientInfoPtr) data;
    
    clientInfoPtr->threadId = CmtGetCurrentThreadID ();

    /* Load a new panel for this client message. */
    clientInfoPtr->panel = LoadPanel (0, "MultiClientServer.uir", REC_PANEL);
    SetPanelAttribute (clientInfoPtr->panel, ATTR_CLOSE_ITEM_VISIBLE, 0);
    
    /* Set the client's name in the panel. */
    SetCtrlVal (clientInfoPtr->panel, REC_PANEL_CLIENT_NAME, 
        clientInfoPtr->name);
    DisplayPanel (clientInfoPtr->panel);
    
    /* Process user-interface, TCP and other system events. */
    while (!clientInfoPtr->stopFlag)
        {
        ProcessSystemEvents ();
        }
    
    /* Discard the client panel. */
    DiscardPanel (clientInfoPtr->panel);
    
    return 0;
}

/*---------------------------------------------------------------------------*/
/* Connects the client identified by handle.                                 */
/*---------------------------------------------------------------------------*/

static int ConnectClient (unsigned int handle)
{
    int             tcpErr = 0;
    ClientInfoPtr   clientInfoPtr = 0;
    char            peerName[128], peerAddress[128];
    
    /* Create client information data-structure. */
    clientInfoPtr = calloc (1, sizeof (ClientInfo));
    if (clientInfoPtr == NULL)
        return -1;
    clientInfoPtr->handle = handle;
    
    /* Get descriptive name for client. */
    tcpChk (GetTCPPeerName (handle, peerName, sizeof (peerName)));
    tcpChk (GetTCPPeerAddr (handle, peerAddress, sizeof (peerAddress)));
    sprintf (clientInfoPtr->name, "Client name: %s, address: %s", 
        peerName, peerAddress);
    
    /* Create worker thread for this client. */
    CmtScheduleThreadPoolFunction (DEFAULT_THREAD_POOL_HANDLE, 
        ClientThreadFunction, clientInfoPtr, &clientInfoPtr->threadFuncId);
    
    /* Add the client to the list. */
    ListInsertItem (gClientList, &clientInfoPtr, END_OF_LIST);
    
    /* Add client to user interface and update disabled controls. */
    InsertListItem (gPanel, PANEL_CLIENT_LIST, -1, clientInfoPtr->name, 
        (int)clientInfoPtr);
    SetCtrlAttribute (gPanel, PANEL_DISCONNECT, ATTR_DIMMED, 0);
    SetCtrlAttribute (gPanel, PANEL_SEND, ATTR_DIMMED, 0);
    SetCtrlAttribute (gPanel, PANEL_DATA, ATTR_DIMMED, 0);
    
Done:   
    return 0;

⌨️ 快捷键说明

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