Toggle navigation
首页
问答
文章
积分商城
专家
专区
更多专区...
文档中心
返回主站
搜索
提问
会员
中心
登录
注册
网络学习营
【7天入门RTOS网络编程】Nautilus day3-5 作业
发布于 2018-10-18 15:05:54 浏览:1451
订阅该版
[tocm] * 本帖最后由 yukelab 于 2018-10-19 17:21 编辑 * 完成思路 1. 简单对服务器测试了哈, 黄色部分未命令,绿色为返回数据 ![图1.png](/uploads/201810/19/090502p8msbexa8qqtem1a.png) 2. 对数据进行分析发现,look和who命令发出后,客户端需要接收的不止一帧数据,它其实传回的的1(The following are in this room)+ N(login 用户个数)= 1+N帧数据,如果发送数据后紧跟接收。首先,接收的帧数不好判断,如果接收x(
N+1)帧数据,超时未接收,可能会导致接收错误;其次,接收与发送相互纠缠,信息可能出现相互重叠,其本质也是由于帧数不确定引起的。 我的解决办法是对接收单独开一个线程,分离接收和发送。这样就比较简单了,建立相关命令函数,导出即可;在与服务器建立连接后,打开接收数据任务即可; 具体步骤 1. 添加自己编写的文件所需编译内容 由于文件与其他文件例程放在一起,所以照猫画虎,修改了对应目录下的SConscript文件,添加如下部分 ```if GetDepend('RT_USING_SAMPLE_TCP_CLIENT'): src += ['tcpclient_hw/tcpclient_hw.c'] CPPPATH += [cwd + '/tcpclient_hw'] ``` 2 在qemu-vexpress-a9\packages\samples-latest
etwork添加tcpclient_hw(homework)文件夹,并添加了tcpclient_hw.c文件,文件内容如下 添加自己编写的文件 ```#include
#include
/* 使用BSD socket,需要包含socket.h头文件 */ #include
#include
#include
#define BUFSZ 256 #define SEND_DATASZ 256 #define SAY_BUFSZ 240 #define THREAD_PRIORITY 11 #define THREAD_STACK_SIZE 1024 #define THREAD_TIMESLICE 5 static rt_thread_t tid1 = RT_NULL; static int sock = 0; static char send_data[80] = {0}; /* 发送用到的数据 */ /* create receive thread */ static void thread_rece_entry(void* parameter) { char *recv_data; int bytes_received; /* int no = (int) parameter; #<{(| 获得线程的入口参数 |)}># */ /* 分配用于存放接收数据的缓冲 */ recv_data = rt_malloc(BUFSZ); if (recv_data == RT_NULL) { rt_kprintf("No memory
"); } while(1) { /* 从sock连接中接收最大BUFSZ - 1字节数据 */ bytes_received = recv(sock, recv_data, BUFSZ - 1, 0); if (bytes_received < 0) { /* 接收失败,关闭这个连接 */ closesocket(sock); rt_kprintf("
received error,close the socket.
"); /* 释放接收缓冲 */ rt_free(recv_data); rt_thread_delete(tid1); } else if (bytes_received == 0) { /* 默认 recv 为阻塞模式,此时收到0认为连接出错,关闭这个连接 */ closesocket(sock); rt_kprintf("
received error,close the socket.
"); /* 释放接收缓冲 */ rt_free(recv_data); rt_thread_delete(tid1); } /* 有接收到数据,把末端清零 */ recv_data[bytes_received] = '\0'; /* 在控制终端显示收到的数据 */ rt_kprintf("
%s", recv_data); } } /* 用户应用入口 */ static int rt_appchat_init(void) { /* 创建线程 */ tid1 = rt_thread_create("receive thread", thread_rece_entry, (void*)1, /* 线程入口是thread_entry, 入口参数是1 */ THREAD_STACK_SIZE, THREAD_PRIORITY, THREAD_TIMESLICE); if (tid1 != RT_NULL) { rt_kprintf("Create receive thread for chat receive.
"); rt_thread_startup(tid1); } else { return -1; } return 0; } static void send_chat_data(char *p_send, int len) { int ret; /* 是否创建Socket */ if (sock <= 0) { rt_kprintf("Please connect serve first.
"); rt_kprintf("Like: tcpclient_connect 183.193.243.90 5000
"); return; } /* 发送数据到sock连接 */ ret = send(sock, p_send, len, 0); if (ret < 0) { /* 接收失败,关闭这个连接 */ closesocket(sock); rt_kprintf("
send error,close the socket.
"); /* rt_free(recv_data); */ return; } else if (ret == 0) { /* 打印send函数返回值为0的警告信息 */ rt_kprintf("
Send warning,send function return 0.
"); } } static void tcpclient_connect(int argc, char **argv) { /* char *recv_data; */ /* int bytes_received; */ struct hostent *host; struct sockaddr_in server_addr; const char *url; int port; if (1 == argc) { url = "183.193.243.90"; port = 5000; } else if (argc < 3) { rt_kprintf("Usage: tcpclient URL PORT
"); rt_kprintf("Like: tcpclient_connect 183.193.243.90 5000
"); return ; } else { url = argv[1]; port = strtoul(argv[2], 0, 10); } /* 通过函数入口参数url获得host地址(如果是域名,会做域名解析) */ host = gethostbyname(url); /* 创建一个socket,类型是SOCKET_STREAM,TCP类型 */ if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1) { /* 创建socket失败 */ rt_kprintf("Socket error
"); /* 释放接收缓冲 */ /* rt_free(recv_data); */ return; } /* 初始化预连接的服务端地址 */ server_addr.sin_family = AF_INET; server_addr.sin_port = htons(port); server_addr.sin_addr = *((struct in_addr *)host->h_addr); rt_memset(&(server_addr.sin_zero), 0, sizeof(server_addr.sin_zero)); /* 连接到服务端 */ if (connect(sock, (struct sockaddr *)&server_addr, sizeof(struct sockaddr)) == -1) { /* 连接失败 */ rt_kprintf("Connect fail!
"); closesocket(sock); return; } /* 启动chat接收线程 */ rt_appchat_init(); } static void tcpclient_disconnect(void) { if (sock > 0) { rt_kprintf("disconnect server!
"); rt_thread_delete(tid1); closesocket(sock); } } void login(int argc, char **argv) { const char *ID; if (argc < 2) { rt_kprintf("Usage: login ID
"); rt_kprintf("Like: login Nautilus
"); return ; } ID = argv[1]; sprintf(send_data, "login %s
", ID); /* 发送数据到sock连接 */ send_chat_data(send_data, strlen(send_data)); } /* logout server 断开连接了? */ void logout(void) { sprintf(send_data, "logout
"); /* 发送数据到sock连接 */ send_chat_data(send_data, strlen(send_data)); tcpclient_disconnect(); } void look(void) { sprintf(send_data, "look
"); /* 发送数据到sock连接 */ send_chat_data(send_data, strlen(send_data)); } void who(void) { sprintf(send_data, "who
"); /* 发送数据到sock连接 */ send_chat_data(send_data, strlen(send_data)); } /* 变参,最多只能带9个参数 */ /* 调用say 参数需要用 " " , 避免argv参数过多 */ /* for example: say "hello i can see a dead beef in there" */ void say(int argc, char **argv) { if (argc < 2) { rt_kprintf("Usage: say say_content
"); rt_kprintf("Like: say hello
"); } else { sprintf(send_data, "say %s
", argv[1]); /* rt_kprintf("%s
", send_data); */ /* 发送数据到sock连接 */ send_chat_data(send_data, strlen(send_data)); } } #ifdef FINSH_USING_MSH #include
MSH_CMD_EXPORT(tcpclient_connect, connect server); MSH_CMD_EXPORT(tcpclient_disconnect, disconnect server); MSH_CMD_EXPORT(login, a tcp client login); MSH_CMD_EXPORT(logout, a tcp client logout); MSH_CMD_EXPORT(look, a tcp client look); MSH_CMD_EXPORT(who, a tcp client who); MSH_CMD_EXPORT(say, a tcp client say); #endif``` 3. scons 编译 4. 运行qemu ![图2.png](/uploads/201810/19/090612opq60pnqqptzpnyb.png) 下载附件 [day3.pdf](https://oss-club.rt-thread.org/uploads/201810/18/150547j300by2sk8g3zkz8.attach) ![day3.png](https://oss-club.rt-thread.org/uploads/201810/18/150724xi3pmim3cm1u3gwy.png)
查看更多
1
个回答
默认排序
按发布时间排序
yukelab
2018-10-19
这家伙很懒,什么也没写!
2018/10/19 做mqtt 示例时,也发现了这个问题 [attach]6540[/attach]
撰写答案
登录
注册新账号
关注者
0
被浏览
1.5k
关于作者
yukelab
这家伙很懒,什么也没写!
提问
17
回答
47
被采纳
1
关注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
组件 lwip v2.0.3 版本使用 netdev网卡的 ping 功能
2
简单两步配置RTT源码阅读环境 vsc+clangd
3
恩智浦[FRDM-MCXN947]初探 之 ADC与DAC
4
LVGL使用字库IC芯片显示中文
5
基于STM32H750和Rt-Thread的CANFD通信实现的记录(一)
热门标签
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在线升级
PWM
cubemx
freemodbus
flash
packages_软件包
BSP
潘多拉开发板_Pandora
定时器
ADC
GD32
flashDB
socket
中断
编译报错
Debug
SFUD
msh
rt_mq_消息队列_msg_queue
keil_MDK
ulog
MicroPython
C++_cpp
本月问答贡献
出出啊
1517
个答案
342
次被采纳
小小李sunny
1443
个答案
289
次被采纳
张世争
807
个答案
174
次被采纳
crystal266
547
个答案
161
次被采纳
whj467467222
1222
个答案
148
次被采纳
本月文章贡献
出出啊
1
篇文章
4
次点赞
小小李sunny
1
篇文章
1
次点赞
张世争
1
篇文章
1
次点赞
crystal266
2
篇文章
2
次点赞
whj467467222
2
篇文章
1
次点赞
回到
顶部
发布
问题
分享
好友
手机
浏览
扫码手机浏览
投诉
建议
回到
底部