浏览代码

[examples][network] 更新 UDP client & server

Signed-off-by: MurphyZhao <d2014zjt@163.com>
MurphyZhao 6 年之前
父节点
当前提交
b2d4dd0ba7
共有 2 个文件被更改,包括 264 次插入44 次删除
  1. 123 12
      examples/network/udpclient.c
  2. 141 32
      examples/network/udpserver.c

+ 123 - 12
examples/network/udpclient.c

@@ -1,11 +1,28 @@
 #include <rtthread.h>
-//#include <lwip/netdb.h> /* 为了解析主机名,需要包含netdb.h头文件 */
-//#include <lwip/sockets.h> /* 使用BSD socket,需要包含sockets.h头文件 */
+
 #include <sys/socket.h> /* 使用BSD socket,需要包含sockets.h头文件 */
 #include "netdb.h"
 
+#define DEBUG_UDP_CLIENT
+
+#define DBG_ENABLE
+#define DBG_SECTION_NAME               "UDP"
+#ifdef DEBUG_UDP_CLIENT
+#define DBG_LEVEL                      DBG_LOG
+#else
+#define DBG_LEVEL                      DBG_INFO /* DBG_ERROR */
+#endif
+#define DBG_COLOR
+#include <rtdbg.h>
+
+static int started = 0;
+static int is_running = 0;
+static char url[256];
+static int port = 8080;
+static int count = 10;
 const char send_data[] = "This is UDP Client from RT-Thread.\n"; /* 发送用到的数据 */
