首先是stm32通过W5500模块建立tcp-server服务端(购买w5500模块后都有教程 本文提供面向stm32f103rdt6的双网口例程 提取码:ptj3)
在while(1)死循环中持续监听接入的client客户端
与arm-linux不同的是,STM32无法开启线程
如果多个client接入,需要创建多个socket包与不同的client连接
W5500自带8个socket,最多监听8个client客户端
以轮询的方式进行多客户端监听
假代码如下:
#include <string.h>
#include <stdio.h>
#include <time.h>
#include "main.h"
#include "tcp_demo.h"
#include "W5500_conf.h"
#include "w5500.h"
#include "socket.h"
/* 如果需要再监听一个客户端 则需要新建一个do_tcp_server函数并将其中的 SOCK_TCPS 换成其他 socket 即可*/
void do_tcp_server(void)
{
uint16 len=0;
W5500_Use_Flag = 2;
switch(getSn_SR(SOCK_TCPS)) /*获取socket的状态*/
{
case SOCK_CLOSED: /*socket处于关闭状态*/
socket(SOCK_TCPS ,Sn_MR_TCP,local_port,Sn_MR_ND); /*打开socket*/
break;
case SOCK_INIT: /*socket已初始化状态*/
printf("SERVER处于监听状态\r\n");
listen(SOCK_TCPS); /*socket建立监听*/
//建立连接标志位
break;
case SOCK_ESTABLISHED: /*socket处于连接建立状态*/
//printf("处于建立连接状态\r\n");
if(getSn_IR(SOCK_TCPS) & Sn_IR_CON)
{
setSn_IR(SOCK_TCPS, Sn_IR_CON); /*清除接收中断标志位*/
}
len=getSn_RX_RSR(SOCK_TCPS); /*定义len为已接收数据的长度*/
if(len>0)
{
recv(SOCK_TCPS,buff,len);
buff[len]=0x00; /*添加字符串结束符*/
/* 处理来自客户端的信息 */
}
break;
case SOCK_CLOSE_WAIT: /*socket处于等待关闭状态*/
close(SOCK_TCPS);
break;
}
}
int main(void)
{
while(1)
{
do_tcp_server();
}
}
其中W5500可供选择的socket:
/*Socket 端口选择,可按自己的习惯定义*/
#define SOCK_TCPS 0
#define SOCK_TCPC 1
#define SOCK_UDPS 2
#define SOCK_WEIBO 2
#define SOCK_DHCP 3
#define SOCK_HTTPS 4
#define SOCK_DNS 5
#define SOCK_SMTP 6
#define SOCK_NTP 7
雷区1
不要用一个socket轮询访问多个不同ip,不论是客户端还是服务端。
单个socket需要进行多次的连接(connect)和断开连接(close)操作,非常浪费时间,并且容易引起逻辑缠绕。
最好的方式就是一个ip对应一个socket,建立成功连接了,就保持连接,既高效,逻辑耦合也低,只需轮询访问不同socket即可。
雷区2
通过TCP/IP协议连接时,连接成功后,即等于成功建立SOCKET保持通信。如若重启设备,形成新的SOCKET连接,则连接是否成功取决于对方设备(对方设备作为SERVER端)是否支持多CLIENT访问,若不支持会导致连接失败,需要等待对方超时处理,放弃原SOCKET,重新开放连接。
如果我方作为SERVER对方设备作为CLIENT重启设备,同理,若我方不支持多CLIENT连接,也会形成无法连接问题