doubao_chat/lib/net/AT/at_socket.c

489 lines
14 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#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 *********************/