本设计参考以下帖子的思路:服务器每检测到一个客户端连接请求建立一个任务
http://www.openedv.com/forum.php ... =%B7%FE%CE%F1%C6%F7
由于以上版本可读性感觉不是很好,可移植性也不好,而且需要实现客户端之间的互通,我就自己琢磨着写了一个,过程中还是有很多问题的。
新思路:TCP CLIENT结构体加入编号,用新结构体保存TCP CLIENT的地址,保存TCP CLIENT的连接状态,这样根据状态就很容易可以找到哪个TCP需要进行通信。
#define CLIENTMAX 40 //最大客户端数量
typedef struct
{
struct netconn *conn;//连接结构体
OS_TCB *clientTCB;//任务控制块
CPU_STK *clientSTK;//任务堆栈
u8 num;//CLIENT编号
}tcp_client;
typedef struct
{
tcp_client *client[CLIENTMAX];//客户端地址保存
u8 state[CLIENTMAX];//客户端状态
}client_ad;
网线插拔可以读取LAN8720寄存器判断:以下直接通过LED1亮和灭体现网线连接状态
LED1 = ~(ETH_ReadPHYRegister(0x00,29)>>6)%2; //网线热插拔检测
断开网线后需要删除所有客户端任务 并释放内存。其他任务不需要改动,重新连接之后可以正常通信(亲测通过)
断开网线后做如下处理:
for(clientnum=1;clientnum<CLIENTMAX;clientnum++) //循环检测客户端连接状态
{ //从1到40循环检测
if(clientad.state[clientnum]==1) //判断连接状态
{ //已连接
OSTaskDel(clientad.client[clientnum]->clientTCB,&oserr); //删除客户端任务
myfree(SRAMCCM, (clientad.client[clientnum]->clientTCB));//释放clientTCB内存
myfree(SRAMCCM, (clientad.client[clientnum]->clientSTK));//释放clientSTK内存
myfree(SRAMCCM, clientad.client[clientnum]); //释放 结构体 内存
printf(&quot;%d号客户端已删除\r\n&quot;,clientnum); //打印信息
clientad.state[clientnum]=0; //客户端连接状态清0 表示已断开连接
}
}
实现客户端与客户端之间的通信主要通过以下方式(我没有测试开启40个客户端通信 不过9个客户端已经亲测通过)
将 (某个客户端)的数据接收下来存入u8 rbuf[4],判断第一个是不是 'a' 第四个是不是'a' 第二个如果是0-9 如'5' 并且5号客户端已建立连接 就把第三个数据 发送到5号客户端。
这边我数据处理比较粗略,大家可以自己定协议处理。
if( rbuf[0]=='a' && rbuf[3]=='a' && ((rbuf[1]-0x30)==clientad.client[rbuf[1]-0x30]->num ) )
netconn_write(clientad.client[rbuf[1]-0x30]->conn,rbuf+2,1,NETCONN_COPY);//向指定客户端发送数据(前提是该客户端已建立连接)
具体很多细节都在源码体现了,没用到LCD,所有信息都在串口1打印,在探索者开发板调的。
标准库+UCOSIII+LWIP! |