为什么TCP-BSD服务器即使接收数据也卡在read()中?

为什么TCP-BSD服务器即使接收数据也卡在read()中?,tcp,server,iot,stm32,lwip,Tcp,Server,Iot,Stm32,Lwip,我已经使用BSD套接字和NUCLEO-H743ZI2开发板创建了一个TCP服务器应用程序,在Keil MDKARM中使用STM32CubeMX 5.6.0和LwIP 2.0.3 我注意到: 如果客户端首先连接并发送11个字节或更多字节,则服务器 正确接收数据并且read()响应显示数据 但是,如果客户端发送的第一个数据低于11 字节,read()。断开连接后,将显示所有排队的数据 也就是说,如果从客户机发送到我的服务器的第一个数据小于11字节,则在断开连接之前不会触发rcvevent的事件回

我已经使用BSD套接字和NUCLEO-H743ZI2开发板创建了一个TCP服务器应用程序,在Keil MDKARM中使用STM32CubeMX 5.6.0和LwIP 2.0.3

我注意到:

  • 如果客户端首先连接并发送11个字节或更多字节,则服务器 正确接收数据并且
    read()
    响应显示数据
  • 但是,如果客户端发送的第一个数据低于11 字节,
    read()。断开连接后,将显示所有排队的数据
也就是说,如果从客户机发送到我的服务器的第一个数据小于11字节,则在断开连接之前不会触发rcvevent的事件回调

我的目标是使服务器可以接收一个字节

我已将服务器任务/线程粘贴到下面。请在您方便的时候尽早回复,并随时请求其他相关文件/库(lwip.h、lwipopts.h…)

问候

void StartTask01(void const * argument)
{
    /* USER CODE BEGIN StartTask01 */
    MX_LWIP_Init();

    /*start a listening tcp server*/
    int iServerSocket;
    struct sockaddr_in address;

    if ((iServerSocket = socket(AF_INET, SOCK_STREAM, 0)) < 0) 
    {
        printf("Socket could not be created\n");
    }
    else
    {
        address.sin_family = AF_INET;
        address.sin_port = htons(80);
        address.sin_addr.s_addr = INADDR_ANY;

        if (bind(iServerSocket, (struct sockaddr *)&address, sizeof (address)) < 0)
        {
            printf("socket could not be bound\n");
        }
        else
        {
            listen(iServerSocket, MEMP_NUM_NETCONN);    
        }
    }
    /*server started listening*/

    struct sockaddr_in remoteHost;
    int newconn;
    char caReadBuffer[1500];
    memset(caReadBuffer, 0, 1500);

    for(;;)
    {
        /*block until accepting an incoming connection*/
        newconn = accept(iServerSocket, (struct sockaddr *)&remoteHost, (socklen_t *)(sizeof(remoteHost)));

        if (newconn != -1)/*if accepted well*/
        {   
            /*block until data arrives*/
            read(newconn, caReadBuffer, sizeof(caReadBuffer));
            printf("data read: %s\n", caReadBuffer);
            memset(caReadBuffer, 0, 1500);
        }
    }
/* USER CODE END StartTask01 */
}
void StartTask01(void const*参数)
{
/*用户代码BEGIN STARTASK01*/
MX_LWIP_Init();
/*启动侦听tcp服务器*/
int iServerSocket;
地址中的结构sockaddr_;
if((iServerSocket=socket(AF_INET,SOCK_STREAM,0))<0)
{
printf(“无法创建套接字\n”);
}
其他的
{
address.sin_family=AF_INET;
address.sin_port=htons(80);
address.sin_addr.s_addr=INADDR\u ANY;
if(bind(iServerSocket,(struct sockaddr*)&address,sizeof(address))<0)
{
printf(“无法绑定套接字\n”);
}
其他的
{
倾听(iServerSocket,MEMP_NUM_NETCONN);
}
}
/*服务器开始侦听*/
远程主机中的结构sockaddr_;
内特纽康;
字符caReadBuffer[1500];
memset(caReadBuffer,01500);
对于(;;)
{
/*阻塞,直到接受传入连接*/
newconn=accept(iServerSocket,(struct sockaddr*)和remoteHost,(socklen_t*)(sizeof(remoteHost));
如果(newconn!=-1)/*如果接受良好*/
{   
/*阻止,直到数据到达*/
读取(newconn、caReadBuffer、sizeof(caReadBuffer));
printf(“数据读取:%s\n”,caReadBuffer);
memset(caReadBuffer,01500);
}
}
/*用户代码结束StartTask01*/
}

导致此问题的问题是,在每个连接上只调用
read
一次。如果您没有从对
read
(这是完全不可预测的)的单个调用中接收到所有数据,您将永远不会在该连接上再次调用
read

在阻塞的TCP连接上调用
read
时,只有在没有可用数据时才会阻塞。否则,它将为您提供任何可用的数据,直到您要求的最大字节数。如果只有一些数据可用,它将不会等待更多数据。如果您没有收到预期的所有数据,您可以再次调用
read

第二次迭代
for
循环时,使用新连接覆盖
newconn
。您没有关闭旧的连接。您的插座泄漏。

已解决:

问题是,我的服务器正在侦听端口80。我将其更改为端口7,谢天谢地,bug已经解决,现在read()可以正常工作了


这个bug让我认为LwIP在侦听该web(80)端口而不是其他端口时遇到了问题。即使对于未实现的协议,在监听一些引人注目的端口之间也应该存在某种区别。

想想简单的问题,在循环的范围内没有什么可做的。如果我调用
read()
,如果有,它应该给出输出,当到达数据超过11字节时,它给出输出。然后,如果到达数据小于11字节,则为相同情况重新运行应用程序失败。对于我选择的MCU,在LwIP库的BSD实现中应该有一些事情要做。@SarpEnginDaltaban修复了我解释的两个错误,我几乎可以肯定你的问题会消失。如果没有,至少可以诊断,因为不会有重大的混淆问题。您的代码每次连接只调用
read
一次,这使您完全无法预测您将收到什么和不会收到什么,这取决于您调用
read
@SarpEnginDaltaban时碰巧有哪些数据可用。我正计划购买此板,此板是否与现有库存在问题,与F767ZI相比,这并没有解决问题。它只是将错误代码从碰巧在测试条件下不工作更改为碰巧在测试条件下工作。带有bug的代码可能在某些条件下很好地工作,而在其他条件下则不然。除非您继续查找并修复实际的错误,否则更改条件使其在不修复错误的情况下正常工作是一个坏主意。