#include #include #include #include #include #include #include #include #include #include #include volatile int sockfd = 0; typedef void (*CommandHandler)(char*); // Определяем тип функции преобразования typedef void (*ConvertFunc)(char *str, void *output); void handleCloseSignal(int signal); void handleFreqCmd(char* recvBuff); void handleLdCmd(char* recvBuff); void handlePowCmd(char* recvBuff); void handleArmCmd(char* recvBuff); void handleAttCmd(char* recvBuff); void handleIdnCmd(char* recvBuff); void processCommand(char* recvBuff); void convertToUInt16(char *str, void *output); void convertToUint64(char *str, void *output); void convertToDouble(char *str, void *output); void splitLexeme(uint8_t *ptrSCPI, void *numOutAndValue, size_t elementSize, ConvertFunc convertFunc); //Обработчик ошибок void error(const char *msg) { perror(msg); if (sockfd != 0) { close(sockfd); } exit(1); } //Обработчик сигнала SIGINT завершения программы при нажатии Ctrl+C void handleCloseSignal(int signal) { if (signal == SIGINT) { printf("\nCaught signal %d, closing socket and exiting...\n", signal); if (sockfd != 0) { close(sockfd); } exit(0); } } //handleXXXXCmd - обработчики команд void handleFreqCmd(char* recvBuff) { printf("\nTMSG44:FREQ\n"); uint64_t freq[1] = {0}; splitLexeme(recvBuff, freq, sizeof(freq[0]), convertToUint64); printf("%" PRId64 "\n", freq[0]); } void handleLdCmd(char* recvBuff) { printf("\nTMSG44:LD?\n"); } void handlePowCmd(char* recvBuff) { printf("\nTMSG44:POW\n"); double pow[1] = {0}; splitLexeme(recvBuff, pow, sizeof(pow[0]), convertToDouble); printf("%f\n", pow[0]); } void handleArmCmd(char* recvBuff) { printf("\nTMSG44:ARM\n"); uint16_t armCode[1] = {0}; splitLexeme(recvBuff, armCode, sizeof(armCode[0]), convertToUInt16); printf("\n%u\n", armCode[0]); } void handleAttCmd(char* recvBuff) { printf("\nTMSG44:ATT\n"); uint16_t attCode[1] = {0}; splitLexeme(recvBuff, attCode, sizeof(attCode[0]), convertToUInt16); printf("\n%u\n", attCode[0]); } void handleIdnCmd(char* recvBuff) { printf("\n*IDN?\n"); } typedef struct { const char* command; CommandHandler handler; } Command; //Массив структур Command, который связывает строки команд с соответствующими функциями. Command commands[] = { {"TMSG44:FREQ ", handleFreqCmd}, {"TMSG44:LD?", handleLdCmd}, {"TMSG44:POW ", handlePowCmd}, {"TMSG44:ARM ", handleArmCmd}, {"TMSG44:ATT ", handleAttCmd}, {"*IDN?", handleIdnCmd}, {NULL, NULL} // Завершающий элемент для обозначения конца массива }; //Проходим по массиву команд и ищем команду, которая совпадает с началом строки recvBuff. //Если команда найдена, вызывается соответствующая функция-обработчик void processCommand(char* recvBuff) { for (int i = 0; commands[i].command != NULL; i++) { if (!strncasecmp(recvBuff, commands[i].command, strlen(commands[i].command))) { commands[i].handler(recvBuff); return; } } printf("\nUnknown command: %s\n", recvBuff); } //=========================================================// // Преобразование строки в uint16_t void convertToUInt16(char *str, void *output) { *(uint16_t *)output = (uint16_t)strtoul(str, NULL, 10); } // Преобразование строки в unsigned long long int void convertToUint64(char *str, void *output) { *(uint64_t *)output = (uint64_t)strtoull(str, NULL, 10); } // Преобразование строки в double void convertToDouble(char *str, void *output) { *(double *)output = strtod(str, NULL); } // Универсальная функция для разделения строки на лексемы void splitLexeme(uint8_t *ptrSCPI, void *numOutAndValue, size_t elementSize, ConvertFunc convertFunc) { uint8_t counter = 0; // Разделители лексем char charSeparator[3] = {' ', '\n', '\\'}; char *ptrLexeme = NULL; // Инициализируем функцию ptrLexeme = strtok((char *)ptrSCPI, charSeparator); // Ищем лексемы разделенные разделителем ptrLexeme = strtok(NULL, charSeparator); // Ищем лексемы строки while (ptrLexeme) { // Проверяем, является ли первый символ лексемы числом if(('0' <= ptrLexeme[0]) && (ptrLexeme[0] <= '9')) { // Преобразуем строку с числом в число convertFunc(ptrLexeme, (uint8_t *)numOutAndValue + counter * elementSize); counter++; } // Ищем лексемы разделенные разделителем ptrLexeme = strtok(NULL, charSeparator); } } //====================================================// int main(int argc, char *argv[]) { //argv[1] = "127.0.0.1"; int n = 0; char recvBuff[1024]; struct sockaddr_in serv_addr; // Установка обработчика сигналов signal(SIGINT, handleCloseSignal); if(argc != 2) { printf("\n Usage: %s \n",argv[0]); return 1; } memset(recvBuff, '0',sizeof(recvBuff)); if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { error("Error : Could not create socket"); } memset(&serv_addr, '0', sizeof(serv_addr)); serv_addr.sin_family = AF_INET; serv_addr.sin_port = htons(5000); if (inet_pton(AF_INET, argv[1], &serv_addr.sin_addr) <= 0) { error("inet_pton error occured"); } if (connect(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) { error("Error : Connect Failed"); } while ((n = read(sockfd, recvBuff, sizeof(recvBuff) - 1)) > 0) { recvBuff[n] = 0; if(fputs(recvBuff, stdout) == EOF) { printf("\n Error : Fputs error\n"); break; } //Запуск парсера команд processCommand(recvBuff); } if (n == 0) { // Соединение закрыто сервером printf("\n Server closed the connection\n"); } else if (n < 0) { error("Read error"); } close(sockfd); return 0; }