首页 > 其他分享 >UDP实现cmd服务

UDP实现cmd服务

时间:2024-09-18 17:02:09浏览次数:1  
标签:UDP CMD return struct int cmd szBuffer 服务 TYPE

cmd_server.c

/*编译: gcc cmd_server.c -lpthread */
#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <pthread.h>
#include <stdarg.h>
#include <regex.h>
#include <stdbool.h>
#include <errno.h>
 

#define SOCKET_PORT_CMD_CLIENT 2001
#define SOCKET_PORT_CMD_SERVER 2002
#define LOCAL_ADDRESS ("127.0.0.1")
#define RECV_BUFFER_LEN 512

#define CMD_ELEMENT_MAX_LEN     128
#define CMD_ELEMENT_MAX_NUM     30
typedef struct {
    int socketFd;
    struct sockaddr_in stRemoteAddr;
}RECV_SOCK_DATA;

typedef struct
{
    char    szBuffer[CMD_ELEMENT_MAX_NUM][CMD_ELEMENT_MAX_LEN + 1];
    int strNum;
}CMD_S;


typedef int (*Callback)(CMD_S *pstCmd);
typedef struct
{
    CMD_S       stCmd;
    Callback pfCallBack;
}CMD_INFO_S;

typedef enum
{
    CMD_TYPE_PARAM_DEC,
    CMD_TYPE_PARAM_HEX,
    CMD_TYPE_PARAM_STRING,
    CMD_TYPE_PARAM_FLOAT,
    CMD_TYPE_CHAR,
    CMD_TYPE_UNKNOWN,
}CMD_TYPE_E;

typedef struct
{
    regex_t stFloat;    /* 浮点数正则 */
    regex_t stDec;      /* 整数正则 */
}CMD_MATCH_RULE_S;

static CMD_MATCH_RULE_S g_stMatchRule;  /* 正则匹配规则合集 */

CMD_INFO_S *pstCmdInfo = NULL;
RECV_SOCK_DATA *pstSockInfo = NULL;
static int cmdCount = 0;
void resultToClient(const char *pcFormat, ...)
{
    va_list stVaList = {0};
    int u32InfoLen = 0;
    
    char szBuffer[RECV_BUFFER_LEN] = {0};

    va_start(stVaList, pcFormat);
    u32InfoLen += vsnprintf(szBuffer, RECV_BUFFER_LEN, pcFormat, stVaList);
    va_end(stVaList);

    printf("send msg:%s\n", szBuffer);
    if(-1 == sendto(pstSockInfo->socketFd, szBuffer, strlen(szBuffer), 0, (struct sockaddr*)&pstSockInfo->stRemoteAddr, (socklen_t)sizeof(pstSockInfo->stRemoteAddr)))
    {
        printf("sendto msg:%s fail,errno:%d\n", szBuffer, errno);
    }
    return;
}
int add(CMD_S *pstCmd)
{
    resultToClient("%s + %s = %d\n", pstCmd->szBuffer[3], pstCmd->szBuffer[4], atoi(pstCmd->szBuffer[3]) + atoi(pstCmd->szBuffer[4]));
    return 0;
}
int sub(CMD_S *pstCmd)
{
    resultToClient("%s - %s = %d\n", pstCmd->szBuffer[3], pstCmd->szBuffer[4], atoi(pstCmd->szBuffer[3]) - atoi(pstCmd->szBuffer[4]));
    return 0;
}
static CMD_TYPE_E cmd_cli_GetClientElementType(char *pcParam)
{
    if(!pcParam)
    {
        return CMD_TYPE_UNKNOWN;
    }

    if((0 == strncmp(pcParam, "0x", strlen("0x"))) || (0 == strncmp(pcParam, "0X", strlen("0X"))))
    {
        return CMD_TYPE_PARAM_HEX;
    }
    else if(0 == regexec(&g_stMatchRule.stDec, pcParam, 0, NULL, 0))
    {
        return CMD_TYPE_PARAM_DEC;
    }
    else if(0 == regexec(&g_stMatchRule.stFloat, pcParam, 0, NULL, 0))
    {
        return CMD_TYPE_PARAM_FLOAT;
    }

    return CMD_TYPE_CHAR;
}

