LWIP + RTOS - 如何避免netconn永久阻塞线程?

7
当调用LwIPnetconn_accept()netconn_recv()函数时,如果我们正在使用RTOS,则它将阻塞线程并等待连接直到超时或永远,这取决于LWIP_SO_RCVTIME0的设置。超时持续时间等于SYS_ARCH_TIMEOUT
在LwIP堆栈的核心包含部分中,SYS_ARCH_TIMEOUT被定义为0xffffffff,因此我认为不应该改变它。
实际上,我希望它检查是否建立了连接,如果没有,则继续执行线程。但是,如果我调用netconn_accept(),它将只是阻塞线程并永远等待(或非常长时间)......我不想仅更改SYS_ARCH_TIMEOUT的定义值,因为我需要在不同情况下具有不同的超时时间......
有什么好方法可以解决这个问题吗?谢谢。

我不了解lwip的具体细节,但它是否具有非阻塞套接字或类似于“select”的功能? - Some programmer dude
lwIP中的BSD套接字实现确实使用了额外的空间,这可能超出OP的承受范围。64kb的RAM并不是一个很大的空间来存储所有东西。 - Viktor Latypov
1
@ViktorLatypov 你怎么知道我只有64kb的RAM??我认识你吗...? - eepty
1
我怀疑,我自己已经受够了FreeRTOS :))) - Viktor Latypov
4个回答

9

轮询TCP连接(或接受)通常是一种不良实践。考虑生成一个专用于阻塞netconn_accept()调用的新线程。

我了解使用RTOS的局限性,但生成仅具有最小堆栈空间的单个辅助线程不应该是一个主要问题。

我认为实现经典的生产者-消费者问题的解决方案并不难。

如果你谈论的是FreeRTOS,它拥有所有必需的工具——信号量和线程。


4
不要使用阻塞式API。lwIP堆栈提供了一种本地的、非阻塞的、事件驱动的API,这种API比阻塞式API更高效,并且不需要阻塞式RTOS。YouTube视频展示了(在http://youtu.be/MBk5wJ_8jEc),这种API如何在基于QP状态机框架的实时系统中使用。

3

创建一个新的线程,试图建立该连接。只要尚未建立连接,就将线程置于睡眠状态一段时间,这样RTOS就可以进行上下文切换!(切换到另一个任务)


3
您可以使用netconn_set_recvtimeout函数将侦听套接字的超时时间设置为较小的值,例如1毫秒。
例如(为简单起见,省略了新建、绑定和侦听的错误处理)。
struct netconn *conn = netconn_new(NETCONN_TCP);
if (conn)
{
    if (netconn_bind(conn, IP_ADDR_ANY, 1025/*PORT_NUMBER*/) != ERR_OK)
    {
        return;
    }
    if (netconn_listen(conn) != ERR_OK)
    {
        return;
    }
    netconn_set_recvtimeout(conn, 1);
}

然后调用accept的延迟最多为1毫秒:

struct netconn *newConn;
err_t result = netconn_accept(conn, &newConn);
if (result == ERR_OK)
{
    // Handle the connected netconn here
}
else if (result == ERR_TIMEOUT)
{
    // No pending connections
}
else
{
    // A problem with the listen socket accepting the connection
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接