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