3

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

  1. 将 UDP 数据包从lwipDevice发送到LinuxDevice以启动我准备分享我的信息。

  2. 现在LinuxDevice成功识别了这个消息,并发送一个 TCP 数据包(包含命令)给lwipDevice,告诉 lwipDevice 发送它的信息。

  3. 但是在lwipDevice端没有收到这个消息。所以它不会向LinuxDevice发送任何响应。步骤 1-3 一次又一次地重复。

现在这是 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

有谁知道它有什么问题?

4

3 回答 3

1

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

于 2014-07-27T00:21:39.657 回答
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_REDMEM_SIZE也会(6 * 1024)。_ 现在,当我将内存大小更改为(16 * 1024)一切正常时。

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

于 2014-09-19T09:29:17.357 回答
0

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

但是为什么 sock->rcvevent 总是为零,即使 LinuxDevice 已经向它发送了数据包?

您是否尝试过发送数据telnetnetcat确保错误在您的服务器而不是在您的客户端?也许您的客户没有发送到正确的目的地或其他地方。

于 2014-08-07T12:23:20.490 回答