static CMD_TYPE_E cmd_cli_GetServerElementType(char *pcParam)
{
    if(!pcParam)
    {
        return CMD_TYPE_UNKNOWN;
    }

    if(0 == strncmp(pcParam, "DEC", strlen("DEC")))
    {
        return CMD_TYPE_PARAM_DEC;
    }
    else if(0 == strncmp(pcParam, "HEX", strlen("HEX")))
    {
        return CMD_TYPE_PARAM_HEX;
    }
    else if(0 == strncmp(pcParam, "STRING", strlen("STRING")))
    {
        return CMD_TYPE_PARAM_STRING;
    }
    else if(0 == strncmp(pcParam, "FLOAT", strlen("FLOAT")))
    {
        return CMD_TYPE_PARAM_FLOAT;
    }

    return CMD_TYPE_CHAR;
}
static bool cmd_param_Match(CMD_S *pstClientCmd, CMD_S *pstServerCmd)
{
    int u32Index = 0;
    CMD_TYPE_E enClientElementType, enServerElementType;
    
    if(!pstClientCmd || !pstServerCmd)
    {
        printf("Input param is null\n");
        return false;
    }

    if(pstClientCmd->strNum != pstServerCmd->strNum)
    {
        return false;
    }

    for(u32Index = 0; u32Index < pstClientCmd->strNum; u32Index++)
    {
        enClientElementType = cmd_cli_GetClientElementType(pstClientCmd->szBuffer[u32Index]);
        enServerElementType = cmd_cli_GetServerElementType(pstServerCmd->szBuffer[u32Index]);
        if(CMD_TYPE_CHAR == enServerElementType)
        {
            /* POSIX 系统 */
            if (0 != strcasecmp(pstClientCmd->szBuffer[u32Index], pstServerCmd->szBuffer[u32Index]))
            {
                return false;
            }
        }
        else if((CMD_TYPE_PARAM_DEC == enServerElementType) || (CMD_TYPE_PARAM_HEX == enServerElementType) || (CMD_TYPE_PARAM_FLOAT == enServerElementType))
        {
            /*元素是10进制或者16进制、小数,类型不同,匹配失败*/
            if(enClientElementType != enServerElementType)
            {
                return false;
            }
        }
        else if(CMD_TYPE_PARAM_STRING == enServerElementType)
        {
            /*server命令的元素是字符串参数类型,如果client命令的元素不是字符串,匹配失败*/
            if(CMD_TYPE_CHAR != enClientElementType)
            {
                return false;
            }
        }
    }
    return true;
}


