Files
luban-lite/bsp/examples/test-lwip/test-tcp/test_tcp_socket.c
刘可亮 11c97ef399 v1.2.1
2025-07-22 11:15:46 +08:00

200 lines
5.0 KiB
C

/*
* Copyright (c) 2025, ArtInChip Technology Co., Ltd
*
* SPDX-License-Identifier: Apache-2.0
*
* Authors: lv.wu@artinchip.com
*/
#include "rtconfig.h"
#ifdef KERNEL_RTTHREAD
#include <rtthread.h>
#endif
#include <stdio.h>
#include "sys/socket.h"
#include "aic_osal.h"
#define SERVER_PORT 8080
#define SOCK_RCV_BUF_SZ 4096
static u8_t sock_rcv_buf[SOCK_RCV_BUF_SZ] = "Aicinchip!\n";
static int socket_startup()
{
int ret_val = -1;
int listen_fd = -1;
struct sockaddr_in srv_sockaddr;
memset(&srv_sockaddr, 0, sizeof(struct sockaddr_in));
ret_val = socket(AF_INET, SOCK_STREAM, 0);
if (ret_val < 0)
{
printf("Socket alloc error\n");
return -1;
}
listen_fd = ret_val;
int attr_bind = 1;
setsockopt(listen_fd, SOL_SOCKET, SO_REUSEADDR, &attr_bind, sizeof(attr_bind));
srv_sockaddr.sin_family = AF_INET;
srv_sockaddr.sin_len = sizeof(struct sockaddr_in);
srv_sockaddr.sin_port = htons(SERVER_PORT);
srv_sockaddr.sin_addr.s_addr = htonl(INADDR_ANY);
ret_val = bind(listen_fd, (void *)&srv_sockaddr, sizeof(struct sockaddr_in));
if (ret_val < 0)
{
closesocket(listen_fd);
printf("!!!!!!!Bind error\n");
return -1;
}
ret_val = listen(listen_fd, 3);
if (ret_val < 0)
{
closesocket(listen_fd);
printf("!!!!!!!Listen error\n");
return -1;
}
return listen_fd;
}
static int set_tcp_keepalive(int clint_fd)
{
int keepalive = 1;
setsockopt(clint_fd,SOL_SOCKET, SO_KEEPALIVE,(void*)&keepalive, sizeof(keepalive));
int keepalive_idle = 30;
setsockopt(clint_fd,IPPROTO_TCP, TCP_KEEPIDLE,(void*)&keepalive_idle,sizeof(keepalive_idle));
int keepalive_intvl = 1;
setsockopt(clint_fd,IPPROTO_TCP, TCP_KEEPINTVL,(void*)&keepalive_intvl,sizeof(keepalive_intvl));
int keepalive_count = 3;
setsockopt(clint_fd,IPPROTO_TCP, TCP_KEEPCNT,(void*)&keepalive_count,sizeof(keepalive_count));
return 0;
}
void tcp_server_echo_back_thread(void *para)
{
int i;
int ret_val = 0;
int listen_fd, max_fd, clint_fd;
struct sockaddr_in cln_sockaddr;
int length;
socklen_t cln_length;
fd_set read_set,all_set;
restart:
FD_ZERO(&all_set);
memset(&cln_sockaddr, 0, sizeof(struct sockaddr_in));
ret_val = socket_startup();
if (ret_val < 0)
return;
listen_fd = ret_val;
max_fd = listen_fd;
FD_SET(listen_fd, &all_set);
printf("Tcp Server echo back task start, port : 0x%02x\n", SERVER_PORT);
while (1)
{
read_set = all_set;
ret_val = select(max_fd + 1, &read_set, NULL, NULL, NULL);
if (ret_val > 0)
{
if (FD_ISSET(listen_fd, &read_set))
{
clint_fd = accept(listen_fd, (void *)&cln_sockaddr, &cln_length);
if (clint_fd < 0)
{
printf("Accept error\n");
continue;
}
FD_SET(clint_fd, &all_set);
set_tcp_keepalive(clint_fd);
if (clint_fd > max_fd)
{
max_fd = clint_fd;
}
if (ret_val == 1)
{
continue;
}
}
for (i = listen_fd + 1; i < FD_SETSIZE; i++)
{
if (FD_ISSET(i, &read_set))
{
ret_val = recv(i, sock_rcv_buf, SOCK_RCV_BUF_SZ, 0);
if (ret_val < 0)
{
if(errno == EWOULDBLOCK || errno == EAGAIN)
continue;
printf("socket recv ERROR!!!\r\n");
closesocket(i);
FD_CLR(i, &all_set);
continue;
} else if (ret_val == 0) {
printf("remote has been disconnected\r\n");
closesocket(i);
FD_CLR(i, &all_set);
continue;
}
length = ret_val;
ret_val = send(i, sock_rcv_buf, length, 0);
if (ret_val <= 0)
{
printf("socket send ERROR!!!\r\n");
closesocket(i);
FD_CLR(i, &all_set);
continue;
}
}
}
}
else
{
for (i = listen_fd; i < FD_SETSIZE; i++)
{
if (FD_ISSET(i, &all_set))
closesocket(i);
}
printf("\n#######Restart######\n");
goto restart;
}
}
}
int cmd_test_tcp(int argc, char *argv[])
{
static int init_flag = 0;
if (init_flag) {
printf("Failed: Only start once\n");
return -1;
}
init_flag++;
aicos_thread_create("tcp server echo back", 4096, 22, tcp_server_echo_back_thread, NULL);
return 0;
}
MSH_CMD_EXPORT_ALIAS(cmd_test_tcp, test_tcp, test tcp server ehco);