LWIP_STM32_ENC28J60_NETCONN_TCP_SERVICER(5)
前面说了TCP客户端通讯,这一篇来说说单片机作为服务器的通讯方法
tcp客户端和服务器的链接做大的不同在于服务器是不需要主动链接谁的,他只需要绑定在自己得一个特定的端口之上,等别人来连接就好了,先创建任务
//创建TCP服务器线程
//返回值:0 TCP服务器创建成功
// 其他 TCP服务器创建失败
INT8U tcp_server_init(void)
{
INT8U res;
OS_CPU_SR cpu_sr; OS_ENTER_CRITICAL(); //关中断
res = OSTaskCreate(tcp_server_thread,(void*),(OS_STK*)&TCPSERVER_TASK_STK[TCPSERVER_STK_SIZE-],TCPSERVER_PRIO); //创建TCP服务器线程
OS_EXIT_CRITICAL(); //开中断 return res;
}
任务循环如下
//tcp服务器任务
static void tcp_server_thread(void *arg)
{
OS_CPU_SR cpu_sr;
u32 data_len = ;
struct pbuf *q;
err_t err,recv_err;
u8 remot_addr[];
struct netconn *conn, *newconn;
static ip_addr_t ipaddr;
static u16_t port;
struct netbuf *recvbuf; while(dhcpstatus != )//等待dhcp成功
{
OSTimeDly();
//printf("wait dhcp\r\n");
} LWIP_UNUSED_ARG(arg);
printf("创建一个TCP链接\r\n");
conn = netconn_new(NETCONN_TCP); //创建一个TCP链接
netconn_bind(conn,IP_ADDR_ANY,TCP_SERVER_PORT); //绑定端口 8088号端口
netconn_listen(conn); //进入监听模式
printf("进入监听模式");
//这个地方阻塞之后会造成客户端连不上,报错为the socket is marked as non blocking,后面研究
// conn->recv_timeout = 10; //禁止阻塞线程 等待10ms
while ()
{
err = netconn_accept(conn,&newconn); //接收连接请求
newconn->recv_timeout = ; if (err == ERR_OK) //处理新连接的数据
{
printf("处理新连接的数据"); netconn_getaddr(newconn,&ipaddr,&port,); //获取远端IP地址和端口号 remot_addr[] = (uint8_t)(ipaddr.addr >> );
remot_addr[] = (uint8_t)(ipaddr.addr>> );
remot_addr[] = (uint8_t)(ipaddr.addr >> );
remot_addr[] = (uint8_t)(ipaddr.addr);
printf("主机%d.%d.%d.%d连接上服务器,主机端口号为:%d\r\n",\
remot_addr[], remot_addr[],remot_addr[],remot_addr[],port); while()
{
if(keyValue == KEY_UP)
{
keyValue = ;
tcp_server_flag = LWIP_SEND_DATA;
}
if((tcp_server_flag & LWIP_SEND_DATA) == LWIP_SEND_DATA) //有数据要发送
{
err = netconn_write(newconn ,tcp_server_sendbuf,strlen((char*)tcp_server_sendbuf),NETCONN_COPY); //发送tcp_server_sendbuf中的数据
if(err != ERR_OK)
{
printf("发送失败\r\n");
}
tcp_server_flag &= ~LWIP_SEND_DATA;
} if((recv_err = netconn_recv(newconn,&recvbuf)) == ERR_OK) //接收到数据
{
OS_ENTER_CRITICAL(); //关中断
memset(tcp_server_recvbuf,,TCP_SERVER_RX_BUFSIZE); //数据接收缓冲区清零
for(q=recvbuf->p;q!=NULL;q=q->next) //遍历完整个pbuf链表
{
//判断要拷贝到TCP_SERVER_RX_BUFSIZE中的数据是否大于TCP_SERVER_RX_BUFSIZE的剩余空间,如果大于
//的话就只拷贝TCP_SERVER_RX_BUFSIZE中剩余长度的数据,否则的话就拷贝所有的数据
if(q->len > (TCP_SERVER_RX_BUFSIZE-data_len)) memcpy(tcp_server_recvbuf+data_len,q->payload,(TCP_SERVER_RX_BUFSIZE-data_len));//拷贝数据
else memcpy(tcp_server_recvbuf+data_len,q->payload,q->len);
data_len += q->len;
if(data_len > TCP_SERVER_RX_BUFSIZE) break; //超出TCP客户端接收数组,跳出
}
OS_EXIT_CRITICAL(); //开中断
data_len=; //复制完成后data_len要清零。
printf("%s\r\n",tcp_server_recvbuf); //通过串口发送接收到的数据
netbuf_delete(recvbuf);
}else if(recv_err == ERR_CLSD) //关闭连接
{
netconn_close(newconn);
netconn_delete(newconn);
printf("主机:%d.%d.%d.%d断开与服务器的连接\r\n",remot_addr[], remot_addr[],remot_addr[],remot_addr[]);
break;
}
}
OSTimeDly();
}
OSTimeDly();
}
}
这里面用了两个服务器特有的api,如下
netconn_bind(conn,IP_ADDR_ANY,TCP_SERVER_PORT); //绑定端口 8088号端口
netconn_listen(conn); //进入监听模式
其实严格来说,监听之后应该来一个任务生成一个新的任务处理相应的链接,这个demo里面没这个做,循序渐进嘛
代码位置如下
http://download.csdn.net/detail/dengrengong/8599075
LWIP_STM32_ENC28J60_NETCONN_TCP_SERVICER(5)的更多相关文章
- stm32 学习参考(转)
源:stm32 学习参考 单片机裸机下写一个自己的shell调试器 LWIP_STM32_ENC28J60_NETCONN_TCP_SERVICER(5) LWIP_STM32_ENC ...
- Angular2入门系列教程7-HTTP(一)-使用Angular2自带的http进行网络请求
上一篇:Angular2入门系列教程6-路由(二)-使用多层级路由并在在路由中传递复杂参数 感觉这篇不是很好写,因为涉及到网络请求,如果采用真实的网络请求,这个例子大家拿到手估计还要自己写一个web ...
- Angular2学习笔记(1)
Angular2学习笔记(1) 1. 写在前面 之前基于Electron写过一个Markdown编辑器.就其功能而言,主要功能已经实现,一些小的不影响使用的功能由于时间关系还没有完成:但就代码而言,之 ...
- ASP.NET Core 之 Identity 入门(一)
前言 在 ASP.NET Core 中,仍然沿用了 ASP.NET里面的 Identity 组件库,负责对用户的身份进行认证,总体来说的话,没有MVC 5 里面那么复杂,因为在MVC 5里面引入了OW ...
- ABP入门系列(1)——学习Abp框架之实操演练
作为.Net工地搬砖长工一名,一直致力于挖坑(Bug)填坑(Debug),但技术却不见长进.也曾热情于新技术的学习,憧憬过成为技术大拿.从前端到后端,从bootstrap到javascript,从py ...
- Online Judge(OJ)搭建(第一版)
搭建 OJ 需要的知识(重要性排序): Java SE(Basic Knowledge, String, FileWriter, JavaCompiler, URLClassLoader, Secur ...
- 如何一步一步用DDD设计一个电商网站(九)—— 小心陷入值对象持久化的坑
阅读目录 前言 场景1的思考 场景2的思考 避坑方式 实践 结语 一.前言 在上一篇中(如何一步一步用DDD设计一个电商网站(八)—— 会员价的集成),有一行注释的代码: public interfa ...
- 如何一步一步用DDD设计一个电商网站(八)—— 会员价的集成
阅读目录 前言 建模 实现 结语 一.前言 前面几篇已经实现了一个基本的购买+售价计算的过程,这次再让售价丰满一些,增加一个会员价的概念.会员价在现在的主流电商中,是一个不大常见的模式,其带来的问题是 ...
- 【.net 深呼吸】细说CodeDom(5):类型成员
前文中,老周已经厚着脸皮介绍了类型的声明,类型里面包含的自然就是类型成员了,故,顺着这个思路,今天咱们就了解一下如何向类型添加成员. 咱们都知道,常见的类型成员,比如字段.属性.方法.事件.表示代码成 ...
随机推荐
- 学习笔记:GLSL Core Tutorial – Vertex Shader(内置变量说明)
1.每个Vertex Shader都有用户定义的输入属性,例如:位置,法线向量和纹理坐标等.Vertex Shaders也接收一致变量(uniform variables). uniform vari ...
- SSH整合环境下Spring配置文件的配置
applicationContext.xml: <?xml version="1.0" encoding="UTF-8"?> <beans x ...
- eclipse背景颜色修改插件color theme
对于长时间编码的程序猿来说,这个插件可以说是福音了. 安装方式有两种: 1.可以直接在eclipse的eclipse marketplace 那里搜索安装 2.可以在Help->Install ...
- 命令行从Android手机中导出已安装APK的方法调研
一.背景 二.步骤 一.背景 很多时候,APK文件只存在于应用市场,在PC上无法直接下载.用手机下载下来后就直接安装了,也不能保存原始的APK文件. APK安装到手机后,Android系统会保存一份和 ...
- 单独谈谈 Android Cursor 的使用细节
使用过 SQLite 数据库对 Cursor 应该不陌生,这里单独拿出来谈一下,加深对Android SQLite中使用 Cursor 的理解. 在你理解和使用 Android Cursor 的时候你 ...
- UVALive 2053 Puzzlestan(深搜+技巧)
这个题目的深搜形式,我也找出来了,dfs(i,j)表示第i个人选到了第j个物品,但是我却无限RE了,原因是我的viod型深搜太过暴力,我当时定义了一个计数器,来记录并限制递归的层数,发现它已经递归到了 ...
- poj 3020 Antenna Placement (最小路径覆盖)
二分图题目 当时看到网上有人的博客写着最小边覆盖,也有人写最小路径覆盖,我就有点方了,斌哥(kuangbin)的博客上只给了代码,没有解释,但是现在我还是明白了,这是个最小路径覆盖(因为我现在还不知道 ...
- vbs打包exe工具
工具下载:http://yunpan.cn/cceRRbszUt5MC 访问密码 66e2
- 随机法解决TSP问题
TSP问题一直是个头疼的问题,但是解决的方法数不胜数,很多的算法也都能解决.百度资料一大堆,但是我找到了代码比较简练的一种.随机法.下面只是个人的看法而已,如果有任何问题虚心接受. 顾名思义,随机法就 ...
- 利用hibernate实现oracle(每张表的ID)自动增长
设置ID的增长策略是sequence,同时指定sequence的名字,最好每个表建一个sequence 例如创建一个序列:CREATE SEQUENCE DEPARTMENT_ID_SEQ MINVA ...