-void udpclient(const char *url, int port, int count)
+
+static void udpclient(void *arg)
 {
     int sock;
     struct hostent *host;
@@ -13,11 +30,16 @@ void udpclient(const char *url, int port, int count)
 
     /* 通过函数入口参数url获得host地址(如果是域名,会做域名解析) */
     host = (struct hostent *) gethostbyname(url);
+    if (host == RT_NULL)
+    {
+        LOG_E("Get host by name failed!");
+        return;
+    }
 
     /* 创建一个socket,类型是SOCK_DGRAM,UDP类型 */
-    if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
+    if ((sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1)
     {
-        rt_kprintf("Socket error\n");
+        LOG_E("Create socket error");
         return;
     }
 
@@ -27,26 +49,115 @@ void udpclient(const char *url, int port, int count)
     server_addr.sin_addr = *((struct in_addr *)host->h_addr);
     rt_memset(&(server_addr.sin_zero), 0, sizeof(server_addr.sin_zero));
 
+    started = 1;
+    is_running = 1;
+
     /* 总计发送count次数据 */
-    while (count)
+    while (count && is_running)
     {
         /* 发送数据到服务远端 */
-        sendto(sock, send_data, strlen(send_data), 0,
+        sendto(sock, send_data, rt_strlen(send_data), 0,
                (struct sockaddr *)&server_addr, sizeof(struct sockaddr));
 
         /* 线程休眠一段时间 */
-        rt_thread_delay(50);
+        rt_thread_mdelay(1000);
 
         /* 计数值减一 */
         count --;
     }
 
+    if (count == 0)
+    {
+        LOG_I("UDP client send data finished!");
+    }
+
     /* 关闭这个socket */
-    closesocket(sock);
+    if (sock >= 0)
+    {
+        closesocket(sock);
+        sock = -1;
+    }
+    started = 0;
+    is_running = 0;
+}
+
+static void usage(void)
+{
+    LOG_I("Usage: udpclient -h <host> -p <port> [--cnt] [count]");
+    LOG_I("       udpclient --stop");
+    LOG_I("       udpclient --help");
+    LOG_I("");
+    LOG_I("Miscellaneous:");
+    LOG_I("  -h           Specify host address");
+    LOG_I("  -p           Specify the host port number");
+    LOG_I("  --cnt        Specify the send data count");
+    LOG_I("  --stop       Stop tcpclient program");
+    LOG_I("  --help       Print help information");
+}
+
+static void udpclient_test(int argc, char** argv)
+{
+    rt_thread_t tid;
+
+    if (argc == 1 || argc > 7)
+    {
+        LOG_I("Please check the command you entered!\n");
+        goto __usage;
+    }
+    else
+    {
+        if (rt_strcmp(argv[1], "--help") == 0)
+        {
+            goto __usage;
+        }
+        else if (rt_strcmp(argv[1], "--stop") == 0)
+        {
+            is_running = 0;
+            return;
+        }
+        else if (rt_strcmp(argv[1], "-h") == 0 && rt_strcmp(argv[3], "-p") == 0)
+        {
+            if (started)
+            {
+                LOG_I("The tcpclient has started!");
+                LOG_I("Please stop tcpclient firstly, by: tcpclient --stop");
+                return;
+            }
+
+            if (argc == 7 && rt_strcmp(argv[6], "--cnt") == 0)
+            {
+                count = atoi(argv[7]);
+            }
+
+            if (rt_strlen(argv[2]) > sizeof(url))
+            {
+                LOG_E("The input url is too long, max %d bytes!", sizeof(url));
+                return;
+            }
+            rt_memset(url, 0x0, sizeof(url));
+            rt_strncpy(url, argv[2], rt_strlen(argv[2]));
+            port = atoi(argv[4]);
+        }
+        else
+        {
+            goto __usage;
+        }
+    }
+
+    tid = rt_thread_create("udp_client",
+        udpclient, RT_NULL,
+        2048, RT_THREAD_PRIORITY_MAX/3, 20);
+    if (tid != RT_NULL)
+    {
+        rt_thread_startup(tid);
+    }
+    return;
+
+__usage:
+    usage();
 }
 
 #ifdef RT_USING_FINSH
-#include <finsh.h>
-/* 输出udpclient函数到finsh shell中 */
-FINSH_FUNCTION_EXPORT(udpclient, startup udp client);
+MSH_CMD_EXPORT_ALIAS(udpclient_test, udpclient,
+    Start a udp client. Help: udpclient --help);
 #endif

+ 141 - 32
examples/network/udpserver.c

@@ -1,10 +1,33 @@
 #include <rtthread.h>
+#include <string.h>
 
+#if !defined(SAL_USING_POSIX)
+#error "Please enable SAL_USING_POSIX!"
+#else
+#include <sys/time.h>
+#include <sys/select.h>
+#endif
 #include <sys/socket.h> /* 使用BSD socket,需要包含socket.h头文件 */
 #include "netdb.h"
 
+#define DEBUG_UDP_SERVER
+
+#define DBG_ENABLE
+#define DBG_SECTION_NAME               "UDP"
+#ifdef DEBUG_UDP_SERVER
+#define DBG_LEVEL                      DBG_LOG
+#else
+#define DBG_LEVEL                      DBG_INFO /* DBG_ERROR */
+#endif
+#define DBG_COLOR
+#include <rtdbg.h>
+
 #define BUFSZ   1024
 
+static int started = 0;
+static int is_running = 0;
+static int port = 5000;
+
 static void udpserv(void *paramemter)
 {
     int sock;
@@ -13,28 +36,27 @@ static void udpserv(void *paramemter)
     socklen_t addr_len;
     struct sockaddr_in server_addr, client_addr;
 
+    struct timeval timeout;
+    fd_set readset;
+
     /* 分配接收用的数据缓冲 */
     recv_data = rt_malloc(BUFSZ);
     if (recv_data == RT_NULL)
     {
-        /* 分配内存失败,返回 */
-        rt_kprintf("No memory\n");
+        LOG_E("No memory");
         return;
     }
 
     /* 创建一个socket,类型是SOCK_DGRAM,UDP类型 */
     if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
     {
-        rt_kprintf("Socket error\n");
-
-        /* 释放接收用的数据缓冲 */
-        rt_free(recv_data);
-        return;
+        LOG_E("Create socket error");
+        goto __exit;
     }
 
     /* 初始化服务端地址 */
     server_addr.sin_family = AF_INET;
-    server_addr.sin_port = htons(5000);
+    server_addr.sin_port = htons(port);
     server_addr.sin_addr.s_addr = INADDR_ANY;
     rt_memset(&(server_addr.sin_zero), 0, sizeof(server_addr.sin_zero));
 
@@ -42,47 +64,134 @@ static void udpserv(void *paramemter)
     if (bind(sock, (struct sockaddr *)&server_addr,
              sizeof(struct sockaddr)) == -1)
     {
-        /* 绑定地址失败 */
-        rt_kprintf("Bind error\n");
-
-        /* 释放接收用的数据缓冲 */
-        rt_free(recv_data);
-        return;
+        LOG_E("Unable to bind");
+        goto __exit;
     }
 
     addr_len = sizeof(struct sockaddr);
-    rt_kprintf("UDPServer Waiting for client on port 5000...\n");
+    LOG_I("UDPServer Waiting for client on port %d...", port);
 
-    while (1)
+    started = 1;
+    is_running = 1;
+
+    timeout.tv_sec = 3;
+    timeout.tv_usec = 0;
+
+    while (is_running)
     {
+        FD_ZERO(&readset);
+        FD_SET(sock, &readset);
+
+        /* Wait for read or write */
+        if (select(sock + 1, &readset, RT_NULL, RT_NULL, &timeout) == 0)
+            continue;
+
         /* 从sock中收取最大BUFSZ - 1字节数据 */
         bytes_read = recvfrom(sock, recv_data, BUFSZ - 1, 0,
                               (struct sockaddr *)&client_addr, &addr_len);
-        /* UDP不同于TCP,它基本不会出现收取的数据失败的情况,除非设置了超时等待 */
+        if (bytes_read < 0)
+        {
+            LOG_E("Received error, close the connect.");
+            goto __exit;
+        }
+        else if (bytes_read == 0)
+        {
+            LOG_W("Received warning, recv function return 0.");
+            continue;
+        }
+        else
+        {
+            recv_data[bytes_read] = '\0'; /* 把末端清零 */
 
-        recv_data[bytes_read] = '\0'; /* 把末端清零 */
+            /* 输出接收的数据 */
+            LOG_D("Received data = %s", recv_data);
 
-        /* 输出接收的数据 */
-        rt_kprintf("\n(%s , %d) said : ", inet_ntoa(client_addr.sin_addr),
-                   ntohs(client_addr.sin_port));
-        rt_kprintf("%s", recv_data);
+            /* 如果接收数据是exit,退出 */
+            if (strcmp(recv_data, "exit") == 0)
+            {
+                goto __exit;
+            }
+        }
+    }
 
-        /* 如果接收数据是exit,退出 */
-        if (strcmp(recv_data, "exit") == 0)
-        {
-            closesocket(sock);
+__exit:
+    if (recv_data)
+    {
+        rt_free(recv_data);
+        recv_data = RT_NULL;
+    }
+    if (sock >= 0)
+    {
+        closesocket(sock);
+        sock = -1;
+    }
+    started = 0;
+    is_running = 0;
+}
 
-            /* 释放接收用的数据缓冲 */
-            rt_free(recv_data);
-            break;
+static void usage(void)
+{
+    LOG_I("Usage: udpserver -p <port>");
+    LOG_I("       udpserver --stop");
+    LOG_I("       udpserver --help");
+    LOG_I("");
+    LOG_I("Miscellaneous:");
+    LOG_I("  -p           Specify the host port number");
+    LOG_I("  --stop       Stop udpserver program");
+    LOG_I("  --help       Print help information");
+}
+
+static void udpserver_test(int argc, char** argv)
+{
+    rt_thread_t tid;
+
+    if (argc == 1 || argc > 3)
+    {
+        LOG_I("Please check the command you entered!\n");
+        goto __usage;
+    }
+    else
+    {
+        if (rt_strcmp(argv[1], "--help") == 0)
+        {
+            goto __usage;
+        }
+        else if (rt_strcmp(argv[1], "--stop") == 0)
+        {
+            is_running = 0;
+            return;
+        }
+        else if (rt_strcmp(argv[1], "-p") == 0)
+        {
+            if (started)
+            {
+                LOG_I("The tcpclient has started!");
+                LOG_I("Please stop tcpclient firstly, by: tcpclient --stop");
+                return;
+            }
+
+            port = atoi(argv[2]);
+        }
+        else
+        {
+            goto __usage;
         }
     }
 
+    tid = rt_thread_create("udp_serv",
+        udpserv, RT_NULL,
+        2048, RT_THREAD_PRIORITY_MAX/3, 20);
+    if (tid != RT_NULL)
+    {
+        rt_thread_startup(tid);
+    }
     return;
+
+__usage:
+    usage();
 }
 
 #ifdef RT_USING_FINSH
-#include <finsh.h>
-/* 输出udpserv函数到finsh shell中 */
-FINSH_FUNCTION_EXPORT(udpserv, startup udp server);
+MSH_CMD_EXPORT_ALIAS(udpserver_test, udpserver,
+    Start a udp server. Help: udpserver --help);
 #endif