void * recvMsgFunc(void * arg)
{
    RECV_SOCK_DATA *data = (RECV_SOCK_DATA *)arg;
#if 0
    CMD_INFO_S stCmdInfo;
    stCmdInfo.pfCallBack = add;
#endif
    int u32RecvLen = 0;
    char  szBuffer[RECV_BUFFER_LEN];
    CMD_S stCmd;
    int i32RecvLen = 0;
    int u32AddrLen = 0;
    struct sockaddr_in stRemoteAddr = {0};
    char *str_ptr;
    char *token;
    int paramNum = 0;
    bool bMatch = false;
    while(1)
    {
        memset(szBuffer, 0, RECV_BUFFER_LEN);
        memset(&stCmd, 0, sizeof(CMD_S));    

        u32AddrLen = sizeof(stRemoteAddr);
        i32RecvLen = recvfrom(data->socketFd, szBuffer, RECV_BUFFER_LEN, 0, (struct sockaddr *)&stRemoteAddr, &u32AddrLen);
        if(i32RecvLen > 0)
        {
            printf("recv msg:%s\n", szBuffer);
            paramNum = 0;
            str_ptr = szBuffer;
            while(NULL != (token = strsep(&str_ptr, " ")))
            {
                printf("token:%s\n", token);
                memcpy(stCmd.szBuffer[paramNum++], token, strlen(token));
                stCmd.strNum += 1;
            }
            
            bMatch = false;
            for(int i = 0; i < cmdCount; i++)
            {
                if (cmd_param_Match(&stCmd, &pstCmdInfo[i].stCmd))
                {
                    pstCmdInfo[i].pfCallBack(&stCmd);
                    bMatch = true;
                    break;                    
                }
            }
            if (!bMatch)
            {
                resultToClient("no support cmd in server\n");
            }
        }
    }

    return NULL;
}
int main(int argc, char *argv[])
{ 
    int opt = 0;
    int socketFd = -1;
    struct sockaddr_in stAddr;
    struct sockaddr_in stClientAddr;
    struct timeval stTimeInterval = {3,0};
    
    int recvlen = 0;
    int addrlen = 0;
    struct sockaddr_in stRemoteAddr = {0};
    char szBuffer[RECV_BUFFER_LEN] = {0};
    RECV_SOCK_DATA stSockInfo;
    
    pthread_t       theadID;
    
    CMD_INFO_S stInfos[] = {
        { {{"st", "cal", "add", "DEC<a[0~10]>", "DEC<b[0~10]>"}, 5},             add },
        { {{"st", "cal", "sub", "DEC<a[0~10]>", "DEC<b[0~10]>"}, 5},             sub },
    };
    pstCmdInfo = stInfos;
    cmdCount = sizeof(stInfos) / sizeof(stInfos[0]);
    if (regcomp(&g_stMatchRule.stDec, "^-?[0-9]+$", REG_NOSUB | REG_EXTENDED) != 0)
    {
        printf("precompiled DEC failed\n");
        return -1;
    }

    if (regcomp(&g_stMatchRule.stFloat, "^-?[0-9]+\\.[0-9]+$", REG_NOSUB | REG_EXTENDED) != 0)
    {
        printf("precompiled FLOAT failed\n");
        return -1;
    }
    
    
    if (0 > (socketFd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)))
    {
        printf("create socket error, errno(%d)\n",errno);
        return -1;
    }
    memset(&stAddr, 0, sizeof(stAddr));
    stAddr.sin_family = AF_INET;
    stAddr.sin_port = htons(SOCKET_PORT_CMD_SERVER);
    stAddr.sin_addr.s_addr = inet_addr(LOCAL_ADDRESS);
    if(0 != setsockopt(socketFd, SOL_SOCKET, SO_REUSEADDR, (const void*)&opt, sizeof(opt)))
    {
        printf("setsockopt error, errno(%d)\n",errno);
        return -1;
    }
    if(0 > bind(socketFd, (struct sockaddr*)&stAddr, sizeof(struct sockaddr)))
    {
        printf("bind error, errno(%d)\n",errno);
        return -1;
    }
    if(0 != setsockopt(socketFd, SOL_SOCKET, SO_RCVTIMEO, &stTimeInterval, sizeof(struct timeval)))
    {
        printf("setsockopt error, errno(%d)\n",errno);
        return -1;
    }

    memset(&stSockInfo, 0, sizeof(stSockInfo));
    stSockInfo.socketFd = socketFd;
    stSockInfo.stRemoteAddr.sin_family = AF_INET;
    stSockInfo.stRemoteAddr.sin_port = htons(SOCKET_PORT_CMD_CLIENT);
    pstSockInfo = &stSockInfo;
    if (0 != pthread_create(&theadID, NULL, recvMsgFunc, (void*)&stSockInfo))
    {
   
        perror("create thread failed\n");
        return -1;
    }
    pthread_detach(theadID);
    while(1)
    {
        sleep(200);
    }
    printf("recv error\n");
    return 0;
}

 

标签:UDP,CMD,return,struct,int,cmd,szBuffer,服务,TYPE
From: https://www.cnblogs.com/tianxincode/p/18418894

