TCP服务器似乎无法在LWIP + FreeRTOS中运行

时间:2014-07-26 06:41:51

标签: c sockets tcp freertos lwip

我使用 lwip + freeRTOS 在我的一个嵌入式设备中开发了一个tcp服务器。 现在,这是我使用我的设备与其他设备(其他设备具有Linux系统并将其命名为 LinuxDevice )进行通信的流程(让我们将其命名为 lwipDevice

  1. lwipDevice 发送UDP数据包到 LinuxDevice ,以表示我已准备好分享我的信息。

  2. 现在 LinuxDevice 成功识别此消息并将一个TCP数据包(包含命令)发送到 lwipDevice 以告知发送其信息。

    < / LI>
  3. 但是在 lwipDevice 一侧,未收到此消息。所以它不会向 LinuxDevice 发送任何响应。并且步骤1-3一次又一次地重复。

  4. 现在这是TCP服务器的lwipDevice代码:

    long server_sock=-1;
    #define FAIL 1
    #define PASS 0
    int CreateTcpServerSocket(long *pSock, int port)
    {
        struct sockaddr_in   sin;
        int addrlen = sizeof(sin);
        int   e;
        struct linger linger;
        linger.l_linger=0;
        int i = 1;
    
        *pSock = socket(AF_INET, SOCK_STREAM, 0);
    
        if (*pSock == -1)
        {
            printf("*** createTcpSercerSocket:open sock error,port %d\n",port);
            return FAIL;
        }
    
        memset((char *)&sin, 0, sizeof(sin));
        sin.sin_family = AF_INET;
        sin.sin_len = sizeof(sin);
        sin.sin_addr.s_addr = htonl(INADDR_ANY);   /* wildcard IP address */
        sin.sin_port = htons(port);
    
    
        e = bind(*pSock, (struct sockaddr*)&sin, addrlen);
        if (e != 0)
        {
            printf("error %d binding tcp listen on port\n");
            closesocket(*pSock);
            *pSock = -1;
            return FAIL;
        }
    
        lwip_ioctl(*pSock, FIONBIO, &i); //Set Non blocking mode
    
        e = listen(*pSock, 2);
    
        if (e != 0)
        {
            pprintf("error :listen on TCP server\n");
            closesocket(*pSock);
            *pSock = -1;
            return FAIL;
        }
    
        return PASS;
    }
    void vTCPTask(void *parm)
    {
        struct sockaddr client; /* for BSDish accept() call */
        int clientsize;
        long sock;
    
        if(CreateTcpServerSocket(&server_sock, 8000) == FAIL) //Here server created successfully
        {
            printf("Fail to create server!!!!!\n");
            server_sock=-1;
        }
    
        while(1)
        {
            // some code for other stuff
    
            sock= accept(server_sock, &client, &clientsize); //This line always fails and reurn -1
    
            if(sock != -1)
            {
                printf("accepted socket:\n\n");
                //...now receive data from client....
                // send some data to client
            }
    
            // some code for other stuff
    
            //sleep for 15 seconds
        }
    
    }
    int main()
    {
    
        //...initilization of lwip stack
        //....some more code
        //...................
    
        xTaskCreate(vTCPTask, (signed char const *) "tcptask",
        356, NULL, 3, (xTaskHandle *)&xNotifierServiceTaskHandle);
    
    
        /* Start the scheduler */
        vTaskStartScheduler();
    
        return 1
    }
    

    我检查了lwip_accept函数,它将从这个条件返回:

      if (netconn_is_nonblocking(sock->conn) && (sock->rcvevent <= 0))
      {
        LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_accept(%d): returning EWOULDBLOCK\n", s));
        sock_set_errno(sock, EWOULDBLOCK);
        return -1;
      }
    

    修改

    我知道netconn_is_nonblocking(sock->conn)条件总是正确的,因为在非阻塞模式下设置套接字。但是为什么sock->rcvevent总是为零,即使LinuxDevice已经发送了数据包呢?

    修改

    出于测试目的,在任务中注释了所有其他东西代码(参见//some code for other stuff),然后套接字被成功接受,我尝试接收数据包但现在问题是它现在卡在lwip_recvfrom函数中(注意: LinuxDevice 继续发送数据包)。所以进一步调试更多,发现它停留在函数sys_arch_mbox_fetch(函数调用流程:: lwip_recvfrom\netconn_recv\netconn_recv_data\sys_arch_mbox_fetch)。

    有没有人知道它有什么问题?

3 个答案:

答案 0 :(得分:1)

您已将套接字配置为非阻塞,因此accept()调用永远不会阻塞。如果没有传入连接挂起,它将返回EWOULDBLOCK错误代码,这就是您所看到的。

答案 1 :(得分:1)

最后,我想出了问题的原因。

lwipopt.h文件中有像

这样的宏
/* Non-static memory, used with DMA pool */
#ifdef __CODE_RED
#define MEM_SIZE                        (6 * 1024) 
#else
#define MEM_SIZE                        (24 * 1024)
#endif

我定义了_CODE_RED。因此MEM_SIZE(6 * 1024)。现在,当我将内存大小更改为(16 * 1024)时,一切正常。

现在一直接受连接,之后我能够成功发送/ recv tcp数据包。

答案 2 :(得分:0)

您在哪里设置rcvevent?你的代码没有透露它。我认为这是recv(或read)的结果。从没有可用数据的非阻塞中读取(尚未接收到数据)将返回EAGAIN,其在rcvevent <= 0条件下评估为真。您必须手动检查这些特定的错误代码。

  

但是为什么sock-&gt; rcvevent总是为零,即使LinuxDevice已经发送了数据包呢?

您是否尝试使用telnetnetcat发送数据,以确保错误在您的服务器中而不在您的客户端?也许你的客户没有发送到正确的目的地或其他东西。