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_SERVER
# define DBG_ENABLE
# define DBG_SECTION_NAME "TCP"
# ifdef DEBUG_TCP_SERVER
# 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 int port = 5000 ;
2025-07-05 19:47:28 +08:00
static const char send_data [ ] = " This is TCP Server from RT-Thread. " ; /* <20> <> <EFBFBD> <EFBFBD> <EFBFBD> õ<EFBFBD> <C3B5> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> */
2025-06-27 00:32:57 +08:00
static void tcpserv ( void * arg )
{
int ret ;
2025-07-05 19:47:28 +08:00
char * recv_data ; /* <20> <> <EFBFBD> ڽ<EFBFBD> <DABD> յ<EFBFBD> ָ<EFBFBD> 룬<EFBFBD> <EBA3AC> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> һ <EFBFBD> ζ<EFBFBD> ̬<EFBFBD> <CCAC> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> ڴ<EFBFBD> */
2025-06-27 00:32:57 +08:00
int sock , connected , bytes_received ;
struct sockaddr_in server_addr , client_addr ;
struct timeval timeout ;
fd_set readset , readset_c ;
socklen_t sin_size = sizeof ( struct sockaddr_in ) ;
2025-07-05 19:47:28 +08:00
recv_data = rt_malloc ( BUFSZ + 1 ) ; /* <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> õ<EFBFBD> <C3B5> <EFBFBD> <EFBFBD> ݻ<EFBFBD> <DDBB> <EFBFBD> */
2025-06-27 00:32:57 +08:00
if ( recv_data = = RT_NULL )
{
LOG_E ( " No memory " ) ;
return ;
}
2025-07-05 19:47:28 +08:00
/* һ <> <D2BB> socket<65> <74> ʹ <EFBFBD> <CAB9> ǰ<EFBFBD> <C7B0> <EFBFBD> <EFBFBD> ҪԤ<D2AA> ȴ<EFBFBD> <C8B4> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> ָ<EFBFBD> <D6B8> SOCK_STREAMΪTCP<43> <50> socket */
2025-06-27 00:32:57 +08:00
if ( ( sock = socket ( AF_INET , SOCK_STREAM , IPPROTO_TCP ) ) = = - 1 )
{
LOG_E ( " Create socket error " ) ;
goto __exit ;
}
2025-07-05 19:47:28 +08:00
/* <20> <> ʼ <EFBFBD> <CABC> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> ˵<EFBFBD> ַ */
2025-06-27 00:32:57 +08:00
server_addr . sin_family = AF_INET ;
2025-07-05 19:47:28 +08:00
server_addr . sin_port = htons ( port ) ; /* <20> <> <EFBFBD> <EFBFBD> <EFBFBD> ˹<EFBFBD> <CBB9> <EFBFBD> <EFBFBD> Ķ˿<C4B6> */
2025-06-27 00:32:57 +08:00
server_addr . sin_addr . s_addr = INADDR_ANY ;
rt_memset ( & ( server_addr . sin_zero ) , 0x0 , sizeof ( server_addr . sin_zero ) ) ;
2025-07-05 19:47:28 +08:00
/* <20> <> <EFBFBD> <EFBFBD> socket<65> <74> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> ˵<EFBFBD> ַ */
2025-06-27 00:32:57 +08:00
if ( bind ( sock , ( struct sockaddr * ) & server_addr , sizeof ( struct sockaddr ) ) = = - 1 )
{
LOG_E ( " Unable to bind " ) ;
goto __exit ;
}
2025-07-05 19:47:28 +08:00
/* <20> <> socket<65> Ͻ<EFBFBD> <CFBD> м<EFBFBD> <D0BC> <EFBFBD> */
2025-06-27 00:32:57 +08:00
if ( listen ( sock , 10 ) = = - 1 )
{
LOG_E ( " Listen error " ) ;
goto __exit ;
}
LOG_I ( " \n TCPServer Waiting for client on port %d... \n " , port ) ;
started = 1 ;
is_running = 1 ;
timeout . tv_sec = 3 ;
timeout . tv_usec = 0 ;
while ( is_running )
{
FD_ZERO ( & readset ) ;
FD_SET ( sock , & readset ) ;
LOG_I ( " Waiting for a new connection... " ) ;
/* Wait for read or write */
if ( select ( sock + 1 , & readset , RT_NULL , RT_NULL , & timeout ) = = 0 )
continue ;
2025-07-05 19:47:28 +08:00
/* <20> <> <EFBFBD> <EFBFBD> һ <EFBFBD> <D2BB> <EFBFBD> ͻ<EFBFBD> <CDBB> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> socket<65> <74> <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> <CABD> */
2025-06-27 00:32:57 +08:00
connected = accept ( sock , ( struct sockaddr * ) & client_addr , & sin_size ) ;
2025-07-05 19:47:28 +08:00
/* <20> <> <EFBFBD> ص<EFBFBD> <D8B5> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> ӳɹ<D3B3> <C9B9> <EFBFBD> socket */
2025-06-27 00:32:57 +08:00
if ( connected < 0 )
{
LOG_E ( " accept connection failed! errno = %d " , errno ) ;
continue ;
}
2025-07-05 19:47:28 +08:00
/* <20> <> <EFBFBD> ܷ<EFBFBD> <DCB7> ص<EFBFBD> client_addrָ<72> <D6B8> <EFBFBD> ˿ͻ<CBBF> <CDBB> ˵ĵ<CBB5> ַ<EFBFBD> <D6B7> Ϣ */
2025-06-27 00:32:57 +08:00
LOG_I ( " I got a connection from (%s , %d) \n " ,
inet_ntoa ( client_addr . sin_addr ) , ntohs ( client_addr . sin_port ) ) ;
2025-07-05 19:47:28 +08:00
/* <20> ͻ<EFBFBD> <CDBB> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> ӵĴ<D3B5> <C4B4> <EFBFBD> */
2025-06-27 00:32:57 +08:00
while ( is_running )
{
FD_ZERO ( & readset_c ) ;
FD_SET ( connected , & readset_c ) ;
/* Wait for read or write */
if ( select ( connected + 1 , & readset_c , RT_NULL , RT_NULL , & timeout ) = = 0 )
continue ;
2025-07-05 19:47:28 +08:00
/* <20> <> connected socket<65> н<EFBFBD> <D0BD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> ݣ<EFBFBD> <DDA3> <EFBFBD> <EFBFBD> <EFBFBD> buffer<65> <72> 1024<32> <34> С <EFBFBD> <D0A1> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> һ <EFBFBD> <D2BB> <EFBFBD> ܹ<EFBFBD> <DCB9> յ<EFBFBD> 1024<32> <34> С <EFBFBD> <D0A1> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> */
2025-06-27 00:32:57 +08:00
bytes_received = recv ( connected , recv_data , BUFSZ , 0 ) ;
if ( bytes_received < 0 )
{
LOG_E ( " Received error, close the connect. " ) ;
closesocket ( connected ) ;
connected = - 1 ;
break ;
}
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 ( strcmp ( recv_data , " q " ) = = 0 | | 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 connect. " ) ;
closesocket ( connected ) ;
connected = - 1 ;
break ;
}
else if ( strcmp ( recv_data , " exit " ) = = 0 )
{
2025-07-05 19:47:28 +08:00
/* <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> յ<EFBFBD> <D5B5> <EFBFBD> exit<69> <74> <EFBFBD> <EFBFBD> <EFBFBD> ر<EFBFBD> <D8B1> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> */
2025-06-27 00:32:57 +08:00
closesocket ( connected ) ;
connected = - 1 ;
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> connected socket */
2025-06-27 00:32:57 +08:00
ret = send ( connected , send_data , rt_strlen ( send_data ) , 0 ) ;
if ( ret < 0 )
{
LOG_E ( " send error, close the connect. " ) ;
closesocket ( connected ) ;
connected = - 1 ;
break ;
}
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 ( connected > = 0 )
{
closesocket ( connected ) ;
connected = - 1 ;
}
if ( sock > = 0 )
{
closesocket ( sock ) ;
sock = - 1 ;
}
started = 0 ;
is_running = 0 ;
return ;
}
static void usage ( void )
{
rt_kprintf ( " Usage: tcpserver -p <port> \n " ) ;
rt_kprintf ( " tcpserver --stop \n " ) ;
rt_kprintf ( " tcpserver --help \n " ) ;
rt_kprintf ( " \n " ) ;
rt_kprintf ( " Miscellaneous: \n " ) ;
rt_kprintf ( " -p Specify the host port number \n " ) ;
rt_kprintf ( " --stop Stop tcpserver program \n " ) ;
rt_kprintf ( " --help Print help information \n " ) ;
}
static void tcpserver_test ( int argc , char * * argv )
{
rt_thread_t tid ;
if ( argc = = 1 | | argc > 3 )
{
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 ] , " -p " ) = = 0 )
{
if ( started )
{
LOG_I ( " The tcpclient has started! " ) ;
LOG_I ( " Please stop tcpclient firstly, by: tcpclient --stop " ) ;
return ;
}
port = atoi ( argv [ 2 ] ) ;
}
else
{
goto __usage ;
}
}
tid = rt_thread_create ( " tcp_serv " ,
tcpserv , 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 ( tcpserver_test , tcpserver ,
Start a tcp server . Help : tcpserver - - help ) ;
# endif