RTT6-RTThread_采用netcon接口进行异步读写目的:建立一客户端,连接192.168.1.100的服务器;连接成功后,接收服务器发来的消息后,发送至串口。
1. client.c文件说明
在下一版本的RTT编程指南中会有。此程序来自于RTT的官网论坛。
在LwIP中netbuf、netconn是属于非常简洁的接口,代码清晰而简洁,十分适合于嵌入式应用。
但netconn有个缺点,即它的API接口都是阻塞模式的,例如一个线程调用netconn_recv读取一个连接上的数据,在数据未达到前,线程将一直被阻塞。此时如果想发送一些数据到网络连接上,将比较困难。而且netcon...
目的:建立一客户端,连接192.168.1.100的服务器;连接成功后,接收服务器发来的消息后,发送至串口。
1. client.c文件说明
在下一版本的RTT编程指南中会有。此程序来自于RTT的官网论坛。
在LwIP中netbuf、netconn是属于非常简洁的接口,代码清晰而简洁,十分适合于嵌入式应用。
但netconn有个缺点,即它的API接口都是阻塞模式的,例如一个线程调用netconn_recv读取一个连接上的数据,在数据未达到前,线程将一直被阻塞。此时如果想发送一些数据到网络连接上,将比较困难。而且netconn不是线程安全的(即不能在多个线程中使用netconn API),这也基本上杜绝了多个线程中使用netconn的可能。
客户因为使用RT-Thread & LwIP,而提出如上的问题。因为这个属于一个普遍的问题,所以把相应的例子程序附在后面,它通过LwIP netconn中提供的callback机制,当LwIP收到网络报文时,在回调函数中发送event给nw_thread线程,让nw_thread继续进行接收的处理。同时nw_thread也在监视发送事件和连接关闭事件。
#include
#include
#include
static struct netconn* conn = RT_NULL;
#define NW_RX 0x01
#define NW_TX 0x02
#define NW_CLOSED 0x04
#define NW_MASK (NW_RX | NW_TX | NW_CLOSED)
/* tx session structure */
struct tx_session
{
rt_uint8_t *data; /* data to be transmitted */
rt_uint32_t length; /* data length */
rt_sem_t ack; /* acknowledge semaphore */
};
struct tx_session tx_data;
struct rt_event nw_event;
struct rt_semaphore nw_sem;
void rx_callback(struct netconn *conn, enum netconn_evt evt, rt_uint16_t len)
{
if (evt == NETCONN_EVT_RCVPLUS)
{
rt_event_send(&nw_event, NW_RX);
}
}
void process_rx_data(struct netbuf *buffer)
{
rt_uint8_t *data;
rt_uint16_t length;
/* get data */
netbuf_data(buffer, (void**)&data, &length);
rt_kprintf("rx: %s\n", data);
}
void nw_thread(void* parameter)
{
struct netbuf *buf;
rt_err_t result;
rt_uint32_t event;
/* set network rx call back */
conn->callback = rx_callback;
while (1)
{
/* receive network event */
result = rt_event_recv(&nw_event,
NW_MASK, RT_EVENT_FLAG_OR | RT_EVENT_FLAG_CLEAR,
RT_WAITING_FOREVER, &event);
if (result == RT_EOK)
{
/* get event successfully */
if (event & NW_RX)
{
/* do a rx procedure */
buf = netconn_recv(conn);
if (buf != RT_NULL)
{
process_rx_data(buf);
}
}
if (event & NW_TX)
{
/* do a tx procedure */
netconn_write(conn, tx_data.data, tx_data.length, NETCONN_COPY);
/* tx done, notify upper application */
rt_sem_release(tx_data.ack);
}
if (event & NW_CLOSED)
{
/* connection is closed */
netconn_close(conn);
}
}
}
}
void send_hit(void)
{
static char hit_data[80];
static rt_uint32_t hit = 0;
if (conn != RT_NULL)
{
tx_data.data = (rt_uint8_t*)&hit_data[0];
tx_data.length = rt_sprintf(hit_data, "hit %d", hit ++);
rt_kprintf("send hit: %s\n", tx_data.data);
rt_event_send(&nw_event, NW_TX);
/* wait ack */
rt_sem_take(&nw_sem, RT_WAITING_FOREVER);
}
}
FINSH_FUNCTION_EXPORT(send_hit, send hit on network)
void client(void)
{
int err;
struct ip_addr ip;
rt_thread_t thread;
/* create a TCP connection */
conn = netconn_new(NETCONN_TCP);
/* set ip address */
IP4_ADDR(&ip, 192, 168, 1, 100);
/* connect to server */
err = netconn_connect(conn, &ip, 20);
rt_kprintf("connect error code: %d\n", err);
/* connect OK */
if (err == 0)
{
rt_kprintf("Connect OK, startup rx thread\n");
/* init event */
rt_event_init(&nw_event, "nw_event", RT_IPC_FLAG_FIFO);
rt_sem_init(&nw_sem, "nw_sem", 0, RT_IPC_FLAG_FIFO);
tx_data.ack = &nw_sem;
/* create a new thread */
thread = rt_thread_create("rx", nw_thread, RT_NULL,
1024, 20, 20);
if (thread != RT_NULL)
rt_thread_startup(thread);
}
}
FINSH_FUNCTION_EXPORT(client, tcp client demo)
将client.c添加到中。
2.用shell运行
本机IP 地址:
3.打开TCPUDP测试工具,创建服务器
192.168.1.100,在端口20监听。以下已经被开发板连接成功
4.打开串口调试助手
输入 client(),成功连接后,connect error code:0 表示错误代码为0,没有错误。 在TCPUDP测试工具中发送”abcdefg1234567”,
5.网上源码修订内容
来自于:
源码中,
thread = rt_thread_create("rx", nw_thread, RT_NULL,
1024, 150, 20);
优先级设置过高,priority超出了RT_THREAD_PRIORITY_MAX,会出现错误。
串口打印错误为:(priority < RT_THREAD_PRIORITY_MAX) assert failed at _rt_thread_init:62
本文档为【RTT6-RTThread_采用netcon接口进行异步读写】,请使用软件OFFICE或WPS软件打开。作品中的文字与图均可以修改和编辑,
图片更改请在作品中右键图片并更换,文字修改请直接点击文字进行修改,也可以新增和删除文档中的内容。
[版权声明] 本站所有资料为用户分享产生,若发现您的权利被侵害,请联系客服邮件isharekefu@iask.cn,我们尽快处理。
本作品所展示的图片、画像、字体、音乐的版权可能需版权方额外授权,请谨慎使用。
网站提供的党政主题相关内容(国旗、国徽、党徽..)目的在于配合国家政策宣传,仅限个人学习分享使用,禁止用于任何广告和商用目的。