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.
156 lines
3.3 KiB
156 lines
3.3 KiB
|
2 weeks ago
|
#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));
|
||
|
|
}
|
||
|
|
}
|