6.2远程打印

因为串口打印速度慢,调试程序会影响程序的真正效果,所以引入网络打印

 

debug_manager.h

#ifndef _DEBUG_MANAGER_H
#define _DEBUG_MANAGER_H

#define    APP_EMERG    "<0>"    /* system is unusable            */
#define    APP_ALERT    "<1>"    /* action must be taken immediately    */
#define    APP_CRIT    "<2>"    /* critical conditions            */
#define    APP_ERR            "<3>"    /* error conditions            */
#define    APP_WARNING    "<4>"    /* warning conditions            */
#define    APP_NOTICE    "<5>"    /* normal but significant condition    */
#define    APP_INFO    "<6>"    /* informational            */
#define    APP_DEBUG    "<7>"    /* debug-level messages            */

#define DEFAULT_DBGLEVEL  4

typedef struct DebugOpr {
    char *name;
    int isCanUse;
    int (*DebugInit)(void);
    int (*DebugExit)(void);
    int (*DebugPrint)(char *strData);    
    struct DebugOpr *ptNext;
}T_DebugOpr, *PT_DebugOpr;

int RegisterDebugOpr(PT_DebugOpr ptDebugOpr);
void ShowDebugOpr(void);
PT_DebugOpr GetDebugOpr(char *pcName);
int SetDbgLevel(char *strBuf);
int SetDbgChanel(char *strBuf);
int DebugInit(void);
int DebugPrint(const char *pcFormat, ...);
int InitDebugChanel(void);
int NetPrintInit(void);
int StdoutInit(void);

#endif /* _DEBUG_MANAGER_H */

 

debug_manager.c

#include <config.h>
#include <debug_manager.h>
#include <string.h>
#include <stdio.h>
#include <stdarg.h>

static PT_DebugOpr g_ptDebugOprHead;
static int g_iDbgLevelLimit = 8;        //允许所有级别打印信息

int RegisterDebugOpr(PT_DebugOpr ptDebugOpr)
{
    PT_DebugOpr ptTmp;

    if (!g_ptDebugOprHead)
    {
        g_ptDebugOprHead   = ptDebugOpr;
        ptDebugOpr->ptNext = NULL;
    }
    else
    {
        ptTmp = g_ptDebugOprHead;
        while (ptTmp->ptNext)
        {
            ptTmp = ptTmp->ptNext;
        }
        ptTmp->ptNext      = ptDebugOpr;
        ptDebugOpr->ptNext = NULL;
    }

    return 0;
}


void ShowDebugOpr(void)
{
    int i = 0;
    PT_DebugOpr ptTmp = g_ptDebugOprHead;

    while (ptTmp)
    {
        printf("%02d %s\n", i++, ptTmp->name);
        ptTmp = ptTmp->ptNext;
    }
}

PT_DebugOpr GetDebugOpr(char *pcName)
{
    PT_DebugOpr ptTmp = g_ptDebugOprHead;
    
    while (ptTmp)
    {
        if (strcmp(ptTmp->name, pcName) == 0)
        {
            return ptTmp;
        }
        ptTmp = ptTmp->ptNext;
    }
    return NULL;
}

/* strBuf = "dbglevel=<0-7>" */
int SetDbgLevel(char *strBuf)
{
    g_iDbgLevelLimit = strBuf[9] - '0';
    return 0;
}

/*
 *stdout   = 0               :关闭stdout打印
 *stdout   = 1               :打开staout打印
 *netprint = 0               :关闭netprint打印
 *netprint = 1               :打开netprint打印
 */

int SetDbgChanel(char *strBuf)
{
    char *pStrTmp;
    char strName[100];
    PT_DebugOpr ptTmp;
    
    pStrTmp = strchr(strBuf,'=');        //返回指向‘=’的指针
    if(!pStrTmp)
    {
        return -1;
    }
    else
    {
        strncpy(strName, strBuf, pStrTmp-strBuf);
        strName[pStrTmp-strBuf] = '\0';
        ptTmp = GetDebugOpr(strName);
        if(!ptTmp)
            return -1;

        if(pStrTmp[1] == '0')
            ptTmp->isCanUse = 0;
        else
            ptTmp->isCanUse = 1;
        return 0;
    }
    
}


