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):类型成员
前文中,老周已经厚着脸皮介绍了类型的声明,类型里面包含的自然就是类型成员了,故,顺着这个思路,今天咱们就了解一下如何向类型添加成员. 咱们都知道,常见的类型成员,比如字段.属性.方法.事件.表示代码成 ...
随机推荐
- 字符串查找 cmd find命令
find /i "ora-" *.log 我对findstr是如此的依赖,以至于当我向各位讲解find命令的时候,我还得老老实实地在cmd窗口中敲下 find /? 这条命令,然后 ...
- oracle提高之索引学习
一. 索引介绍 1.1 索引的创建 语法 : CREATE UNIUQE | BITMAP INDEX <schema>.<index_name> ON <schema ...
- http请求连接
1.在Info.plist中添加NSAppTransportSecurity类型Dictionary.2.在NSAppTransportSecurity下添加NSAllowsArbitraryLoad ...
- 青蛙的约会<数论,extgcd>
青蛙的约会 题意: 在一个圆上有一个零刻度点,公青蛙和母青蛙分别在A点和B点<不同的位 置>,他们每秒行走的距离分别是m和n,圆的周长是L.问题是这两个青 蛙能不能相遇,若能在什么时候相遇 ...
- python 对比图片相似度
最近appium的使用越来越广泛了,对于测试本身而言,断言同样是很重要的,没有准确的断言那么就根本就不能称之为完整的测试了.那么目前先从最简单的截图对比来看.我这里分享下python的图片相似度的代码 ...
- .bat批处理命令的介绍
HUC = = D组 http://www.cnhonkerarmy.com/ 63707869 =====================================开始============ ...
- ActionBar的简单使用
只简单实现了一下ActionBar的使用,在右上角添加两个ActionBar,在左上角实现默认的返回箭头,类似于微信朋友圈的 这是MainActivity的代码: public class MainA ...
- ThinkPHP3.2.3版本框架could not find driver错误
ThinkPHP3.2.3版本框架could not find driver错误 在更新ThinkPHP框架 3.2.3 时出现错误 解决方法如下: 修改php.ini文件 extension=php ...
- Android Studio开发环境的配置
为了使开发人员与时俱进, 在这里给大家讲解一下Android Studio的安装步骤及设置. 使用的是Android的最新版本,0.4.2版本,Android Studio可以脱离Eclipse单独运 ...
- java邮件收发
http://blog.csdn.net/ycg01/article/details/1394465 java邮件收发 标签: javaimportexceptionnulluserclass 200 ...