11#include <rtthread.h>
2+ #include <string.h>
23
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
310#include <sys/socket.h> /* 使用BSD socket,需要包含socket.h头文件 */
411#include "netdb.h"
512
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+
625#define BUFSZ 1024
726
27+ static int started = 0 ;
28+ static int is_running = 0 ;
29+ static char url [256 ];
30+ static int port = 8080 ;
831static const char send_data [] = "This is TCP Client from RT-Thread." ; /* 发送用到的数据 */
9- void tcpclient (const char * url , int port )
32+
33+ static void tcpclient (void * arg )
1034{
1135 int ret ;
1236 char * recv_data ;
13- struct hostent * host ;
14- int sock , bytes_received ;
37+ int bytes_received ;
38+ int sock = -1 ;
39+ struct hostent * host = RT_NULL ;
1540 struct sockaddr_in server_addr ;
1641
42+ struct timeval timeout ;
43+ fd_set readset ;
44+
1745 /* 通过函数入口参数url获得host地址(如果是域名,会做域名解析) */
1846 host = gethostbyname (url );
47+ if (host == RT_NULL )
48+ {
49+ LOG_E ("Get host by name failed!" );
50+ return ;
51+ }
1952
2053 /* 分配用于存放接收数据的缓冲 */
2154 recv_data = rt_malloc (BUFSZ );
2255 if (recv_data == RT_NULL )
2356 {
24- rt_kprintf ("No memory\n " );
57+ LOG_E ("No memory" );
2558 return ;
2659 }
2760
2861 /* 创建一个socket,类型是SOCKET_STREAM,TCP类型 */
2962 if ((sock = socket (AF_INET , SOCK_STREAM , 0 )) == -1 )
3063 {
3164 /* 创建socket失败 */
32- rt_kprintf ("Socket error\n" );
33-
34- /* 释放接收缓冲 */
35- rt_free (recv_data );
36- return ;
65+ LOG_E ("Create socket error" );
66+ goto __exit ;
3767 }
3868
3969 /* 初始化预连接的服务端地址 */
@@ -46,78 +76,159 @@ void tcpclient(const char *url, int port)
4676 if (connect (sock , (struct sockaddr * )& server_addr , sizeof (struct sockaddr )) == -1 )
4777 {
4878 /* 连接失败 */
49- rt_kprintf ("Connect fail!\n" );
50- closesocket (sock );
51-
52- /*释放接收缓冲 */
53- rt_free (recv_data );
54- return ;
79+ LOG_E ("Connect fail!" );
80+ goto __exit ;
5581 }
5682
57- while (1 )
83+ started = 1 ;
84+ is_running = 1 ;
85+
86+ timeout .tv_sec = 3 ;
87+ timeout .tv_usec = 0 ;
88+
89+ while (is_running )
5890 {
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+
5998 /* 从sock连接中接收最大BUFSZ - 1字节数据 */
6099 bytes_received = recv (sock , recv_data , BUFSZ - 1 , 0 );
61100 if (bytes_received < 0 )
62101 {
63102 /* 接收失败,关闭这个连接 */
64- closesocket (sock );
65- rt_kprintf ("\nreceived error,close the socket.\r\n" );
66-
67- /* 释放接收缓冲 */
68- rt_free (recv_data );
69- break ;
103+ LOG_E ("Received error, close the socket." );
104+ goto __exit ;
70105 }
71106 else if (bytes_received == 0 )
72107 {
73108 /* 打印recv函数返回值为0的警告信息 */
74- rt_kprintf ("\nReceived warning,recv function return 0.\r\n" );
75-
109+ LOG_W ("Received warning, recv function return 0." );
76110 continue ;
77111 }
78-
79- /* 有接收到数据,把末端清零 */
80- recv_data [bytes_received ] = '\0' ;
81-
82- if (strcmp (recv_data , "q" ) == 0 || strcmp (recv_data , "Q" ) == 0 )
83- {
84- /* 如果是首字母是q或Q,关闭这个连接 */
85- closesocket (sock );
86- rt_kprintf ("\n got a 'q' or 'Q',close the socket.\r\n" );
87-
88- /* 释放接收缓冲 */
89- rt_free (recv_data );
90- break ;
91- }
92112 else
93113 {
94- /* 在控制终端显示收到的数据 */
95- rt_kprintf ("\nReceived data = %s " , recv_data );
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+ }
96128 }
97129
98130 /* 发送数据到sock连接 */
99- ret = send (sock , send_data , strlen (send_data ), 0 );
131+ ret = send (sock , send_data , rt_strlen (send_data ), 0 );
100132 if (ret < 0 )
101133 {
102134 /* 接收失败,关闭这个连接 */
103- closesocket (sock );
104- rt_kprintf ("\nsend error,close the socket.\r\n" );
105-
106- rt_free (recv_data );
107- break ;
135+ LOG_I ("send error, close the socket." );
136+ goto __exit ;
108137 }
109138 else if (ret == 0 )
110139 {
111140 /* 打印send函数返回值为0的警告信息 */
112- rt_kprintf ("\n Send warning,send function return 0.\r\n" );
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+
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+
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 ;
113215 }
114216 }
115217
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+ }
116225 return ;
226+
227+ __usage :
228+ usage ();
117229}
118230
119231#ifdef RT_USING_FINSH
120- #include <finsh.h>
121- /* 输出tcpclient函数到finsh shell中 */
122- FINSH_FUNCTION_EXPORT (tcpclient , startup tcp client );
232+ MSH_CMD_EXPORT_ALIAS (tcpclient_test , tcpclient ,
233+ Start a tcp client . Help : tcpclient -- help );
123234#endif
0 commit comments