从套接字接收时出错

时间:2017-08-06 00:10:46

标签: c++ sockets null receiver

我需要从服务器接收消息,到目前为止我可以做到这一点,但我仍然有一个问题,我不知道它是什么。该文本定义消息采用以下格式:

  • 作为标题,2个字节表示消息的其余部分(有效负载+ 校验和);
  • 作为预告片,校验和为1个字节(校验和为 计算包括大小的2个字节)
  • ,其余部分 字节用于有效负载本身(在消息中间)

我试图接收该消息,所以我使用了接收函数,它位于

之下
/**
    Receive data from the connected host
*/
    string client::receive(int size){
    //string buffer;
    string reply;
    std::vector<char> buffer(size, 0);
    //strcpy(buffer, "\0");
   // memset(&buffer[0], 0, sizeof(buffer));
    int result = recv(sock, buffer.data(), buffer.size(), 0);

    if( result < 0){
        puts("recv failed");
    }
    cout << "read bytes: " << result << endl;
    cout << "buffer: " << buffer.data() << endl;
    //reply = stringToBit(buffer);
    reply = buffer.data();
    cout << "reply: " << reply << endl;

    return reply;
    }

但问题是,当我暂时接收接收以接收所有消息时,事情开始变得奇怪。起初,我意识到我只需要清理缓冲区,但事情仍然很奇怪,因为对于消息,我收到的信息是:

第一条消息: NULL - 收到的字节数:2

第二条消息:用户接受 - 接收的字节数:14

第3条消息:5 - 接收的字节数:1

第4条消息: NULL - 收到的字节数:2

第5条消息: unprintable_char 501&amp; xt,md-ldt ='t&lt; 1t?1-t $; =: - 收到的字节数:30

第6条消息: NULL - 收到的字节数:1

第5条消息总是会改变,但其余的消息(消息和字节数)总是相同的。当从3中查看消息1时,我认为可能有3个是大小的标题,2是消息,3是校验和。但是,接收所有那些 NULL 而不是任何有用的信息,否则会让我感到厌烦。

有人对可能发生的事情有所了解吗?我对服务器没有控制权,我只能相信服务器按照规定发送这些消息。

2 个答案:

答案 0 :(得分:1)

服务器会向您发送邮件大小。你必须利用这个优势。此外,定义您的功能的方式使报告错误变得困难。你应该考虑这样的事情:

// receives a fixed number of bytes. returns zero or a negative number on error
int client::receiveBytes(size_t n, void* buffer)
{
     char* p = reinterpret_cast<char*>(buffer);
     while (n)
     {
         int got = recv(sock, p, n, 0);
         if (got <= 0)
             return got;
         n -= got;
         p += got;
     }
     return 1;
}

/**
Receive data from the connected host
*/
int client::receive(std::string& reply) 
{
    reply.clear();
    uint16_t replyLength = 0;    // or the appropriate 16-bit type if your compiler doesn't provide <cstdint>

    int result = receiveBytes(2, &replyLength);
    if (result <= 0)
        return result;

    if (replyLength == 0)  // <-- you could add more length validation here 
       return -1;          // <-- or whatever error code you wish...

    reply.resize(replyLength);
    result = receiveBytes(replyLength, &reply[0]);

    if (result <= 0)
        return result;

    // verify the checksum.  failure indicates we have lost sync...

    // I'm assuming here that the checksum is computed using plain char's,
    const char* p = reinterpret_cast<const char*>(&replyLength);
    char chksum = *(p++) + *p;

    for (size_t i = 0; i < replyLength - 1; ++i)
        chksum += reply[i];

    if (chksum != reply[replyLength - 1])
    {
         // there is not much that can be done to recover sync with this protocol
         // the best option the caller has is to close the connection and start anew.
         reply.clear();
         return -1;   // or whatever error code you wish...
    }
    reply.resize(replyLength - 1);
    return reply.size();
}

答案 1 :(得分:-1)

我为16位整数创建了另一个接收函数(由于某种原因我不知道),我意识到字节已被交换。例如:

我收到号码3840,二进制表示法是:0000111100000000

但我应该收到15,二进制表示是: 0000000000001111

所以,除了接收之外,我还添加了一些字节交换的想法

 int client::receiveSize(){
    int16_t size;
    int result = recv(sock, &size, sizeof(size), 0);

    int hibyte = (size & 0xff00) >> 8;
    int lobyte = (size & 0xff);
    size = lobyte << 8 | hibyte;
    cout << "received: " << size << " and " << result<< endl;
    return size;
}

我意识到了(方式!我学到了一些东西),我应该准确地说明我将在recv上接收的数据类型。否则,我可以获得没有意义的信息。