udpserver.c 4.5 KB
Newer Older
B
Bernard Xiong 已提交
1
#include <rtthread.h>
2
#include <string.h>
3

4 5 6 7 8 9
#if !defined(SAL_USING_POSIX)
#error "Please enable SAL_USING_POSIX!"
#else
#include <sys/time.h>
#include <sys/select.h>
#endif
wuyangyong's avatar
wuyangyong 已提交
10 11
#include <sys/socket.h> /* 使用BSD socket,需要包含socket.h头文件 */
#include "netdb.h"
B
Bernard Xiong 已提交
12

13 14
#define DEBUG_UDP_SERVER

15
#define DBG_TAG               "UDP"
16
#ifdef DEBUG_UDP_SERVER
17
#define DBG_LVL               DBG_LOG
18
#else
19
#define DBG_LVL               DBG_INFO /* DBG_ERROR */
20 21 22
#endif
#include <rtdbg.h>

wuyangyong's avatar
wuyangyong 已提交
23
#define BUFSZ   1024
B
Bernard Xiong 已提交
24

25 26 27 28
static int started = 0;
static int is_running = 0;
static int port = 5000;

wuyangyong's avatar
wuyangyong 已提交
29
static void udpserv(void *paramemter)
B
Bernard Xiong 已提交
30
{
wuyangyong's avatar
wuyangyong 已提交
31 32 33 34 35 36
    int sock;
    int bytes_read;
    char *recv_data;
    socklen_t addr_len;
    struct sockaddr_in server_addr, client_addr;

37 38 39
    struct timeval timeout;
    fd_set readset;

wuyangyong's avatar
wuyangyong 已提交
40 41 42 43
    /* 分配接收用的数据缓冲 */
    recv_data = rt_malloc(BUFSZ);
    if (recv_data == RT_NULL)
    {
44
        LOG_E("No memory");
wuyangyong's avatar
wuyangyong 已提交
45 46 47 48 49 50
        return;
    }

    /* 创建一个socket,类型是SOCK_DGRAM,UDP类型 */
    if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
    {
51 52
        LOG_E("Create socket error");
        goto __exit;
wuyangyong's avatar
wuyangyong 已提交
53 54 55 56
    }

    /* 初始化服务端地址 */
    server_addr.sin_family = AF_INET;
57
    server_addr.sin_port = htons(port);
wuyangyong's avatar
wuyangyong 已提交
58 59 60 61 62 63 64
    server_addr.sin_addr.s_addr = INADDR_ANY;
    rt_memset(&(server_addr.sin_zero), 0, sizeof(server_addr.sin_zero));

    /* 绑定socket到服务端地址 */
    if (bind(sock, (struct sockaddr *)&server_addr,
             sizeof(struct sockaddr)) == -1)
    {
65 66
        LOG_E("Unable to bind");
        goto __exit;
wuyangyong's avatar
wuyangyong 已提交
67 68 69
    }

    addr_len = sizeof(struct sockaddr);
70
    LOG_I("UDPServer Waiting for client on port %d...", port);
wuyangyong's avatar
wuyangyong 已提交
71

72 73 74 75 76 77 78
    started = 1;
    is_running = 1;

    timeout.tv_sec = 3;
    timeout.tv_usec = 0;

    while (is_running)
wuyangyong's avatar
wuyangyong 已提交
79
    {
80 81 82 83 84 85 86
        FD_ZERO(&readset);
        FD_SET(sock, &readset);

        /* Wait for read or write */
        if (select(sock + 1, &readset, RT_NULL, RT_NULL, &timeout) == 0)
            continue;

wuyangyong's avatar
wuyangyong 已提交
87 88 89
        /* 从sock中收取最大BUFSZ - 1字节数据 */
        bytes_read = recvfrom(sock, recv_data, BUFSZ - 1, 0,
                              (struct sockaddr *)&client_addr, &addr_len);
90 91 92 93 94 95 96 97 98 99 100 101 102
        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'; /* 把末端清零 */
wuyangyong's avatar
wuyangyong 已提交
103

104 105
            /* 输出接收的数据 */
            LOG_D("Received data = %s", recv_data);
wuyangyong's avatar
wuyangyong 已提交
106

107 108 109 110 111 112 113
            /* 如果接收数据是exit,退出 */
            if (strcmp(recv_data, "exit") == 0)
            {
                goto __exit;
            }
        }
    }
wuyangyong's avatar
wuyangyong 已提交
114

115 116 117 118 119 120 121 122 123 124 125 126 127 128
__exit:
    if (recv_data)
    {
        rt_free(recv_data);
        recv_data = RT_NULL;
    }
    if (sock >= 0)
    {
        closesocket(sock);
        sock = -1;
    }
    started = 0;
    is_running = 0;
}
wuyangyong's avatar
wuyangyong 已提交
129

130 131
static void usage(void)
{
132 133 134 135 136 137 138 139
    rt_kprintf("Usage: udpserver -p <port>\n");
    rt_kprintf("       udpserver --stop\n");
    rt_kprintf("       udpserver --help\n");
    rt_kprintf("\n");
    rt_kprintf("Miscellaneous:\n");
    rt_kprintf("  -p           Specify the host port number\n");
    rt_kprintf("  --stop       Stop udpserver program\n");
    rt_kprintf("  --help       Print help information\n");
140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165
}

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)
            {
D
David Lin 已提交
166 167
                LOG_I("The udpserver has started!");
                LOG_I("Please stop udpserver firstly, by: udpserver --stop");
168 169 170 171 172 173 174 175
                return;
            }

            port = atoi(argv[2]);
        }
        else
        {
            goto __usage;
wuyangyong's avatar
wuyangyong 已提交
176 177 178
        }
    }

179 180 181 182 183 184 185
    tid = rt_thread_create("udp_serv",
        udpserv, RT_NULL,
        2048, RT_THREAD_PRIORITY_MAX/3, 20);
    if (tid != RT_NULL)
    {
        rt_thread_startup(tid);
    }
wuyangyong's avatar
wuyangyong 已提交
186
    return;
187 188 189

__usage:
    usage();
B
Bernard Xiong 已提交
190 191 192
}

#ifdef RT_USING_FINSH
193 194
MSH_CMD_EXPORT_ALIAS(udpserver_test, udpserver,
    Start a udp server. Help: udpserver --help);
B
Bernard Xiong 已提交
195
#endif