udpserver.c 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204
  1. /*
  2. * Copyright (c) 2006-2021, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. */
  9. #include <rtthread.h>
  10. #include <string.h>
  11. #if !defined(SAL_USING_POSIX)
  12. #error "Please enable SAL_USING_POSIX!"
  13. #else
  14. #include <sys/time.h>
  15. #include <sys/select.h>
  16. #endif
  17. #include <sys/socket.h> /* 使用BSD socket,需要包含socket.h头文件 */
  18. #include "netdb.h"
  19. #define DEBUG_UDP_SERVER
  20. #define DBG_TAG "UDP"
  21. #ifdef DEBUG_UDP_SERVER
  22. #define DBG_LVL DBG_LOG
  23. #else
  24. #define DBG_LVL DBG_INFO /* DBG_ERROR */
  25. #endif
  26. #include <rtdbg.h>
  27. #define BUFSZ 1024
  28. static int started = 0;
  29. static int is_running = 0;
  30. static int port = 5000;
  31. static void udpserv(void *paramemter)
  32. {
  33. int sock;
  34. int bytes_read;
  35. char *recv_data;
  36. socklen_t addr_len;
  37. struct sockaddr_in server_addr, client_addr;
  38. struct timeval timeout;
  39. fd_set readset;
  40. /* 分配接收用的数据缓冲 */
  41. recv_data = rt_malloc(BUFSZ);
  42. if (recv_data == RT_NULL)
  43. {
  44. LOG_E("No memory");
  45. return;
  46. }
  47. /* 创建一个socket,类型是SOCK_DGRAM,UDP类型 */
  48. if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
  49. {
  50. LOG_E("Create socket error");
  51. goto __exit;
  52. }
  53. /* 初始化服务端地址 */
  54. server_addr.sin_family = AF_INET;
  55. server_addr.sin_port = htons(port);
  56. server_addr.sin_addr.s_addr = INADDR_ANY;
  57. rt_memset(&(server_addr.sin_zero), 0, sizeof(server_addr.sin_zero));
  58. /* 绑定socket到服务端地址 */
  59. if (bind(sock, (struct sockaddr *)&server_addr,
  60. sizeof(struct sockaddr)) == -1)
  61. {
  62. LOG_E("Unable to bind");
  63. goto __exit;
  64. }
  65. addr_len = sizeof(struct sockaddr);
  66. LOG_I("UDPServer Waiting for client on port %d...", port);
  67. started = 1;
  68. is_running = 1;
  69. timeout.tv_sec = 3;
  70. timeout.tv_usec = 0;
  71. while (is_running)
  72. {
  73. FD_ZERO(&readset);
  74. FD_SET(sock, &readset);
  75. /* Wait for read or write */
  76. if (select(sock + 1, &readset, RT_NULL, RT_NULL, &timeout) == 0)
  77. continue;
  78. /* 从sock中收取最大BUFSZ - 1字节数据 */
  79. bytes_read = recvfrom(sock, recv_data, BUFSZ - 1, 0,
  80. (struct sockaddr *)&client_addr, &addr_len);
  81. if (bytes_read < 0)
  82. {
  83. LOG_E("Received error, close the connect.");
  84. goto __exit;
  85. }
  86. else if (bytes_read == 0)
  87. {
  88. LOG_W("Received warning, recv function return 0.");
  89. continue;
  90. }
  91. else
  92. {
  93. recv_data[bytes_read] = '\0'; /* 把末端清零 */
  94. /* 输出接收的数据 */
  95. LOG_D("Received data = %s", recv_data);
  96. /* 如果接收数据是exit,退出 */
  97. if (strcmp(recv_data, "exit") == 0)
  98. {
  99. goto __exit;
  100. }
  101. }
  102. }
  103. __exit:
  104. if (recv_data)
  105. {
  106. rt_free(recv_data);
  107. recv_data = RT_NULL;
  108. }
  109. if (sock >= 0)
  110. {
  111. closesocket(sock);
  112. sock = -1;
  113. }
  114. started = 0;
  115. is_running = 0;
  116. }
  117. static void usage(void)
  118. {
  119. rt_kprintf("Usage: udpserver -p <port>\n");
  120. rt_kprintf(" udpserver --stop\n");
  121. rt_kprintf(" udpserver --help\n");
  122. rt_kprintf("\n");
  123. rt_kprintf("Miscellaneous:\n");
  124. rt_kprintf(" -p Specify the host port number\n");
  125. rt_kprintf(" --stop Stop udpserver program\n");
  126. rt_kprintf(" --help Print help information\n");
  127. }
  128. static void udpserver_test(int argc, char** argv)
  129. {
  130. rt_thread_t tid;
  131. if (argc == 1 || argc > 3)
  132. {
  133. LOG_I("Please check the command you entered!\n");
  134. goto __usage;
  135. }
  136. else
  137. {
  138. if (rt_strcmp(argv[1], "--help") == 0)
  139. {
  140. goto __usage;
  141. }
  142. else if (rt_strcmp(argv[1], "--stop") == 0)
  143. {
  144. is_running = 0;
  145. return;
  146. }
  147. else if (rt_strcmp(argv[1], "-p") == 0)
  148. {
  149. if (started)
  150. {
  151. LOG_I("The udpserver has started!");
  152. LOG_I("Please stop udpserver firstly, by: udpserver --stop");
  153. return;
  154. }
  155. port = atoi(argv[2]);
  156. }
  157. else
  158. {
  159. goto __usage;
  160. }
  161. }
  162. tid = rt_thread_create("udp_serv",
  163. udpserv, RT_NULL,
  164. 2048, RT_THREAD_PRIORITY_MAX/3, 20);
  165. if (tid != RT_NULL)
  166. {
  167. rt_thread_startup(tid);
  168. }
  169. return;
  170. __usage:
  171. usage();
  172. }
  173. #ifdef RT_USING_FINSH
  174. MSH_CMD_EXPORT_ALIAS(udpserver_test, udpserver,
  175. Start a udp server. Help: udpserver --help);
  176. #endif