短的新大板V2630 测试程序
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.
 
 
 

155 lines
3.3 KiB

#include "tcp_server.h"
#include "lwip/tcp.h"
#include "lwip/memp.h"
#include <string.h>
static client_conn_t clients[MAX_CLIENTS];
static struct tcp_pcb *server_pcb = NULL;
// 回调函数声明
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);
// 初始化TCP服务器
void tcp_server_init(uint16_t port) {
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_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);
}
}
}
}
// 定时器回调(从主定时器中断调用)
void tcp_server_timer_callback(void) {
static uint32_t counter = 0;
counter++;
// 每5秒发送一次数据
if (counter % 5 == 0) {
const char *msg = "Hello from STM32 TCP Server!\r\n";
tcp_send_to_all_clients(msg, strlen(msg));
}
}