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