client.c 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249
  1. #include <sys/socket.h>
  2. #include <netinet/in.h>
  3. #include <stdio.h>
  4. #include <string.h>
  5. #include <strings.h>
  6. #include <stdlib.h>
  7. #include <unistd.h>
  8. #include <errno.h>
  9. #include <arpa/inet.h>
  10. #include <inttypes.h>
  11. #include <signal.h>
  12. volatile int sockfd = 0;
  13. typedef void (*CommandHandler)(char*);
  14. // Определяем тип функции преобразования
  15. typedef void (*ConvertFunc)(char *str, void *output);
  16. void handleCloseSignal(int signal);
  17. void handleFreqCmd(char* recvBuff);
  18. void handleLdCmd(char* recvBuff);
  19. void handlePowCmd(char* recvBuff);
  20. void handleArmCmd(char* recvBuff);
  21. void handleAttCmd(char* recvBuff);
  22. void handleIdnCmd(char* recvBuff);
  23. void processCommand(char* recvBuff);
  24. void convertToUInt16(char *str, void *output);
  25. void convertToUint64(char *str, void *output);
  26. void convertToDouble(char *str, void *output);
  27. void splitLexeme(uint8_t *ptrSCPI, void *numOutAndValue, size_t elementSize, ConvertFunc convertFunc);
  28. //Обработчик ошибок
  29. void error(const char *msg)
  30. {
  31. perror(msg);
  32. if (sockfd != 0)
  33. {
  34. close(sockfd);
  35. }
  36. exit(1);
  37. }
  38. //Обработчик сигнала SIGINT завершения программы при нажатии Ctrl+C
  39. void handleCloseSignal(int signal)
  40. {
  41. if (signal == SIGINT)
  42. {
  43. printf("\nCaught signal %d, closing socket and exiting...\n", signal);
  44. if (sockfd != 0)
  45. {
  46. close(sockfd);
  47. }
  48. exit(0);
  49. }
  50. }
  51. //handleXXXXCmd - обработчики команд
  52. void handleFreqCmd(char* recvBuff)
  53. {
  54. printf("\nTMSG44:FREQ\n");
  55. uint64_t freq[1] = {0};
  56. splitLexeme(recvBuff, freq, sizeof(freq[0]), convertToUint64);
  57. printf("%" PRId64 "\n", freq[0]);
  58. }
  59. void handleLdCmd(char* recvBuff)
  60. {
  61. printf("\nTMSG44:LD?\n");
  62. }
  63. void handlePowCmd(char* recvBuff)
  64. {
  65. printf("\nTMSG44:POW\n");
  66. double pow[1] = {0};
  67. splitLexeme(recvBuff, pow, sizeof(pow[0]), convertToDouble);
  68. printf("%f\n", pow[0]);
  69. }
  70. void handleArmCmd(char* recvBuff)
  71. {
  72. printf("\nTMSG44:ARM\n");
  73. uint16_t armCode[1] = {0};
  74. splitLexeme(recvBuff, armCode, sizeof(armCode[0]), convertToUInt16);
  75. printf("\n%u\n", armCode[0]);
  76. }
  77. void handleAttCmd(char* recvBuff)
  78. {
  79. printf("\nTMSG44:ATT\n");
  80. uint16_t attCode[1] = {0};
  81. splitLexeme(recvBuff, attCode, sizeof(attCode[0]), convertToUInt16);
  82. printf("\n%u\n", attCode[0]);
  83. }
  84. void handleIdnCmd(char* recvBuff)
  85. {
  86. printf("\n*IDN?\n");
  87. }
  88. typedef struct {
  89. const char* command;
  90. CommandHandler handler;
  91. } Command;
  92. //Массив структур Command, который связывает строки команд с соответствующими функциями.
  93. Command commands[] = {
  94. {"TMSG44:FREQ ", handleFreqCmd},
  95. {"TMSG44:LD?", handleLdCmd},
  96. {"TMSG44:POW ", handlePowCmd},
  97. {"TMSG44:ARM ", handleArmCmd},
  98. {"TMSG44:ATT ", handleAttCmd},
  99. {"*IDN?", handleIdnCmd},
  100. {NULL, NULL} // Завершающий элемент для обозначения конца массива
  101. };
  102. //Проходим по массиву команд и ищем команду, которая совпадает с началом строки recvBuff.
  103. //Если команда найдена, вызывается соответствующая функция-обработчик
  104. void processCommand(char* recvBuff)
  105. {
  106. for (int i = 0; commands[i].command != NULL; i++)
  107. {
  108. if (!strncasecmp(recvBuff, commands[i].command, strlen(commands[i].command)))
  109. {
  110. commands[i].handler(recvBuff);
  111. return;
  112. }
  113. }
  114. printf("\nUnknown command: %s\n", recvBuff);
  115. }
  116. //=========================================================//
  117. // Преобразование строки в uint16_t
  118. void convertToUInt16(char *str, void *output)
  119. {
  120. *(uint16_t *)output = (uint16_t)strtoul(str, NULL, 10);
  121. }
  122. // Преобразование строки в unsigned long long int
  123. void convertToUint64(char *str, void *output)
  124. {
  125. *(uint64_t *)output = (uint64_t)strtoull(str, NULL, 10);
  126. }
  127. // Преобразование строки в double
  128. void convertToDouble(char *str, void *output)
  129. {
  130. *(double *)output = strtod(str, NULL);
  131. }
  132. // Универсальная функция для разделения строки на лексемы
  133. void splitLexeme(uint8_t *ptrSCPI, void *numOutAndValue, size_t elementSize, ConvertFunc convertFunc)
  134. {
  135. uint8_t counter = 0;
  136. // Разделители лексем
  137. char charSeparator[3] = {' ', '\n', '\\'};
  138. char *ptrLexeme = NULL;
  139. // Инициализируем функцию
  140. ptrLexeme = strtok((char *)ptrSCPI, charSeparator);
  141. // Ищем лексемы разделенные разделителем
  142. ptrLexeme = strtok(NULL, charSeparator);
  143. // Ищем лексемы строки
  144. while (ptrLexeme) {
  145. // Проверяем, является ли первый символ лексемы числом
  146. if(('0' <= ptrLexeme[0]) && (ptrLexeme[0] <= '9')) {
  147. // Преобразуем строку с числом в число
  148. convertFunc(ptrLexeme, (uint8_t *)numOutAndValue + counter * elementSize);
  149. counter++;
  150. }
  151. // Ищем лексемы разделенные разделителем
  152. ptrLexeme = strtok(NULL, charSeparator);
  153. }
  154. }
  155. //====================================================//
  156. int main(int argc, char *argv[])
  157. {
  158. //argv[1] = "127.0.0.1";
  159. int n = 0;
  160. char recvBuff[1024];
  161. struct sockaddr_in serv_addr;
  162. // Установка обработчика сигналов
  163. signal(SIGINT, handleCloseSignal);
  164. if(argc != 2)
  165. {
  166. printf("\n Usage: %s <ip of server> \n",argv[0]);
  167. return 1;
  168. }
  169. memset(recvBuff, '0',sizeof(recvBuff));
  170. if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
  171. {
  172. error("Error : Could not create socket");
  173. }
  174. memset(&serv_addr, '0', sizeof(serv_addr));
  175. serv_addr.sin_family = AF_INET;
  176. serv_addr.sin_port = htons(5000);
  177. if (inet_pton(AF_INET, argv[1], &serv_addr.sin_addr) <= 0)
  178. {
  179. error("inet_pton error occured");
  180. }
  181. if (connect(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0)
  182. {
  183. error("Error : Connect Failed");
  184. }
  185. while ((n = read(sockfd, recvBuff, sizeof(recvBuff) - 1)) > 0)
  186. {
  187. recvBuff[n] = 0;
  188. if(fputs(recvBuff, stdout) == EOF)
  189. {
  190. printf("\n Error : Fputs error\n");
  191. break;
  192. }
  193. //Запуск парсера команд
  194. processCommand(recvBuff);
  195. }
  196. if (n == 0)
  197. {
  198. // Соединение закрыто сервером
  199. printf("\n Server closed the connection\n");
  200. }
  201. else if (n < 0)
  202. {
  203. error("Read error");
  204. }
  205. close(sockfd);
  206. return 0;
  207. }