仓库提交练习
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

252 lines
4.9 KiB

#include "tcp_server.h"
#include "lwip/tcp.h"
#include "lwip/memp.h"
#include <string.h>
#include "lwip.h"
#include "string.h"
#include "bsp_UDP.h"
#include "bsp_DLT_Log.h"
#include <bsp_UpperComputer_Handler.h>
#include "bsp_GPIO.h"
static client_conn_t clients[MAX_CLIENTS];
static struct tcp_pcb *server_pcb = NULL;
void send_tcp(SendDataNode **head);
// 回调函数声明
static err_t tcp_accept_cb(void *arg, struct tcp_pcb *newpcb, err_t err);
static err_t tcp_recv_cb(void *arg, struct tcp_pcb *tpcb, struct pbuf *p,
err_t err);
static void tcp_err_cb(void *arg, err_t err);
static void tcp_sent_cb(void *arg, struct tcp_pcb *tpcb, u16_t len);
SendDataNode *pTcpHead = NULL; /*初始化链表头指针,使其为空*/
void tcp_server_timer_callback();
char listIndex = 0;
SendDataNode* CreateSendDataNode(uint8_t *tx_Buf, uint8_t tx_count)
{
SendDataNode *newNode = (SendDataNode*) malloc(sizeof(SendDataNode));
if (newNode == NULL)
{
return NULL;
}
memcpy(newNode->Tx_Buf, tx_Buf, tx_count);
newNode->Tx_Count = tx_count;
newNode->next = NULL;
return newNode;
}
void insertAtTail(SendDataNode **head, uint8_t *tx_Buf, uint8_t tx_count)
{
SendDataNode *newNode = CreateSendDataNode(tx_Buf, tx_count);
// 如果链表为空
if (*head == NULL)
{
*head = newNode;
return;
}
listIndex = 0;
// 遍历到链表尾部
SendDataNode *current = *head;
while (current->next != NULL)
{
// listIndex++;
// if (listIndex >= 50)
// {
// free(current);
// return;
// }
current = current->next;
}
//SendDataNode *newNode = CreateSendDataNode(tx_Buf, tx_count);
current->next = newNode; // 尾部节点指向新节点
}
void tcp_add_sendList(uint8_t *tx_Buf, uint8_t tx_count)
{
for (int i = 0; i < MAX_CLIENTS; i++)
{
if (clients[i].active)
{
insertAtTail(&pTcpHead, tx_Buf, tx_count);
return;
}
}
}
void send_tcp(SendDataNode **head)
{
if (*head == NULL)
{
return;
}
tcp_send_to_all_clients((*head)->Tx_Buf, (*head)->Tx_Count);
SendDataNode *temp = *head;
*head = (*head)->next;
free(temp);
}
// 初始化TCP服务器
void tcp_server_init(uint16_t port)
{
GF_BSP_Interrupt_Add_CallBack(
DF_BSP_InterCall_TIM8_2ms_PeriodElapsedCallback,
tcp_server_timer_callback);
err_t err;
// 创建TCP控制块
server_pcb = tcp_new_ip_type(IPADDR_TYPE_ANY);
if (!server_pcb) return;
// 绑定到指定端口
err = tcp_bind(server_pcb, IP_ANY_TYPE, port);
if (err != ERR_OK)
{
memp_free(MEMP_TCP_PCB, server_pcb);
server_pcb = NULL;
return;
}
// 开始监听
server_pcb = tcp_listen(server_pcb);
if (!server_pcb) return;
// 设置接受连接回调
tcp_accept(server_pcb, tcp_accept_cb);
// 初始化客户端数组
memset(clients, 0, sizeof(clients));
}
// 接受新连接回调
static err_t tcp_accept_cb(void *arg, struct tcp_pcb *newpcb, err_t err)
{
LWIP_UNUSED_ARG(arg);
LWIP_UNUSED_ARG(err);
// 查找空闲的客户端槽位
int free_index = -1;
for (int i = 0; i < MAX_CLIENTS; i++)
{
if (!clients[i].active)
{
free_index = i;
break;
}
}
if (free_index == -1)
{
// 没有可用槽位,拒绝连接
tcp_abort(newpcb);
return ERR_ABRT;
}
// 配置新连接
tcp_setprio(newpcb, TCP_PRIO_MIN);
tcp_recv(newpcb, tcp_recv_cb);
tcp_err(newpcb, tcp_err_cb);
tcp_sent(newpcb, (tcp_sent_fn)tcp_sent_cb);
// 保存客户端信息
clients[free_index].pcb = newpcb;
clients[free_index].active = 1;
return ERR_OK;
}
// 接收数据回调
static err_t tcp_recv_cb(void *arg, struct tcp_pcb *tpcb, struct pbuf *p,
err_t err)
{
LWIP_UNUSED_ARG(arg);
if (!p)
{
// 连接关闭
for (int i = 0; i < MAX_CLIENTS; i++)
{
if (clients[i].pcb == tpcb)
{
clients[i].active = 0;
break;
}
}
tcp_close(tpcb);
return ERR_OK;
}
// 处理接收到的数据(这里简单释放)
tcp_recved(tpcb, p->tot_len);
pbuf_free(p);
return ERR_OK;
}
// 错误回调
static void tcp_err_cb(void *arg, err_t err)
{
LWIP_UNUSED_ARG(err);
for (int i = 0; i < MAX_CLIENTS; i++)
{
if (clients[i].pcb == arg)
{
clients[i].active = 0;
break;
}
}
}
// 数据发送完成回调
static void tcp_sent_cb(void *arg, struct tcp_pcb *tpcb, u16_t len)
{
LWIP_UNUSED_ARG(arg);
LWIP_UNUSED_ARG(tpcb);
LWIP_UNUSED_ARG(len);
// 可在此实现流量控制
}
// 向所有活跃客户端发送数据
void tcp_send_to_all_clients(const char *data, uint16_t len)
{
for (int i = 0; i < MAX_CLIENTS; i++)
{
if (clients[i].active)
{
//clients[i].pcb->flags=
// err_t err = tcp_write(clients[i].pcb, data, len,
// TCP_WRITE_FLAG_COPY);
err_t err = tcp_write(clients[i].pcb, data, len,
TCP_WRITE_FLAG_COPY);
if (err == ERR_OK)
{
tcp_output(clients[i].pcb);
}
else
{
// 发送失败,关闭连接
//clients[i].active = 0;
//tcp_close(clients[i].pcb);
}
}
}
}
int32_t counter = 0;
// 定时器回调(从主定时器中断调用)
void tcp_server_timer_callback()
{
counter++;
if (counter > 5)
{
counter = 0;
send_tcp(&pTcpHead);
};
}