【问题标题】:C - send multiple messages over a single socket - Data not transferred until I close the socketC - 通过单个套接字发送多条消息 - 在我关闭套接字之前不会传输数据
【发布时间】:2023-10-02 02:47:02
【问题描述】:

我正在尝试从我的笔记本电脑与 SoC 板进行 TCP 通信,在该板上我发送一条消息以启动一个进程,它会向我发送一系列状态消息,直到它完成该进程。这意味着我会从 SoC 通过套接字多次调用 send()。问题是我的笔记本电脑没有收到任何状态消息,除非套接字连接被 SoC 关闭。一旦套接字关闭,我就会收到 SoC 发送的所有数据。有没有办法使这种通信实时进行,以便我在发送时立即获得状态消息?

发送数据的SoC上的代码:该函数被多次调用:

INT16 upload(INT16* socket, INT8 HOB, INT8 LOB, INT8 msg_type, INT8* data) {
    INT8* Tx_Data= NULL;
    INT8 size = 0;
    INT16 num= 0;
    int temp = 0;
    size = 256*HOB + LOB + NAME_SIZE + 3;
    Tx_Data = (INT8*) malloc(size*sizeof(INT8));
    for (num=0;num<NAME_SIZE ;num++) {
            Tx_Data[num] = NAME[num];   
    }   
    Tx_Data[num++] = HOB;
    Tx_Data[num++] = LOB;
    Tx_Data[num++] = msg_type; // 11 byte header ends here
    for(temp = 0;num<size;num++,temp++) {
        Tx_Data[num] = data[temp]; // data
    }
    send(*socket, (INT8*)Tx_Data,num,0);
    return PASS;
}

我的笔记本电脑上的代码:

for(;;) {
            printf("Start of for loop socket id: %d \n",socket_id);
            RX_Data = (unsigned char*)malloc(2048);
            unsigned char Command;
            int No_of_Data_Bytes=0;
            printf("Before read.... \n");
            nbytes = read(socket_id,RX_Data,11);    // get 11 bytes from EZ80
            printf("Received %d bytes from socket\n",nbytes);
            No_of_Data_Bytes = RX_Data[8]*256 + RX_Data[9];
            Command = RX_Data[10];
            printf("\n command:%c %d \n",Command,No_of_Data_Bytes);
            if(Command=='I' || Command=='E'|| Command=='V') {
                    //read and analyse data
            }
            else {
                    break;
            }
            Command = '\0';
            free(RX_Data);
        }

【问题讨论】:

  • 不保证每次读取都能获得 11 个字节。你必须循环阅读,直到你确定你有完整的请求。这可能是您的问题,也可能不是,但它没有帮助。
  • @Duck 我确定我发送了 11 个字节。
  • 发送什么都没关系。 TCP 会根据需要将其分解以进行传输,并且您发送的内容可能是也可能不是您在读取时获得的内容。您必须循环读取,直到确定获得 11 个字节。
  • 查看send 上的 TCP_NODELAY。这将迫使 TCP 在每次写入时发送 11 个字节,我认为这就是你所得到的。否则 tcp 可能会在缓冲区中收集您的 send 数据,直到它认为发送它是最佳的。这可能就是为什么您在收盘时看到爆炸的原因。并更改读取。
  • 是的,我将更改读取。我的 SoC 不支持 TCP_NODELAY 标志。send 仅支持一个标志,即 PSH 标志。两者都一样吗?如果没有,还有其他替代方法吗?

标签: c sockets tcp send


【解决方案1】:

在 Linux 中,您可以只使用 fdopen,写入和刷新流。但是不确定它是否适用于您的情况。示例:

FILE *f = fdopen(socketdescriptor, "w+");
. . .
n = write(socketdescriptor, "this is a message", 17);
fflush(f);
...

【讨论】:

  • 这基本上是我在笔记本电脑上所做的,但我不能在 SoC 上做同样的事情,因为它有自己的内核,称为实时 Zilog 内核,我猜它是一个非 *nix 内核。
【解决方案2】:

这种行为的原因是默认情况下在套接字上启用了 Nagel 算法。您可以通过setsockopt() 调用禁用它。

您可以使用fflush() 或只是在写入套接字的字符串末尾添加“\n”字符,但这只会刷新用户空间中的 stdio 缓冲区,这不是您的目标。

【讨论】:

  • 如果这是 OP 的问题 - 我不确定是 - 最简单的解决方案是正确执行 read。换行符和fflush 应该对 TCP 没有影响。它将刷新 stdio 缓冲区,但对 tcp 毫无意义。
最近更新 更多