6.2遠程列印

来源:http://www.cnblogs.com/CZM-/archive/2016/04/09/5371797.html
-Advertisement-
Play Games

因為串口列印速度慢,調試程式會影響程式的真正效果,所以引入網路列印 debug_manager.h #ifndef _DEBUG_MANAGER_H #define _DEBUG_MANAGER_H #define APP_EMERG "" /* system is unusable */ #def... ...


因為串口列印速度慢,調試程式會影響程式的真正效果,所以引入網路列印

 

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;
}

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 龍果學院 講師:吳水成 三、高可用架構篇 第13節--MySQL源碼編譯安裝(CentOS-6.6+MySQL-5.6) 第14節--MySQL主從複製的配置(CentOS-6.6+MySQL-5.6) 第15節--MyCat在MySQL主從複製基礎上實現讀寫分離 第16節--MyCat集群部署(H ...
  • 前幾天被老大訓斥連openrowset 都不會用,然後我就去看了文檔,想測試一下慄子~ openrowset 的具體語法我就不貼了,戳這裡:https://msdn.microsoft.com/zh-cn/library/ms190312(v=sql.120).aspx 按照文檔裡面的樣例來測試,首 ...
  • 1. 安裝VSFTP 1 yum -y install vsftpd 2. 配置vsftpd.conf文件 1 # Example config file /etc/vsftpd/vsftpd.conf 2 # 3 # The default compiled in settings are fai ...
  • 1. 添加官方軟體庫 1) 編輯/etc/apt/sources.list 2) 用#註釋掉原有的內容,並添加下述內容: 3) 順序執行下列命令: 2. 添加中文輸入法 我的fcitx安裝之後不能正常使用,故最終還是安裝了ibus. 執行上述命令安裝結束後,在Region & Language 中的 ...
  • 上一篇我已經把zabbix server 和zabbix agent 安裝在了同一臺主機上,現在如何配置zabbix server監控自己。 vim /etc/zabbix/zabbix_agentd.conf 編輯agent配置文件。 指定那些伺服器可以來獲取數據,可用逗號隔開指定多台伺服器。 這 ...
  • 一、rsync 簡介 Rsync(remote synchronize)是一個遠程數據同步工具,可通過LAN/WAN快速同步多台主機間的文件,也可以使用 Rsync 同步本地硬碟中的不同目錄。 Rsync 是用於取代rcp的一個工具,Rsync使用所謂的 “Rsync 演算法” 來使本地和遠程兩個主機 ...
  • 重啟命令: 1、reboot 2、shutdown -r now 立刻重啟(root用戶使用) 3、shutdown -r 10 過10分鐘自動重啟(root用戶使用) 4、shutdown -r 20:35 在時間為20:35時候重啟(root用戶使用) 關機命令: 1、halt 立刻關機 2、p ...
  • Linux Free命令各數字含義及Buffer和Cache的區別 Free 命令的各數字含義 命令演示 加上參數 ,顯示的單位為MB 按行詳解 total :物理記憶體的實際總量 used :總計分配給緩存(buffer+cache)的使用的數量,但是其中部分可能並未實際使用(註意:這裡不是實際使用 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...