加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

c – 如何在TCP / IP中添加消息长度的前缀

发布时间:2020-12-16 09:24:34 所属栏目:百科 来源:网络整理
导读:我正在通过TCP / IP发送消息,我需要在char数组中为消息长度添加前缀,然后发送它.我该怎么做? 还请你提供一个如何在另一端提取它的例子.如果可能的话,请解释一下. 我正在使用C和Winsock. 编辑: string writeBuffer = "Hello";unsigned __int32 length = hto
我正在通过TCP / IP发送消息,我需要在char数组中为消息长度添加前缀,然后发送它.我该怎么做?

还请你提供一个如何在另一端提取它的例子.如果可能的话,请解释一下.

我正在使用C和Winsock.

编辑:

string writeBuffer = "Hello";

unsigned __int32 length = htonl(writeBuffer.length());

它没有返回正确的长度而是非常大的数字.

对于接收部分,如果我使用ntohl(),那么我也得到一个大数而不是正确的长度?为什么会这样?我收到这样的

bool Server::Receive(unsigned int socketIndex)
{
    // Read data from the socket
    if (receivingLength)
    {
        bytesReceived = recv(socketArray[socketIndex - WSA_WAIT_EVENT_0],((char*)&messageLength) + bytesReceived,MESSAGE_LENGTH_SIZE - bytesReceived,0);

        if (bytesReceived == SOCKET_ERROR)
        {
            return false;
        }

        if (bytesReceived == MESSAGE_LENGTH_SIZE)
        {
            // If uncomment the following line,// I won't get the correct length,but a large number
            //messageLength = ntohl(messageLength);
            receivingLength = false;
            bytesReceived = 0;
            bytesLeft = messageLength;
        }
    }
    else
    {
        if (bytesLeft > BUFFER_SIZE)
        {
            return false;
        }

        bytesReceived = recv(socketArray[socketIndex - WSA_WAIT_EVENT_0],&receiveBuffer[bytesReceived],bytesLeft,0);

        if (bytesReceived == SOCKET_ERROR)
        {
            return false;
        }

        if (bytesReceived == messageLength)
        {
            // we have received full message
            messageReceived = true;

            receiveBuffer[bytesReceived] = '';

            // wait for next message
            receivingLength = true;
        }

        bytesLeft -= bytesReceived;
    }

    return true;
}

解决方法

在TCP流上发送长度字段时,您需要确定两件事:

>长度应该是多长(1字节,2字节,4字节,可变长度)
>我应该使用什么字节序

我建议使用4个字节的长度和网络字节顺序(即big-endian).对于网络字节顺序,宏htonl和ntohl将在主机(本机)字节顺序(在您的情况下为little-endian)和网络字节顺序之间进行转换.

要发送数据,片段应如下所示:

size_t length = strlen(data);
uint32_t nlength = htonl(length);
send(sock,&nlength,4,0);
send(sock,data,length,0);

在接收方,首先提取长度,然后提取数据:

uint32_t length,nlength;
recv(sock,0);
length = ntohl(nlength);
data = malloc(length+1);
recv(sock,0);
data[length] = 0;

缺少此代码的是错误处理:每个发送和接收调用都可能失败; recvs可能收到的数据少于预期.但这应该给你一个想法.

编辑:要处理recv返回的数据太少的情况,请在循环中运行它,保持到目前为止所读取内容的计数,例如:

int length_bytes = 0;
while(length_bytes < 4){
   int read = recv(sock,((char*)&nLength)+length_bytes,4-length_bytes,0);
   if (read == -1) some_error_occurred_check_errno();
   length_bytes += read;
}

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读