xref: /nrf52832-nimble/rt-thread/examples/network/tcpclient.c (revision 104654410c56c573564690304ae786df310c91fc)
1 #include <rtthread.h>
2 #include <string.h>
3 
4 #if !defined(SAL_USING_POSIX)
5 #error "Please enable SAL_USING_POSIX!"
6 #else
7 #include <sys/time.h>
8 #include <sys/select.h>
9 #endif
10 #include <sys/socket.h> /* 使用BSD socket,需要包含socket.h头文件 */
11 #include "netdb.h"
12 
13 #define DEBUG_TCP_CLIENT
14 
15 #define DBG_ENABLE
16 #define DBG_SECTION_NAME               "TCP"
17 #ifdef DEBUG_TCP_CLIENT
18 #define DBG_LEVEL                      DBG_LOG
19 #else
20 #define DBG_LEVEL                      DBG_INFO /* DBG_ERROR */
21 #endif
22 #define DBG_COLOR
23 #include <rtdbg.h>
24 
25 #define BUFSZ   1024
26 
27 static int started = 0;
28 static int is_running = 0;
29 static char url[256];
30 static int port = 8080;
31 static const char send_data[] = "This is TCP Client from RT-Thread."; /* 发送用到的数据 */
32 
tcpclient(void * arg)33 static void tcpclient(void *arg)
34 {
35     int ret;
36     char *recv_data;
37     int bytes_received;
38     int sock = -1;
39     struct hostent *host = RT_NULL;
40     struct sockaddr_in server_addr;
41 
42     struct timeval timeout;
43     fd_set readset;
44 
45     /* 通过函数入口参数url获得host地址(如果是域名,会做域名解析) */
46     host = gethostbyname(url);
47     if (host == RT_NULL)
48     {
49         LOG_E("Get host by name failed!");
50         return;
51     }
52 
53     /* 分配用于存放接收数据的缓冲 */
54     recv_data = rt_malloc(BUFSZ);
55     if (recv_data == RT_NULL)
56     {
57         LOG_E("No memory");
58         return;
59     }
60 
61     /* 创建一个socket,类型是SOCKET_STREAM,TCP类型 */
62     if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1)
63     {
64         /* 创建socket失败 */
65         LOG_E("Create socket error");
66         goto __exit;
67     }
68 
69     /* 初始化预连接的服务端地址 */
70     server_addr.sin_family = AF_INET;
71     server_addr.sin_port = htons(port);
72     server_addr.sin_addr = *((struct in_addr *)host->h_addr);
73     rt_memset(&(server_addr.sin_zero), 0, sizeof(server_addr.sin_zero));
74 
75     /* 连接到服务端 */
76     if (connect(sock, (struct sockaddr *)&server_addr, sizeof(struct sockaddr)) == -1)
77     {
78         /* 连接失败 */
79         LOG_E("Connect fail!");
80         goto __exit;
81     }
82 
83     started = 1;
84     is_running = 1;
85 
86     timeout.tv_sec = 3;
87     timeout.tv_usec = 0;
88 
89     while (is_running)
90     {
91         FD_ZERO(&readset);
92         FD_SET(sock, &readset);
93 
94         /* Wait for read */
95         if (select(sock + 1, &readset, RT_NULL, RT_NULL, &timeout) == 0)
96             continue;
97 
98         /* 从sock连接中接收最大BUFSZ - 1字节数据 */
99         bytes_received = recv(sock, recv_data, BUFSZ - 1, 0);
100         if (bytes_received < 0)
101         {
102             /* 接收失败,关闭这个连接 */
103             LOG_E("Received error, close the socket.");
104             goto __exit;
105         }
106         else if (bytes_received == 0)
107         {
108             /* 打印recv函数返回值为0的警告信息 */
109             LOG_W("Received warning, recv function return 0.");
110             continue;
111         }
112         else
113         {
114             /* 有接收到数据,把末端清零 */
115             recv_data[bytes_received] = '\0';
116 
117             if (rt_strcmp(recv_data, "q") == 0 || rt_strcmp(recv_data, "Q") == 0)
118             {
119                 /* 如果是首字母是q或Q,关闭这个连接 */
120                 LOG_I("Got a 'q' or 'Q', close the socket.");
121                 goto __exit;
122             }
123             else
124             {
125                 /* 在控制终端显示收到的数据 */
126                 LOG_D("Received data = %s", recv_data);
127             }
128         }
129 
130         /* 发送数据到sock连接 */
131         ret = send(sock, send_data, rt_strlen(send_data), 0);
132         if (ret < 0)
133         {
134             /* 接收失败,关闭这个连接 */
135             LOG_I("send error, close the socket.");
136             goto __exit;
137         }
138         else if (ret == 0)
139         {
140             /* 打印send函数返回值为0的警告信息 */
141             LOG_W("Send warning, send function return 0.");
142         }
143     }
144 
145 __exit:
146     if (recv_data)
147     {
148         rt_free(recv_data);
149         recv_data = RT_NULL;
150     }
151     if (sock >= 0)
152     {
153         closesocket(sock);
154         sock = -1;
155     }
156     started = 0;
157     is_running = 0;
158     return;
159 }
160 
usage(void)161 static void usage(void)
162 {
163     rt_kprintf("Usage: tcpclient -h <host> -p <port>\n");
164     rt_kprintf("       tcpclient --stop\n");
165     rt_kprintf("       tcpclient --help\n");
166     rt_kprintf("\n");
167     rt_kprintf("Miscellaneous:\n");
168     rt_kprintf("  -h           Specify host address\n");
169     rt_kprintf("  -p           Specify the host port number\n");
170     rt_kprintf("  --stop       Stop tcpclient program\n");
171     rt_kprintf("  --help       Print help information\n");
172 }
173 
tcpclient_test(int argc,char ** argv)174 static void tcpclient_test(int argc, char** argv)
175 {
176     rt_thread_t tid;
177 
178     if (argc == 1 || argc > 5)
179     {
180         LOG_I("Please check the command you entered!\n");
181         goto __usage;
182     }
183     else
184     {
185         if (rt_strcmp(argv[1], "--help") == 0)
186         {
187             goto __usage;
188         }
189         else if (rt_strcmp(argv[1], "--stop") == 0)
190         {
191             is_running = 0;
192             return;
193         }
194         else if (rt_strcmp(argv[1], "-h") == 0 && rt_strcmp(argv[3], "-p") == 0)
195         {
196             if (started)
197             {
198                 LOG_I("The tcpclient has started!");
199                 LOG_I("Please stop tcpclient firstly, by: tcpclient --stop");
200                 return;
201             }
202 
203             if (rt_strlen(argv[2]) > sizeof(url))
204             {
205                 LOG_E("The input url is too long, max %d bytes!", sizeof(url));
206                 return;
207             }
208             rt_memset(url, 0x0, sizeof(url));
209             rt_strncpy(url, argv[2], rt_strlen(argv[2]));
210             port = atoi(argv[4]);
211         }
212         else
213         {
214             goto __usage;
215         }
216     }
217 
218     tid = rt_thread_create("tcp_client",
219         tcpclient, RT_NULL,
220         2048, RT_THREAD_PRIORITY_MAX/3, 20);
221     if (tid != RT_NULL)
222     {
223         rt_thread_startup(tid);
224     }
225     return;
226 
227 __usage:
228     usage();
229 }
230 
231 #ifdef RT_USING_FINSH
232 MSH_CMD_EXPORT_ALIAS(tcpclient_test, tcpclient,
233     Start a tcp client. Help: tcpclient --help);
234 #endif
235