489 lines
14 KiB
C
489 lines
14 KiB
C
#include "sock_api/sock_api.h"
|
||
#include "os/os_api.h"
|
||
#include "system/includes.h"
|
||
#include "wifi/wifi_connect.h"
|
||
#include "lwip.h"
|
||
#include "lwip/sockets.h"
|
||
#include "lwip/netdb.h"
|
||
#include "at_socket.h"
|
||
|
||
/********************** TCP_SERVER_BEGIN *********************/
|
||
|
||
#define MAX_RECV_BUF_SIZE 50 //单次能接收数据的最大字节数(Bytes)
|
||
|
||
static int accept_pid = -1; //tcp_sock_accpet线程的句柄
|
||
static int recv_pid_1 = -1; //tcp_recv_accpet线程的句柄
|
||
|
||
//tcp_client数据结构
|
||
struct tcp_client_info {
|
||
struct list_head entry; //链表节点
|
||
struct sockaddr_in remote_addr; //tcp_client地址信息
|
||
void *fd; //建立连接后的套接字
|
||
};
|
||
|
||
//tcp_server数据结构
|
||
struct tcp_server_info {
|
||
struct list_head client_head; //链表
|
||
struct sockaddr_in local_addr; //tcp_server地址信息
|
||
void *fd; //tcp_server套接字
|
||
OS_MUTEX tcp_mutex; //互斥锁
|
||
};
|
||
|
||
static struct tcp_server_info server_info;
|
||
|
||
static void tcp_sock_accpet(void);
|
||
static void tcp_recv_handler(void);
|
||
static struct tcp_client_info *get_tcp_client_info(void);
|
||
static void tcp_client_quit(struct tcp_client_info *priv);
|
||
|
||
|
||
//功 能:向tcp_client发送消息
|
||
//参 数:void *sock_hdl :socket句柄
|
||
// const void *buf:需要发送的数据BUF
|
||
// u32 len : BUF大小
|
||
//返回值:返回发送成功的数据的字节数;返回-1,发送失败
|
||
static int tcp_send_data(void *sock_hdl, const void *buf, u32 len)
|
||
{
|
||
return sock_send(sock_hdl, buf, len, 0);
|
||
}
|
||
|
||
|
||
//功 能:接收tcp_client的数据
|
||
//参 数:void *sock_hdl :socket句柄
|
||
// void *buf :需要接收数据BUF
|
||
// u32 len : BUF大小
|
||
//返回值:返回接收成功的数据的字节数;返回-1,发送失败
|
||
static int tcp_recv_data(void *sock_hdl, void *buf, u32 len)
|
||
{
|
||
return sock_recv(sock_hdl, buf, len, 0);
|
||
}
|
||
|
||
|
||
//功 能:tcp_server接收线程,用于接收tcp_client的数据
|
||
//参 数: 无
|
||
//返回值:无
|
||
static void tcp_recv_handler(void)
|
||
{
|
||
struct tcp_client_info *client_info = NULL;
|
||
char recv_buf[MAX_RECV_BUF_SIZE] = {0};
|
||
|
||
_reconnect_:
|
||
|
||
do {
|
||
client_info = get_tcp_client_info();
|
||
os_time_dly(5);
|
||
} while (client_info == NULL);
|
||
|
||
for (;;) {
|
||
if (tcp_recv_data(client_info->fd, recv_buf, sizeof(recv_buf)) > 0) {
|
||
printf("Received data from (ip : %s, port : %d)\r\n", inet_ntoa(client_info->remote_addr.sin_addr), client_info->remote_addr.sin_port);
|
||
printf("recv_buf = %s.\n", recv_buf);
|
||
memset(recv_buf, 0, sizeof(recv_buf));
|
||
//此处可添加数据处理函数
|
||
tcp_send_data(client_info->fd, "Data received successfully!", strlen("Data received successfully!"));
|
||
} else {
|
||
tcp_client_quit(client_info);
|
||
goto _reconnect_;
|
||
}
|
||
}
|
||
}
|
||
|
||
//功 能:tcp_sock_accpet线程,用于接收tcp_client的连接请求
|
||
//参 数: void *priv:NULL
|
||
//返回值:无
|
||
static void tcp_sock_accpet(void)
|
||
{
|
||
socklen_t len = sizeof(server_info.local_addr);
|
||
|
||
for (;;) {
|
||
struct tcp_client_info *client_info = calloc(1, sizeof(struct tcp_client_info));
|
||
if (client_info == NULL) {
|
||
printf(" %s calloc fail\n", __FILE__);
|
||
return;
|
||
}
|
||
|
||
client_info->fd = sock_accept(server_info.fd, (struct sockaddr *)&client_info->remote_addr, &len, NULL, NULL);
|
||
if (client_info->fd == NULL) {
|
||
printf("%s socket_accept fail\n", __FILE__);
|
||
return;
|
||
}
|
||
|
||
os_mutex_pend(&server_info.tcp_mutex, 0);
|
||
list_add_tail(&client_info->entry, &server_info.client_head);
|
||
os_mutex_post(&server_info.tcp_mutex);
|
||
|
||
printf("%s, build connnect success.\n", inet_ntoa(client_info->remote_addr.sin_addr));
|
||
}
|
||
}
|
||
|
||
//功 能:搭建tcp_server
|
||
//参 数: int port:端口号
|
||
//返回值:返回0,成功;返回-1,失败
|
||
static int tcp_server_init(int port)
|
||
{
|
||
u32 opt = 1;
|
||
|
||
memset(&server_info, 0, sizeof(server_info));
|
||
|
||
server_info.local_addr.sin_family = AF_INET;
|
||
server_info.local_addr.sin_addr.s_addr = htonl(INADDR_ANY);
|
||
server_info.local_addr.sin_port = htons(port);
|
||
|
||
server_info.fd = sock_reg(AF_INET, SOCK_STREAM, 0, NULL, NULL);
|
||
if (server_info.fd == NULL) {
|
||
printf("%s build socket fail\n", __FILE__);
|
||
return -1;
|
||
}
|
||
|
||
if (sock_setsockopt(server_info.fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) < 0) {
|
||
printf("%s sock_setsockopt fail\n", __FILE__);
|
||
return -1;
|
||
}
|
||
|
||
if (sock_bind(server_info.fd, (struct sockaddr *)&server_info.local_addr, sizeof(struct sockaddr))) {
|
||
printf("%s sock_bind fail\n", __FILE__);
|
||
return -1;
|
||
}
|
||
|
||
if (sock_listen(server_info.fd, 0x2) != 0) {
|
||
printf("%s sock_listen fail\n", __FILE__);
|
||
return -1;
|
||
}
|
||
|
||
if (os_mutex_create(&server_info.tcp_mutex) != OS_NO_ERR) {
|
||
printf("%s os_mutex_create fail\n", __FILE__);
|
||
return -1;
|
||
}
|
||
|
||
INIT_LIST_HEAD(&server_info.client_head);
|
||
|
||
//创建线程,用于接收tcp_client的连接请求
|
||
if (thread_fork("tcp_sock_accpet", 26, 256, 0, &accept_pid, tcp_sock_accpet, NULL) != OS_NO_ERR) {
|
||
printf("%s thread fork fail\n", __FILE__);
|
||
return -1;
|
||
}
|
||
|
||
//创建线程,用于接收tcp_client的数据
|
||
if (thread_fork("tcp_recv_handler", 25, 512, 0, &recv_pid_1, tcp_recv_handler, NULL) != OS_NO_ERR) {
|
||
printf("%s thread fork fail\n", __FILE__);
|
||
return -1;
|
||
}
|
||
|
||
return 0;
|
||
}
|
||
|
||
//功 能:注销tcp_client
|
||
//参 数: struct tcp_client_info *priv:需要注销的tcp_client
|
||
//返回值:无
|
||
static void tcp_client_quit(struct tcp_client_info *priv)
|
||
{
|
||
list_del(&priv->entry);
|
||
sock_set_quit(priv->fd);
|
||
sock_unreg(priv->fd);
|
||
priv->fd = NULL;
|
||
free(priv);
|
||
}
|
||
|
||
//功 能:获取当前最新的tcp_client
|
||
//参 数: 无
|
||
//返回值:返回获取的tcp_client
|
||
static struct tcp_client_info *get_tcp_client_info(void)
|
||
{
|
||
struct list_head *pos = NULL;
|
||
struct tcp_client_info *client_info = NULL;
|
||
struct tcp_client_info *old_client_info = NULL;
|
||
|
||
|
||
os_mutex_pend(&server_info.tcp_mutex, 0);
|
||
|
||
list_for_each(pos, &server_info.client_head) {
|
||
client_info = list_entry(pos, struct tcp_client_info, entry);
|
||
}
|
||
|
||
os_mutex_post(&server_info.tcp_mutex);
|
||
|
||
return client_info;
|
||
}
|
||
|
||
//功 能:注销tcp_server
|
||
//参 数: 无
|
||
//返回值:无
|
||
static void tcp_server_exit(void)
|
||
{
|
||
struct list_head *pos = NULL;
|
||
struct tcp_client_info *client_info = NULL;
|
||
|
||
thread_kill(&accept_pid, KILL_WAIT);
|
||
thread_kill(&recv_pid_1, KILL_WAIT);
|
||
|
||
os_mutex_pend(&server_info.tcp_mutex, 0);
|
||
|
||
list_for_each(pos, &server_info.client_head) {
|
||
client_info = list_entry(pos, struct tcp_client_info, entry);
|
||
if (client_info) {
|
||
list_del(&client_info->entry);
|
||
sock_unreg(client_info->fd);
|
||
client_info->fd = NULL;
|
||
free(client_info);
|
||
}
|
||
}
|
||
|
||
os_mutex_post(&server_info.tcp_mutex);
|
||
|
||
os_mutex_del(&server_info.tcp_mutex, OS_DEL_NO_PEND);
|
||
}
|
||
|
||
static void tcp_server_start(void *priv)
|
||
{
|
||
int err;
|
||
enum wifi_sta_connect_state state;
|
||
|
||
while (1) {
|
||
printf("Connecting to the network...\n");
|
||
state = wifi_get_sta_connect_state();
|
||
if (WIFI_STA_NETWORK_STACK_DHCP_SUCC == state) {
|
||
printf("Network connection is successful!\n");
|
||
break;
|
||
}
|
||
|
||
os_time_dly(1000);
|
||
}
|
||
|
||
err = tcp_server_init(60000);
|
||
if (err == -1) {
|
||
printf("tcp_server_init faile\n");
|
||
tcp_server_exit();
|
||
}
|
||
}
|
||
|
||
//应用程序入口,需要运行在STA模式下
|
||
void tcp_server_run(void)
|
||
{
|
||
if (thread_fork("tcp_server_start", 10, 512, 0, NULL, tcp_server_start, NULL) != OS_NO_ERR) {
|
||
printf("thread fork fail\n");
|
||
}
|
||
}
|
||
|
||
/********************** TCP_SERVER_END *********************/
|
||
|
||
/********************** TCP_CLIENT_BEGIN *********************/
|
||
|
||
#define CLIENT_TCP_PORT 0 //客户端端口号
|
||
static void *sock = NULL;
|
||
#define SERVER_TCP_IP "192.168.31.156" //服务端ip
|
||
#define SERVER_TCP_PORT 60000 //服务端端口号
|
||
|
||
static int tcp_client_init(const char *server_ip, const int server_port)
|
||
{
|
||
//struct sockaddr_in local;
|
||
struct sockaddr_in dest;
|
||
|
||
//创建socket
|
||
sock = sock_reg(AF_INET, SOCK_STREAM, 0, NULL, NULL);
|
||
if (sock == NULL) {
|
||
printf("sock_reg fail.\n");
|
||
return -1;
|
||
}
|
||
|
||
//绑定本地地址信息
|
||
// local.sin_addr.s_addr = INADDR_ANY;
|
||
// local.sin_port = htons(CLIENT_TCP_PORT);
|
||
// local.sin_family = AF_INET;
|
||
// if (0 != sock_bind(sock, (struct sockaddr *)&local, sizeof(struct sockaddr_in))) {
|
||
// sock_unreg(sock);
|
||
// printf("sock_bind fail.\n");
|
||
// return -1;
|
||
// }
|
||
|
||
//连接指定地址服务端
|
||
dest.sin_family = AF_INET;
|
||
dest.sin_addr.s_addr = inet_addr(server_ip);
|
||
dest.sin_port = htons(server_port);
|
||
if (0 != sock_connect(sock, (struct sockaddr *)&dest, sizeof(struct sockaddr_in))) {
|
||
printf("sock_connect fail.\n");
|
||
sock_unreg(sock);
|
||
return -1;
|
||
}
|
||
|
||
return 0;
|
||
}
|
||
|
||
//接收数据
|
||
static int tcp_client_recv_data(const void *sock_hdl, void *buf, u32 len)
|
||
{
|
||
return sock_recvfrom(sock_hdl, buf, len, 0, NULL, NULL);
|
||
}
|
||
|
||
//tcp client任务
|
||
static void tcp_client_task(void *priv)
|
||
{
|
||
int err;
|
||
char *payload = "Please send me some data!";
|
||
char recv_buf[1024];
|
||
int recv_len;
|
||
int send_len;
|
||
|
||
err = tcp_client_init(SERVER_TCP_IP, SERVER_TCP_PORT);
|
||
if (err) {
|
||
printf("tcp_client_init err!");
|
||
return;
|
||
}
|
||
|
||
send_len = tcp_send_data(sock, payload, strlen(payload));
|
||
if (send_len == -1) {
|
||
printf("sock_sendto err!");
|
||
sock_unreg(sock);
|
||
return;
|
||
}
|
||
|
||
for (;;) {
|
||
recv_len = tcp_client_recv_data(sock, recv_buf, sizeof(recv_buf));
|
||
if ((recv_len != -1) && (recv_len != 0)) {
|
||
recv_buf[recv_len] = '\0';
|
||
printf("Received %d bytes, data: %s\n\r", recv_len, recv_buf);
|
||
tcp_send_data(sock, "Data received successfully!", strlen("Data received successfully!"));
|
||
} else {
|
||
printf("sock_recvfrom err!");
|
||
break;
|
||
}
|
||
}
|
||
|
||
if (sock) {
|
||
sock_unreg(sock);
|
||
sock = NULL;
|
||
}
|
||
|
||
}
|
||
|
||
static void tcp_client_start(void *priv)
|
||
{
|
||
enum wifi_sta_connect_state state;
|
||
|
||
while (1) {
|
||
printf("Connecting to the network...\n");
|
||
state = wifi_get_sta_connect_state() ;
|
||
if (WIFI_STA_NETWORK_STACK_DHCP_SUCC == state) {
|
||
printf("Network connection is successful!\n");
|
||
break;
|
||
}
|
||
os_time_dly(1000);
|
||
}
|
||
|
||
if (thread_fork("tcp_client_task", 10, 1024, 0, NULL, tcp_client_task, NULL) != OS_NO_ERR) {
|
||
printf("thread fork fail\n");
|
||
}
|
||
}
|
||
|
||
//应用程序入口,需要运行在STA模式下
|
||
void tcp_client_run(void)
|
||
{
|
||
|
||
if (thread_fork("tcp_client_start", 10, 512, 0, NULL, tcp_client_start, NULL) != OS_NO_ERR) {
|
||
printf("thread fork fail\n");
|
||
}
|
||
}
|
||
|
||
/********************** TCP_CLIENT_END *********************/
|
||
|
||
/********************** UDP_SERVER_BEGIN *********************/
|
||
|
||
static void *socket_fd = 0;
|
||
static int recv_pid = 0;
|
||
|
||
//功 能:udp_server接收线程,用于接收udp_client的数据
|
||
//参 数: 无
|
||
//返回值:无
|
||
static void udp_recv_handler(void)
|
||
{
|
||
struct sockaddr_in remote_addr = {0};
|
||
socklen_t len = sizeof(remote_addr);
|
||
int recv_len = 0;
|
||
u8 recv_buf[50] = {0};
|
||
|
||
for (;;) {
|
||
|
||
//接收udp_client的数据,并获取udp_client的地址信息
|
||
recv_len = sock_recvfrom(socket_fd, recv_buf, sizeof(recv_buf), 0, (struct sockaddr *)&remote_addr, &len);
|
||
printf("\n recv_len is %d \n", recv_len);
|
||
|
||
//将接收到的数据发送至udp_client
|
||
sock_sendto(socket_fd, recv_buf, sizeof(recv_buf), 0, (struct sockaddr *)&remote_addr, sizeof(struct sockaddr_in));
|
||
|
||
memset(recv_buf, 0, sizeof(recv_buf));
|
||
}
|
||
}
|
||
|
||
//功 能:搭建udp_server
|
||
//参 数: int port:端口号
|
||
//返回值:返回0,成功;返回-1,失败
|
||
static int udp_server_init(int port)
|
||
{
|
||
struct sockaddr_in local_addr = {0};
|
||
|
||
local_addr.sin_family = AF_INET;
|
||
local_addr.sin_addr.s_addr = htonl(INADDR_ANY);
|
||
local_addr.sin_port = htons(port);
|
||
|
||
socket_fd = sock_reg(AF_INET, SOCK_DGRAM, 0, NULL, NULL);
|
||
if (socket_fd == NULL) {
|
||
printf("%s build socket fail\n", __FILE__);
|
||
return -1;
|
||
}
|
||
|
||
if (sock_bind(socket_fd, (struct sockaddr *)&local_addr, sizeof(struct sockaddr))) {
|
||
printf("%s sock_bind fail\n", __FILE__);
|
||
return -1;
|
||
}
|
||
|
||
//创建线程,用于接收tcp_client的数据
|
||
if (thread_fork("udp_recv_handler", 25, 512, 0, &recv_pid, udp_recv_handler, NULL) != OS_NO_ERR) {
|
||
printf("%s thread fork fail\n", __FILE__);
|
||
return -1;
|
||
}
|
||
|
||
return 0;
|
||
}
|
||
|
||
//功 能:注销udp_server
|
||
//参 数: 无
|
||
//返回值:无
|
||
static void udp_server_exit(void)
|
||
{
|
||
thread_kill(&recv_pid, KILL_WAIT);
|
||
sock_unreg(socket_fd);
|
||
}
|
||
|
||
static void udp_server_start(void *priv)
|
||
{
|
||
int err;
|
||
enum wifi_sta_connect_state state;
|
||
|
||
while (1) {
|
||
state = wifi_get_sta_connect_state();
|
||
printf("Connecting to the network...\n");
|
||
if (WIFI_STA_NETWORK_STACK_DHCP_SUCC == state) {
|
||
printf("Network connection is successful!\n");
|
||
break;
|
||
}
|
||
|
||
os_time_dly(1000);
|
||
}
|
||
|
||
err = udp_server_init(60000);
|
||
if (err == -1) {
|
||
printf("udp_server_init faile\n");
|
||
udp_server_exit();
|
||
}
|
||
}
|
||
|
||
//应用程序入口,需要运行在STA模式下
|
||
void udp_server_run(void)
|
||
{
|
||
if (thread_fork("udp_server_start", 10, 512, 0, NULL, udp_server_start, NULL) != OS_NO_ERR) {
|
||
printf("thread fork fail\n");
|
||
}
|
||
}
|
||
|
||
/********************** UDP_SERVER_END *********************/
|
||
|