2025-06-27 00:32:57 +08:00
# include <rtthread.h>
# include <string.h>
# if !defined(SAL_USING_POSIX)
# error "Please enable SAL_USING_POSIX!"
# else
# include <sys/time.h>
# include <sys/select.h>
# endif
2025-07-05 19:47:28 +08:00
# include <sys/socket.h> /* ʹ <> <CAB9> BSD socket<65> <74> <EFBFBD> <EFBFBD> Ҫ<EFBFBD> <D2AA> <EFBFBD> <EFBFBD> socket.hͷ<68> ļ<EFBFBD> */
2025-06-27 00:32:57 +08:00
# include "netdb.h"
# define DEBUG_TCP_CLIENT
# define DBG_ENABLE
# define DBG_SECTION_NAME "TCP"
# ifdef DEBUG_TCP_CLIENT
# define DBG_LEVEL DBG_LOG
# else
# define DBG_LEVEL DBG_INFO /* DBG_ERROR */
# endif
# define DBG_COLOR
# include <rtdbg.h>
# define BUFSZ 1024
static int started = 0 ;
static int is_running = 0 ;
static char url [ 256 ] ;
static int port = 8080 ;
2025-07-05 19:47:28 +08:00
static const char send_data [ ] = " This is TCP Client from RT-Thread. " ; /* <20> <> <EFBFBD> <EFBFBD> <EFBFBD> õ<EFBFBD> <C3B5> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> */
2025-06-27 00:32:57 +08:00
static void tcpclient ( void * arg )
{
int ret ;
char * recv_data ;
int bytes_received ;
int sock = - 1 ;
struct hostent * host = RT_NULL ;
struct sockaddr_in server_addr ;
struct timeval timeout ;
fd_set readset ;
2025-07-05 19:47:28 +08:00
/* ͨ<> <CDA8> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> ڲ<EFBFBD> <DAB2> <EFBFBD> url<72> <6C> <EFBFBD> <EFBFBD> host<73> <74> ַ<EFBFBD> <D6B7> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> */
2025-06-27 00:32:57 +08:00
host = gethostbyname ( url ) ;
if ( host = = RT_NULL )
{
LOG_E ( " Get host by name failed! " ) ;
return ;
}
2025-07-05 19:47:28 +08:00
/* <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> ڴ<EFBFBD> <DAB4> Ž<EFBFBD> <C5BD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> ݵĻ<DDB5> <C4BB> <EFBFBD> */
2025-06-27 00:32:57 +08:00
recv_data = rt_malloc ( BUFSZ ) ;
if ( recv_data = = RT_NULL )
{
LOG_E ( " No memory " ) ;
return ;
}
2025-07-05 19:47:28 +08:00
/* <20> <> <EFBFBD> <EFBFBD> һ <EFBFBD> <D2BB> socket<65> <74> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> SOCKET_STREAM<41> <4D> TCP<43> <50> <EFBFBD> <EFBFBD> */
2025-06-27 00:32:57 +08:00
if ( ( sock = socket ( AF_INET , SOCK_STREAM , 0 ) ) = = - 1 )
{
2025-07-05 19:47:28 +08:00
/* <20> <> <EFBFBD> <EFBFBD> socketʧ<74> <CAA7> */
2025-06-27 00:32:57 +08:00
LOG_E ( " Create socket error " ) ;
goto __exit ;
}
2025-07-05 19:47:28 +08:00
/* <20> <> ʼ <EFBFBD> <CABC> Ԥ<EFBFBD> <D4A4> <EFBFBD> ӵķ<D3B5> <C4B7> <EFBFBD> <EFBFBD> ˵<EFBFBD> ַ */
2025-06-27 00:32:57 +08:00
server_addr . sin_family = AF_INET ;
server_addr . sin_port = htons ( port ) ;
server_addr . sin_addr = * ( ( struct in_addr * ) host - > h_addr ) ;
rt_memset ( & ( server_addr . sin_zero ) , 0 , sizeof ( server_addr . sin_zero ) ) ;
2025-07-05 19:47:28 +08:00
/* <20> <> <EFBFBD> ӵ<EFBFBD> <D3B5> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> */
2025-06-27 00:32:57 +08:00
if ( connect ( sock , ( struct sockaddr * ) & server_addr , sizeof ( struct sockaddr ) ) = = - 1 )
{
2025-07-05 19:47:28 +08:00
/* <20> <> <EFBFBD> <EFBFBD> ʧ<EFBFBD> <CAA7> */
2025-06-27 00:32:57 +08:00
LOG_E ( " Connect fail! " ) ;
goto __exit ;
}
started = 1 ;
is_running = 1 ;
timeout . tv_sec = 3 ;
timeout . tv_usec = 0 ;
while ( is_running )
{
FD_ZERO ( & readset ) ;
FD_SET ( sock , & readset ) ;
/* Wait for read */
if ( select ( sock + 1 , & readset , RT_NULL , RT_NULL , & timeout ) = = 0 )
continue ;
2025-07-05 19:47:28 +08:00
/* <20> <> sock<63> <6B> <EFBFBD> <EFBFBD> <EFBFBD> н<EFBFBD> <D0BD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> BUFSZ - 1<> ֽ<EFBFBD> <D6BD> <EFBFBD> <EFBFBD> <EFBFBD> */
2025-06-27 00:32:57 +08:00
bytes_received = recv ( sock , recv_data , BUFSZ - 1 , 0 ) ;
if ( bytes_received < 0 )
{
2025-07-05 19:47:28 +08:00
/* <20> <> <EFBFBD> <EFBFBD> ʧ<EFBFBD> ܣ<EFBFBD> <DCA3> ر<EFBFBD> <D8B1> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> */
2025-06-27 00:32:57 +08:00
LOG_E ( " Received error, close the socket. " ) ;
goto __exit ;
}
else if ( bytes_received = = 0 )
{
2025-07-05 19:47:28 +08:00
/* <20> <> ӡrecv<63> <76> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> ֵΪ0<CEAA> ľ<EFBFBD> <C4BE> <EFBFBD> <EFBFBD> <EFBFBD> Ϣ */
2025-06-27 00:32:57 +08:00
LOG_W ( " Received warning, recv function return 0. " ) ;
continue ;
}
else
{
2025-07-05 19:47:28 +08:00
/* <20> н<EFBFBD> <D0BD> յ<EFBFBD> <D5B5> <EFBFBD> <EFBFBD> ݣ<EFBFBD> <DDA3> <EFBFBD> ĩ<EFBFBD> <C4A9> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> */
2025-06-27 00:32:57 +08:00
recv_data [ bytes_received ] = ' \0 ' ;
if ( rt_strcmp ( recv_data , " q " ) = = 0 | | rt_strcmp ( recv_data , " Q " ) = = 0 )
{
2025-07-05 19:47:28 +08:00
/* <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> ĸ<EFBFBD> <C4B8> q<EFBFBD> <71> Q<EFBFBD> <51> <EFBFBD> ر<EFBFBD> <D8B1> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> */
2025-06-27 00:32:57 +08:00
LOG_I ( " Got a 'q' or 'Q', close the socket. " ) ;
goto __exit ;
}
else
{
2025-07-05 19:47:28 +08:00
/* <20> ڿ<EFBFBD> <DABF> <EFBFBD> <EFBFBD> ն<EFBFBD> <D5B6> <EFBFBD> ʾ <EFBFBD> յ<EFBFBD> <D5B5> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> */
2025-06-27 00:32:57 +08:00
LOG_D ( " Received data = %s " , recv_data ) ;
}
}
2025-07-05 19:47:28 +08:00
/* <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> ݵ<EFBFBD> sock<63> <6B> <EFBFBD> <EFBFBD> */
2025-06-27 00:32:57 +08:00
ret = send ( sock , send_data , rt_strlen ( send_data ) , 0 ) ;
if ( ret < 0 )
{
2025-07-05 19:47:28 +08:00
/* <20> <> <EFBFBD> <EFBFBD> ʧ<EFBFBD> ܣ<EFBFBD> <DCA3> ر<EFBFBD> <D8B1> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> */
2025-06-27 00:32:57 +08:00
LOG_I ( " send error, close the socket. " ) ;
goto __exit ;
}
else if ( ret = = 0 )
{
2025-07-05 19:47:28 +08:00
/* <20> <> ӡsend<6E> <64> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> ֵΪ0<CEAA> ľ<EFBFBD> <C4BE> <EFBFBD> <EFBFBD> <EFBFBD> Ϣ */
2025-06-27 00:32:57 +08:00
LOG_W ( " Send warning, send function return 0. " ) ;
}
}
__exit :
if ( recv_data )
{
rt_free ( recv_data ) ;
recv_data = RT_NULL ;
}
if ( sock > = 0 )
{
closesocket ( sock ) ;
sock = - 1 ;
}
started = 0 ;
is_running = 0 ;
return ;
}
static void usage ( void )
{
rt_kprintf ( " Usage: tcpclient -h <host> -p <port> \n " ) ;
rt_kprintf ( " tcpclient --stop \n " ) ;
rt_kprintf ( " tcpclient --help \n " ) ;
rt_kprintf ( " \n " ) ;
rt_kprintf ( " Miscellaneous: \n " ) ;
rt_kprintf ( " -h Specify host address \n " ) ;
rt_kprintf ( " -p Specify the host port number \n " ) ;
rt_kprintf ( " --stop Stop tcpclient program \n " ) ;
rt_kprintf ( " --help Print help information \n " ) ;
}
static void tcpclient_test ( int argc , char * * argv )
{
rt_thread_t tid ;
if ( argc = = 1 | | argc > 5 )
{
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 ] , " -h " ) = = 0 & & rt_strcmp ( argv [ 3 ] , " -p " ) = = 0 )
{
if ( started )
{
LOG_I ( " The tcpclient has started! " ) ;
LOG_I ( " Please stop tcpclient firstly, by: tcpclient --stop " ) ;
return ;
}
if ( rt_strlen ( argv [ 2 ] ) > sizeof ( url ) )
{
LOG_E ( " The input url is too long, max %d bytes! " , sizeof ( url ) ) ;
return ;
}
rt_memset ( url , 0x0 , sizeof ( url ) ) ;
rt_strncpy ( url , argv [ 2 ] , rt_strlen ( argv [ 2 ] ) ) ;
port = atoi ( argv [ 4 ] ) ;
}
else
{
goto __usage ;
}
}
tid = rt_thread_create ( " tcp_client " ,
tcpclient , RT_NULL ,
2048 , RT_THREAD_PRIORITY_MAX / 3 , 20 ) ;
if ( tid ! = RT_NULL )
{
rt_thread_startup ( tid ) ;
}
return ;
__usage :
usage ( ) ;
}
# ifdef RT_USING_FINSH
MSH_CMD_EXPORT_ALIAS ( tcpclient_test , tcpclient ,
Start a tcp client . Help : tcpclient - - help ) ;
# endif