Toggle navigation
首页
问答
文章
积分商城
专家
专区
更多专区...
文档中心
返回主站
搜索
提问
会员
中心
登录
注册
网络学习营
【7天入门RTOS网络编程】Wendell Day3-5 RTOS网络编程课作业☆☆
发布于 2018-10-24 13:19:24 浏览:1805
订阅该版
* 本帖最后由 san兄弟 于 2018-10-25 14:24 编辑 * 经过昨天和今天上午的学习摸索,Day3-5 RTOS网络编程课的作业终于有眉目了,经过思考总结了多种方法,大中午不睡觉,把做作业的过程写下来!作业要求:观看视频及文档,能够正常获取并运行示例程序,通过示例程序的学习掌握使用 Socket 进行网络编程的方法,能够实现一个简单的 TCP 聊天客户端。 **整体思路:**1. 首先根据作业中给出的服务器的情况,利用网络调试助手测试服务器。2. 发送过程由于需要在msh中输入命令,因此可以给每个命令定义一个函数,并使用MSH_CMD_EXPORT()函数输出到msh列表,这种方法输入比较简洁,但是函数数量多,无法实现作业中要求的“其他命令”;另一种想法是根据作业中的参考Log信息格式,编写名为Command的函数,在该函数中实现各命令功能,并实现“”其他命令“”功能。3. 服务器返回的数据接收程序使用阻塞接收或非阻塞接收方式。 **测试服务器:**首先根据作业要求,使用网络调试助手建立一个tcp客户端,测试服务器功能。**测试时一定要记得输入命令以后按下回车键,不然是没有反应的!**![服务器测试录像.gif](/uploads/201810/24/131646t0gfq3zg39f9wn39.gif) ** 程序实现方法1:**为每个命令编写一个函数,用于发送,并使用MSH_CMD_EXPORT()输出到msh;使用阻塞式接收程序。该方法已经有咱们的同学[yukelab](https://www.rt-thread.org/qa/space-uid-10996.html)实现了,代码写的很好,建议大家看看! [借用:方法1实现](https://club.rt-thread.org/ask/question/8135.html)。 **程序实现方法2:**依然为每个命令编写一个函数,用于发送,并使用MSH_CMD_EXPORT()输出到msh;接收程序使用非阻塞式接收。[参考资料](https://www.rt-thread.org/document/site/rtthread-application-note/components/network/an0019-rtthread-system-tcpclient-socket/)中的4.3节有非阻塞tcpclient的例程代码。 从github中下载代码,文件夹名称为tcpclient,内容如下图。按照参考资料要求将 tcpclient 文件夹 放置rt-thread\bsp\qemu-vexpress-a9目录下,然后打开examples下的tcpclient_example.c文件,将自己需要的程序添加在该文件中;或者新建一个C文件,我是新建的,所以下面按照新建文件进行哈!![tcpclient文件夹.jpg](/uploads/201810/24/140010v6u5f4k5sdyjw887.jpg) 首先删除tcpclient文件夹下的前两个文件夹(上图红框内),在rt-thread\bsp\qemu-vexpress-a9\applications路径下新建homework3_5.c文件,在env工具中输入code . 命令,即可在vs code中打开工程,然后加入以下代码,这是我改好的代码,仅供参考,可以自己按照examples下的tcpclient_example.c文件修改自己的代码。```#include
#include
#include
#include
#include
#include "tcpclient.h" static char send_data[100]; rt_tcpclient_t *handle = RT_NULL; void rt_tc_rx_cb(void *buff, rt_size_t len) { char *recv = RT_NULL; recv = malloc(len + 1); if (recv == RT_NULL) return; memcpy(recv, buff, len); *(recv + len) = '\0'; //elog_d("tc_rx_cb", "recv data: %s
", recv); rt_kprintf("%s
",recv); free(recv); } void rt_tc_test_deinit(rt_tcpclient_t *thiz) { rt_tcpclient_close(thiz); } int rt_tc_init() { /* 服务器的 ip 地址 & 服务器监听的端口号 */ handle = rt_tcpclient_start("183.193.243.90", 5000); if (handle == RT_NULL) { elog_e("tcpclient thread", "param is NULL, exit
"); return -1; } /* 注册接收回调函数 */ rt_tcpclient_attach_rx_cb(handle, rt_tc_rx_cb); elog_i("tc test", "thread init succeed
"); return 0; } MSH_CMD_EXPORT(rt_tc_init, tc); void login(int argc, char **argv) { sprintf(send_data, "login %s
", argv[1]); rt_tcpclient_send(handle, send_data, strlen(send_data)); } MSH_CMD_EXPORT(login, login ID); void say(int argc, char **argv) { int count=0; count = sprintf(send_data, "say"); for(int i=1; i
"); rt_tcpclient_send(handle, send_data, strlen(send_data)); } MSH_CMD_EXPORT(say, say something); void look(void) { sprintf(send_data, "look
"); rt_tcpclient_send(handle, send_data, strlen(send_data)); } MSH_CMD_EXPORT(look, look ID); void who(void) { sprintf(send_data, "who
"); rt_tcpclient_send(handle, send_data, strlen(send_data)); } MSH_CMD_EXPORT(who, who I am); void logout(void) { sprintf(send_data, "logout
"); rt_tcpclient_send(handle, send_data, strlen(send_data)); rt_tc_test_deinit(handle); } MSH_CMD_EXPORT(logout, logout ID);``` ![方法2代码.zip](/uploads/201810/24/153240py0525euy2mrzwru.zip) 加入代码后会发现有错误,头文件处有绿色或红色下划线(红色和绿色下划线的区别暂时没搞清楚),稍等一会右下角会弹出对话框,如图。![头文件错误.jpg](/uploads/201810/24/140524d19qe8fanx11nfxa.jpg) 下划线表示头文件找不到,弹出的对话框是提示我们设置,找到丢失的头文件。如果点击下图中的Configuration Help,则会打开网页,详细介绍如何进行配置。![头文件配置帮助.jpg](/uploads/201810/24/140524wzal42o8xj4j24da.jpg) #include
头文件找不到是因为:1. 没有在在env中打开EasyLogger工具包;2. 头文件没有添加到指定配置文件里。#include "tcpclient.h"头文件找不到是因为:1. tcpclient文件夹没有拷贝到指定目录下;2. 头文件没有添加到指定配置文件里。 在出现下划线时,单击使光标在该头文件上,可以看到出现一个小灯泡一样的图标,单击会有下拉菜单,如果当前目录下没有该头文件,即上面原因1,则下拉菜单如下:![未检测到头文件时.jpg](/uploads/201810/24/140525euizfb0i57xzb6ux.jpg)如果当前目录下有该头文件,只是没有正确配置,即上面原因2,则下拉菜单如下,此时点击Add to “......”则可以自动将该头文件添加到配置文件中,不用自己敲,很方便吧。![检测到头文件.jpg](/uploads/201810/24/140524umqvg39fzqxtx1ft.jpg)如果想自己添加头文件的话,在下图中的文件中添加。![头文件添加文件.jpg](/uploads/201810/24/140525ozmgsashhst28mhm.jpg)EasyLogger工具包添加方式如下。![EasyLogger.jpg](/uploads/201810/24/141239gdtv9t1dsjnctn19.jpg)![EasyLogger2.jpg](/uploads/201810/24/141337nt7ohoon46vb7b9v.jpg) 另外,由于我们删除了tcpclient文件夹下的examples文件夹,因此需要修改tcpclient文件夹下的SConscript文件,在下图红框语句前增加注释符#,注释掉该语句。![SConscript修改.jpg](/uploads/201810/24/143617mwe5pei9ta6e0t0z.jpg) 问题都解决了以后都在env中输入scons -j4编译,之后输入qemu启动,开始测试。上视频![方法2测试-1.gif](/uploads/201810/24/150257dpqbdbsfq3ftfvuz.gif) ![方法2测试-2.gif](/uploads/201810/24/145600jeyf9bkrpmrrzbdk.gif)可以看出整个过程基本符合要求,但是仍然有两个问题:**1. say命令后的语句长度有限制,最长10个字符(以空格区分,包括say)。**![方法2问题1.jpg](/uploads/201810/24/151311hfd8jtj9g999judi.jpg)如果想要不超出限制,可以在say后面的语句加上双引号,这样可以完整输出,但是加双引号的方法貌似不完全符合咱们作业的意思。![方法2问题1解决.jpg](/uploads/201810/24/151511fmnmbznmn2p5pg76.jpg) 还有一种方法就是在env工具中配置,将argv接收的字符串数量改大一些,确保作业够用!将红框中的10改为20对于作业来说妥妥的够用了!![方法2问题1解决2.jpg](/uploads/201810/24/151846h56jt2et6r0l4e64.jpg) **2.不支持作业中的“其他命令”功能。**![方法2问题2.jpg](/uploads/201810/24/152108z3yuuooisasurg8f.jpg)红框中的what:command not found并不是服务器返回的,而是msh输出的。 **程序实现方法3:**发送程序为单一函数,名为command,带有参数,并使用MSH_CMD_EXPORT()输出到msh;接收程序使用非阻塞式接收。[参考资料](https://www.rt-thread.org/document/site/rtthread-application-note/components/network/an0019-rtthread-system-tcpclient-socket/)中的4.3节有非阻塞tcpclient的例程代码。函数名Command来自于作业要求,不晓得理解的对不对哈,也可能作业上只是为了说明前面的是输入的命令,我仅仅提供一种思路,反正对于学习没坏处!![方法3函数名.jpg](/uploads/201810/24/152725oluwtsa9n31f9y1c.jpg)使用该方法的代码如下:```#include
#include
#include
#include
#include
#include "tcpclient.h" static char send_data[100]; rt_tcpclient_t *handle = RT_NULL; void rt_tc_rx_cb(void *buff, rt_size_t len) { char *recv = RT_NULL; recv = malloc(len + 1); if (recv == RT_NULL) return; memcpy(recv, buff, len); *(recv + len) = '\0'; rt_kprintf("%s
",recv); free(recv); } void rt_tc_test_deinit(rt_tcpclient_t *thiz) { rt_tcpclient_close(thiz); } int rt_tc_init() { /* 服务器的 ip 地址 & 服务器监听的端口号 */ handle = rt_tcpclient_start("183.193.243.90", 5000); if (handle == RT_NULL) { elog_e("tcpclient thread", "param is NULL, exit
"); return -1; } /* 注册接收回调函数 */ rt_tcpclient_attach_rx_cb(handle, rt_tc_rx_cb); elog_i("tc test", "thread init succeed
"); return 0; } MSH_CMD_EXPORT(rt_tc_init, tc); void command(int argc, char **argv) { if(strcmp(argv[1],"login")==0) { sprintf(send_data, "login %s
", argv[2]); } else if(strcmp(argv[1],"say")==0) { int count=0; count = sprintf(send_data, "say"); for(int i=2; i
"); } else if(strcmp(argv[1],"look")==0) { sprintf(send_data, "look
"); } else if(strcmp(argv[1],"who")==0) { sprintf(send_data, "who
"); } else if(strcmp(argv[1],"logout")==0) { sprintf(send_data, "logout
"); } else { sprintf(send_data, "%s
",argv[1]); } rt_tcpclient_send(handle, send_data, strlen(send_data)); if(strcmp(argv[1],"logout")==0)rt_tc_test_deinit(handle); } MSH_CMD_EXPORT(command, Command function);```![方法3代码.zip](/uploads/201810/24/155545bdpttxttz7k54y7z.zip)感觉简洁多了,只不过输入命令的时候麻烦一些,每次前面都要带上command。**运行情况看下面截图,可以完美支持“其他命令”,同时提醒一下,每次测试完记得logout,不然下次就没法登录同一个名字了。我就是忘记退出账号Wendell了,所以后面只能登陆账号WendellWang了。**![方法3截图1.jpg](/uploads/201810/24/160644d4azsyrd4nsc4ff6.jpg) ![方法3截图2.jpg](/uploads/201810/24/160828j5reoreknnrqio4z.jpg) ![方法3截图3.jpg](/uploads/201810/24/160645a50sezzh09utsare.jpg) 到这里基本结束了,总结一下。**总结:**虽然基本完成了作业,但是还是有一些值得改进的地方。1. 调试过程中忘记了每次电脑重新开机后都需要重新设置网络共享(详见课程第一节2.5.1),正是由于忘记了这个,导致程序调试迟迟没有进展,最后在msh中使用ipconfig命令发现没有IP地址才想起来的,以后注意。2. 程序执行后如果第一个命令就是格式正确的login命令的话(比如方法2的login wendell,方法3的command wendell),也无法得到正确的回复,还是提示登录,但是实际上已经登陆了,因为后面再用同样的名字会提示已经存在,暂时不知道原因是什么;如果第一个命令输入一个不正确的,待提示登陆后再输入则可以正常登录。该问题待解决。3. 几种方法都还有完善的余地,比如增加提示信息等。(完)
查看更多
4
个回答
默认排序
按发布时间排序
XQQ
2018-10-25
这家伙很懒,什么也没写!
厉害
yqiu
2018-10-25
这家伙很懒,什么也没写!
思路跟示例有些不同, 但是这样也挺好,能够去更深入地挖掘。
san兄弟
2018-10-25
这家伙很懒,什么也没写!
>厉害 --- 多谢夸奖
san兄弟
2018-10-25
这家伙很懒,什么也没写!
[i=s] 本帖最后由 san兄弟 于 2018-10-25 14:25 编辑 [/i] >思路跟示例有些不同, 但是这样也挺好,能够去更深入地挖掘。 --- 课程示例是阻塞式接收,感觉非阻塞的更实用些,如果课程需要的话我就再提交阻塞式的。
撰写答案
登录
注册新账号
关注者
0
被浏览
1.8k
关于作者
san兄弟
这家伙很懒,什么也没写!
提问
8
回答
36
被采纳
0
关注TA
发私信
相关问题
1
【LWIP学习营】第一关开发环境搭建
2
LWIP学习营第一周入门移植问题汇总贴
3
【LWIP学习营】f407+lan8720A小结
4
【LwIP学习营】【第一周】仅零散记录,无主题
5
【LWIP学习营】正点原子探索者F407+LAN8720第一周小结
6
【LwIP学习营】【第一周】网络通信基础及实现TCP 聊天客户端
7
【LwIP学习营】【第一周】LWIP移植
8
【LwIP学习营】【第一周】LWIP移植
9
【LwIP学习营】【第一周】开发板适配
10
【LwIP学习营】【第一周】环境搭建和配置验证
推荐文章
1
RT-Thread应用项目汇总
2
玩转RT-Thread系列教程
3
国产MCU移植系列教程汇总,欢迎查看!
4
机器人操作系统 (ROS2) 和 RT-Thread 通信
5
五分钟玩转RT-Thread新社区
6
【技术三千问】之《玩转ART-Pi》,看这篇就够了!干货汇总
7
关于STM32H7开发板上使用SDIO接口驱动SD卡挂载文件系统的问题总结
8
STM32的“GPU”——DMA2D实例详解
9
RT-Thread隐藏的宝藏之completion
10
【ART-PI】RT-Thread 开启RTC 与 Alarm组件
最新文章
1
使用RC522软件包驱动FM1722
2
常量数据类型和表达式陷阱分享
3
进行i2c驱动移植的经验总结
4
在VSCode中使用clang-format
5
我该如何使用这个微雪的WIFI400 WIFI-LPB-100在rtt里或者我该怎样为它开发驱动
热门标签
RT-Thread Studio
串口
Env
LWIP
SPI
AT
Bootloader
Hardfault
CAN总线
FinSH
ART-Pi
USB
DMA
文件系统
RT-Thread
SCons
RT-Thread Nano
线程
MQTT
STM32
RTC
FAL
rt-smart
ESP8266
I2C_IIC
UART
WIZnet_W5500
ota在线升级
freemodbus
PWM
flash
cubemx
packages_软件包
BSP
潘多拉开发板_Pandora
定时器
ADC
GD32
flashDB
socket
中断
编译报错
Debug
rt_mq_消息队列_msg_queue
SFUD
msh
keil_MDK
ulog
C++_cpp
MicroPython
本月问答贡献
出出啊
1517
个答案
342
次被采纳
小小李sunny
1444
个答案
289
次被采纳
张世争
809
个答案
175
次被采纳
crystal266
547
个答案
161
次被采纳
whj467467222
1222
个答案
148
次被采纳
本月文章贡献
catcatbing
3
篇文章
5
次点赞
qq1078249029
2
篇文章
2
次点赞
xnosky
2
篇文章
1
次点赞
Woshizhapuren
1
篇文章
5
次点赞
YZRD
1
篇文章
2
次点赞
回到
顶部
发布
问题
分享
好友
手机
浏览
扫码手机浏览
投诉
建议
回到
底部