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