int DebugPrint(const char *pcFormat, ...)
{
    char strTmpBuf[1000];
    char *pcTmp;
    va_list tArg;
    int iNum;
    PT_DebugOpr ptTmp = g_ptDebugOprHead;
    int dbglevel = DEFAULT_DBGLEVEL;
    
    va_start (tArg, pcFormat);
    iNum = vsprintf (strTmpBuf, pcFormat, tArg);
    va_end (tArg);
    strTmpBuf[iNum] = '\0';


    pcTmp = strTmpBuf;
    
    /* 根据打印级别决定是否打印 */
    if((strTmpBuf[0] == '<') && (strTmpBuf[2] == '>'))
    {
        dbglevel = strTmpBuf[1] - '0';
        if (dbglevel >= 0 && dbglevel <= 9)
        {
            pcTmp = strTmpBuf + 3;
        }
        else
        {
            dbglevel = DEFAULT_DBGLEVEL;
        }
    }

    if (dbglevel > g_iDbgLevelLimit)
    {
        return -1;
    }

    
    /* 调用链表中所有isCanUse为1的结构体的DebugPrint函数 */

    while (ptTmp)
    {
        if(ptTmp->isCanUse)
        {
            ptTmp->DebugPrint(pcTmp);
        }
        ptTmp = ptTmp->ptNext;
    }

    return 0;
    
}

int DebugInit(void)
{
    int iError;

    iError = StdoutInit();
    iError |= NetPrintInit();
    return iError;
}

int InitDebugChanel(void)
{
    PT_DebugOpr ptTmp = g_ptDebugOprHead;
    while (ptTmp)
    {
        if(ptTmp->isCanUse && ptTmp->DebugInit)
        {
            ptTmp->DebugInit();
        }
        ptTmp = ptTmp->ptNext;
    }

    return 0;
}
 
 
stdout.c
#include <config.h>
#include <debug_manager.h>
#include <stdio.h>
#include <string.h>


static int StdoutDebugPrint(char *strData)
{
    /* 直接把输出信息用printf打印出来 */
    printf("%s", strData);
    return strlen(strData);    
}

static T_DebugOpr g_tStdoutDbgOpr = {
    .name       = "stdout",
    .isCanUse   = 1,
    .DebugPrint = StdoutDebugPrint,
};

int StdoutInit(void)
{
    return RegisterDebugOpr(&g_tStdoutDbgOpr);
}

 

netprint.c

#include <config.h>
#include <debug_manager.h>
#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <stdio.h>
#include <signal.h>
#include <stdlib.h>
#include <pthread.h>

#define SERVER_PORT 5678
#define PRINT_BUF_SIZE (16 * 1024)

static int g_iSocketServer;
static struct sockaddr_in g_tSocketServerAddr;
static struct sockaddr_in g_tSocketClientAddr;
static int g_iHaveConnected = 0;
static char *g_pcNetPrintBuf;    
static int g_iReadPos  = 0;
static int g_iWritePos = 0;

static pthread_t g_tSendTreadID;    //发送线程ID
static pthread_t g_tRecvTreadID;    //接收线程ID

static pthread_mutex_t g_tNetDbgSendMutex  = PTHREAD_MUTEX_INITIALIZER;
static pthread_cond_t  g_tNetDbgSendConVar = PTHREAD_COND_INITIALIZER;

static int isFull(void)
{    
    /* 写数据追上读数据的时候满啦 */
    return (((g_iWritePos + 1) % PRINT_BUF_SIZE) == g_iReadPos);
}

static int isEmpty(void)
{
    return (g_iWritePos == g_iReadPos);
}


static int PutData(char cVal)
{
    if(isFull())
        return -1;
    else
    {
        g_pcNetPrintBuf[g_iWritePos] = cVal;
        g_iWritePos = (g_iWritePos + 1) % PRINT_BUF_SIZE;
        return 0;
    }
}

static int GetData(char *pcVal)
{
    if(isEmpty())
        return -1;
    else
    {
        *pcVal = g_pcNetPrintBuf[g_iReadPos];
        g_iReadPos = (g_iReadPos + 1) % PRINT_BUF_SIZE;
        return 0;
    }
}