相关文章

  • 武汉星起航:深耕电商多年,一站式孵化服务引领跨境电商新潮流
       在当今全球贸易格局不断演变、跨境电商风起云涌的时代背景下,武汉星起航电子商务有限公司以其独特的自身优势,引领着众多跨境电商创业者穿越迷雾,驶向成功的彼岸。武汉星起航不仅是一家自营亚马逊的佼佼者,更是国内领先的亚马逊卖家孵化服务提供商,其背后的故事与成就,无不彰显......
  • 高性能服务器适合哪些应用场景
    高性能服务器通常指的是具备强大计算能力、高内存容量、快速I/O处理能力以及高度可靠性的服务器系统。它们适合运行要求严格的计算任务和关键业务应用。以下是一些高性能服务器适合的应用场景:企业级数据库系统:如Oracle,SQLServer,MySQL等大型数据库,需要高性能服务器来处理大量的......
  • 通过 NSSM 把 FastAPI+Celery+Flower 注册成 3个Windos 服务
    通过NSSM把FastAPI+Celery+Flower注册成3个Windos服务什么是nssm?是一个服务封装程序,它可以将普通exe程序封装成服务,实现开机自启动,同类型的工具还有微软自己的srvany,不过nssm更加简单易用,并且功能强大。nssm官网nssm常用命令nssminstallservername//创建servername......
  • 怎么看服务器的ip访问记录
    查看服务器的IP访问记录通常涉及到检查服务器的日志文件。这些日志文件记录了所有到达服务器的请求,包括访问者的IP地址、访问时间、请求类型和响应状态等。以下是几种不同服务器环境中查看IP访问记录的方法:对于Web服务器:Apache服务器:访问日志:通常位于/var/log/apache2/access.log(......
  • Nginx-HTTP和反向代理web服务器
    概述Nginx(enginex)是一个高性能的HTTP和反向代理web服务器,同时也提供了IMAP/POP3/SMTP服务。Nginx是由伊戈尔·赛索耶夫为俄罗斯访问量第二的Rambler.ru站点(俄文:Рамблер)开发的,公开版本1.19.6发布于2020年12月15日。其将源代码以类BSD许可证的形式发布,因它的稳......
  • zblogPHP后台在线升级后提示Call to undefined function Redirect_cmd_end()错误
    当Z-BlogPHP在线升级后提示“CalltoundefinedfunctionRedirect_cmd_end()”错误时,这通常是因为升级过程中某些文件没有正确更新或存在兼容性问题。以下是一些可能的解决步骤:1.检查函数定义问题描述:Redirect_cmd_end() 函数可能未被定义。解决方法:打开Z-BlogPHP......
  • Hydra(海德拉)工具使用从0到1,爆破服务器密码,2024最新版
    Hydra简介Hydra又叫九头蛇,是一款由著名的黑客组织THC开发的开源暴力破解工具,支持大部分协议的在线密码破解,是网络安全·渗透测试必备的一款工具,目前支持的协议包括Asterisk,AFP,CiscoAAA,Ciscoauth,Ciscoenable,CVS,Firebird,FTP,HTTP-FORM-GET,HTTP-FORM-POST,HT......
  • Electron加载服务器端JS:高效打造跨平台桌面应用与本地 API 交互
    在现代桌面应用开发中,使用Electron加载远程服务器托管的前端资源,再与本地API交互,能够带来灵活的部署和强大的本地功能支持。这种方式不仅提升了开发效率,还能充分利用PC端的资源和性能。本文将深入解析如何使用Electron实现这一架构,并探讨其背后的关键技术,包括ipcMain和......
  • 支持 10 万同时在线量的服务器需要多大的宽带?
    支持10万同时在线用户的服务器所需的带宽取决于多种因素,包括用户的平均数据使用量、活动类型(如视频流、文件下载或网页浏览)、内容的大小和复杂性等。以下是一些估计和考虑因素:平均带宽需求估计:网页浏览:通常需要的带宽较少,假设平均每个用户需要100kbps,则10万用户大约需要10,000*1......
  • 助力园区数字化转型,合合信息市北高新园区打造“一企一画像”个性化服务
    在数字化时代的浪潮中,产业园区的数字化转型已成为推动经济发展、提升管理效率和增强竞争力的关键因素。上海市市北高新技术服务业园区(以下简称“市北高新园区”)携手合合信息旗下启信产业大脑™推出“一企一画像”创新平台,在国内率先探索产业园区数字化转型发展新路径。该平台展现......