static void *NetDbgSendTreadFunction(void *pVoid)
{    
    char strTmpBuf[512];
    char cVal;
    int i;
    int iAddrLen;
    int iSendLen;

    while(1)
    {
        /* 平时休眠 */
        pthread_mutex_lock(&g_tNetDbgSendMutex);
        pthread_cond_wait(&g_tNetDbgSendConVar, &g_tNetDbgSendMutex);    
        pthread_mutex_unlock(&g_tNetDbgSendMutex);
        
        /* 条件等待函数 */
        while((g_iHaveConnected && !isEmpty()))
        {
            i = 0;

            /* 把环形缓冲区的数据最多取512字节 */
            while((i < 512)  &&  (0 == GetData(&cVal)))
            {
                strTmpBuf[i] = cVal;
                i++;
            }
            /* 程序能够向下继续证明被唤醒啦 */
            /* 用sendto函数发送打印信息到客户端 */
            
            iAddrLen = sizeof(struct sockaddr);
            iSendLen = sendto(g_iSocketServer, strTmpBuf, i, 0,
                                  (const struct sockaddr *)&g_tSocketClientAddr, iAddrLen);

        }
            
    }
    return NULL;
}

static void *NetDbgRecvTreadFunction(void *pVoid)
{
    socklen_t iAddrLen;
    int iRecvLen;
    char ucRecvBuf[1000];
    struct sockaddr_in tSocketClientAddr;
    
    while(1)
    {
        iAddrLen = sizeof(struct sockaddr);
        DBG_PRINTF("in NetDbgRecvTreadFunction\n");
        iRecvLen = recvfrom(g_iSocketServer, ucRecvBuf, 999, 0, (struct sockaddr *)&tSocketClientAddr, &iAddrLen);
        
        if(iRecvLen > 0)
        {
            ucRecvBuf[iRecvLen] = '\0';
            DBG_PRINTF("netprint.c get msg: %s\n", ucRecvBuf);
            
            /* 解析数据 :
             * setclient            : 设置接收打印信息的客户端
             * dbglevel=0,1,2...    : 修改打印级别
            *stdout   = 0               :关闭stdout打印
             * stdout=1             : 打开stdout打印
            *netprint = 0               :关闭netprint打印
            *netprint = 1               :打开netprint打印
            */
            if(strcmp(ucRecvBuf, "setclient") == 0)
            {
                /* 成功连接且设置为 */
                g_tSocketClientAddr = tSocketClientAddr;
                g_iHaveConnected = 1;
            }
            else if (strncmp(ucRecvBuf, "dbglevel=", 9) == 0)
            {
                SetDbgLevel(ucRecvBuf);    
            }
            else
            {
                SetDbgChanel(ucRecvBuf);
            }
        }
        
    }
    return NULL;
}


static int NetDbgInit(void)
{
    /* 初始化socket */

    int iRet;
    
    g_iSocketServer = socket(AF_INET, SOCK_DGRAM, 0);
    if (-1 == g_iSocketServer)
    {
        printf("socket error!\n");
        return -1;
    }

    g_tSocketServerAddr.sin_family      = AF_INET;
    g_tSocketServerAddr.sin_port        = htons(SERVER_PORT);  /* host to net, short */
     g_tSocketServerAddr.sin_addr.s_addr = INADDR_ANY;
    memset(g_tSocketServerAddr.sin_zero, 0, 8);
    
    iRet = bind(g_iSocketServer, (const struct sockaddr *)&g_tSocketServerAddr, sizeof(struct sockaddr));
    if (-1 == iRet)
    {
        printf("bind error!\n");
        return -1;
    }

    g_pcNetPrintBuf = malloc(PRINT_BUF_SIZE);
    if(NULL == g_pcNetPrintBuf)
    {
        close(g_iSocketServer);
        return -1;
    }

    /* 创建netprint发送线程: 它用来发送打印信息给客户端 */
    pthread_create(&g_tSendTreadID, NULL, NetDbgSendTreadFunction, NULL);            

    /* 创建netprint接收线否: 用来接收控制信息,比如修改打印级别,打开/关闭打印 */
    pthread_create(&g_tRecvTreadID, NULL, NetDbgRecvTreadFunction, NULL);            
        
    return 0;
}

static int NetDbgExit(void)
 {
    /* 关闭socket,... */
    close(g_iSocketServer);
    free(g_pcNetPrintBuf);
 }

static int NetDbgPrint(char *strData)
 {
     /* 把数据放入环形缓冲区, */
    int i;
    
    for(i = 0; i < strlen(strData); i++)
    {
        if(0 != PutData(strData[i]))
            break;
    }
    
    /* 如果已经有客户端连接了, 就把数据通过网络发送给客户端 */
    /* 唤醒netprint的发送线程 */
    pthread_mutex_lock(&g_tNetDbgSendMutex);
    pthread_cond_signal(&g_tNetDbgSendConVar);
    pthread_mutex_unlock(&g_tNetDbgSendMutex);

    return i;
    
 }


static T_DebugOpr g_tNetDbgOpr = {
    .name       = "netprint",
    .isCanUse   = 1,
    .DebugInit  = NetDbgInit,
    .DebugExit  = NetDbgExit,
    .DebugPrint = NetDbgPrint,
};

int NetPrintInit(void)
{
    return RegisterDebugOpr(&g_tNetDbgOpr);
}

 

netprint_client.c

#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <stdio.h>
#include <signal.h>



/*socket
* connet
* send/recv
*/
#define SERVER_PORT 5678

/*
 * ./netprint_client <server_ip> dbglevel=<0-9>
 * ./netprint_client <server_ip> stdout=0|1
 * ./netprint_client <server_ip> netprint=0|1
 * ./netprint_client <server_ip> show // setclient,²¢ÇÒ½ÓÊÕ´òÓ¡ÐÅÏ¢
 */


int main(int argc, char **argv)
{
    int iSocketClient;
    struct sockaddr_in tSocketServerAddr;

    int iRet;
    unsigned char ucRecvBuf[1000];
    int iSendLen;
    int iAddrLen;
    int iRecvLen;
    if (argc != 3)
    {
        printf("Usage:\n");
        printf("%s <server_ip> dbglevel=<0-9>\n", argv[0]);
        printf("%s <server_ip> stdout=0|1\n", argv[0]);
        printf("%s <server_ip> netprint=0|1\n", argv[0]);
        printf("%s <server_ip> show\n", argv[0]);
        return -1;
    }

    
    iSocketClient = socket(AF_INET, SOCK_DGRAM, 0);
    
    tSocketServerAddr.sin_family      = AF_INET;
    tSocketServerAddr.sin_port        = htons(SERVER_PORT);   /* host to net ,short */
    if(0 == inet_aton(argv[1], &tSocketServerAddr.sin_addr))  /* ±¾»úÉϵÄËùÓÐIP */
    {
        printf("invalid server_ip\n");
        return -1;
    }
    memset(tSocketServerAddr.sin_zero, 0, 8);                  /* ÉèÖÃÎÞÓõĿռäΪ0 */


    if (strcmp(argv[2], "show") == 0)
    {
        /* ·¢ËÍÊý¾Ý */
        iAddrLen = sizeof(struct sockaddr);
        iSendLen = sendto(iSocketClient, "setclient", 9, 0,
                              (const struct sockaddr *)&tSocketServerAddr, iAddrLen);

        while (1)
        {
            /* Ñ­»·: ´ÓÍøÂç¶ÁÊý¾Ý, ´òÓ¡³öÀ´ */
            iAddrLen = sizeof(struct sockaddr);
            iRecvLen = recvfrom(iSocketClient, ucRecvBuf, 999, 0, (struct sockaddr *)&tSocketServerAddr, &iAddrLen);
            if (iRecvLen > 0)
            {
                ucRecvBuf[iRecvLen] = '\0';
                printf("%s\n", ucRecvBuf);
            }
        }
    }
    else
    {
        /* ·¢ËÍÊý¾Ý */
        iAddrLen = sizeof(struct sockaddr);
        iSendLen = sendto(iSocketClient, argv[2], strlen(argv[2]), 0,
                              (const struct sockaddr *)&tSocketServerAddr, iAddrLen);
    }


    return 0;
}
posted @ 2016-04-09 15:53  CAM&  阅读(505)  评论(0编辑  收藏  举报