【问题标题】:Creating an array of chars to accept a message from a client on a server创建一个字符数组以接受来自服务器上客户端的消息
【发布时间】:2013-10-11 18:08:07
【问题描述】:

我正在尝试用 C++ 编写一个程序,该程序将接受来自服务器上客户端的消息。但首先客户端发送消息的 size 并使用此值,服务器将创建一个字符数组来存储消息最终发送时。当我尝试使用消息大小值初始化数组时,编译器说存在错误,因为 messageSize 整数必须是一个常量值 - 我想知道为什么会这样,因为据我所知,初始化是完全可以接受的整数类型数组的长度:

//Deal with data in DNS style
int dnsStyle()
{   
    recv(clientSocket, bufferSize, 1, MSG_WAITALL);
    return bufferSize[0];
}

//Communicate in the DNS style of addressing
char DNS()
{
    int messageSize = dnsStyle();
    printf("The message buffer has been tailoured to this size: '%d'", messageSize);
    char bufferMessDNS[messageSize];
    //Then recieve the actual message itself
    recv(clientSocket, bufferMessDNS, messageSize, MSG_WAITALL);
    //Then send the message back to client
    send(clientSocket, bufferMessDNS, messageSize, 0);

    //std::string returnMess = "OK";
    //send(clientSocket, sendBack.c_str(), sendBack.size(),0);
}

【问题讨论】:

    标签: c++ network-programming


    【解决方案1】:

    在 C++ 中——请注意,我们谈论的是没有扩展的符合 C++——自动数组分配的大小在编译时已知,因为数组的大小必须在编译时知道。

    因此,这段代码:

    char bufferMessDNS[messageSize];
    

    格式不正确,因为messageSize 可以更改。

    如果您需要不同大小的数组,请使用vector <char>

    如果您将messageSize 设为所谓的积分常量表达式,则可以使上述代码工作,如下所示:

    const size_t messageSize = 256;
    char bufferMessDNS[messageSize];
    

    但是这里缓冲区的大小总是正好是 256 字节——我敢肯定这几乎永远不会是正确的大小。

    如果必须,您还可以使用 new[] 使用动态大小的数组:

    char* bufferMessDNS = new char [messageSize]
    

    但这会带来一大堆新问题,其中最重要的是管理您刚刚分配的内存的所有权。现在你必须delete那个:

    delete [] bufferMessDNS;
    

    【讨论】:

    • 我想我会选择动态大小的数组,因为它使用相同的结构并且意味着只需对代码进行微小的更改。谢谢。
    【解决方案2】:

    要扩展John Diblings answer,您应该使用std::vector<char> 作为缓冲区。它是这样工作的:

    char DNS()
    {
        std::vector<char>::size_type messageSize = dnsStyle(); // use correct type
        printf("The message buffer has been tailoured to this size: '%d'", messageSize);
        std::vector<char> bufferMessDNS(messageSize); // create vector with correct size
        //Then recieve the actual message itself
        recv(clientSocket, &bufferMessDNS[0], messageSize, MSG_WAITALL);
        //Then send the message back to client
        send(clientSocket, &bufferMessDNS[0], messageSize, 0);
    
        //std::string returnMess = "OK";
        //send(clientSocket, sendBack.c_str(), sendBack.size(),0);
    }
    

    这里最重要的部分是通过调用以size_type 作为参数的构造函数,以正确的大小初始化std::vector。要将缓冲区传递给revc,您只需获取std::vector 的第一个元素的地址。

    【讨论】:

    • +1 - 谢谢。我不会将您的答案合并到我的答案中,因为我只是在抄袭,而您应该为此获得代表。
    • 为什么不只是size_t messageSize?无论如何,这就是 recv/send 想要的。
    • std::vector 的构造函数需要 std::vector::size_type
    • 与数组相比,提醒一下向量的灵活性很好 - 唯一的问题是如果我错了,请纠正我,但是当收到消息然后再次发送时,你正在放整个消息在向量的第一个位置,所以我想当你真的让它长度为 1 时,创建一个长度为 messageSize 的向量有什么意义吗?
    • 你误会了。大小为nvector&lt;char&gt; 在内存中连续保存n 字符。由于像recvsend 这样的C-API 只接受char *,我们传入向量的第一个元素的地址。这是因为vector 保证内存布局与普通数组相同。
    【解决方案3】:

    您应该只声​​明一个大小可以在编译时解释的数组。即,它应该是 int 文字 (char bufferMessDNS [100]) 或使用宏(如 #define MSG_SIZE 100)或 const int

    出于您的目的,因为您只会在运行时知道您可以选择的大小

    char *bufferMessDNS = new char[messageSize];
    ....
    delete []bufferMessDNS
    

    【讨论】:

      【解决方案4】:

      问题是,编译器需要知道在编译时在堆栈上创建的所有变量的大小 -> 你只能分配在编译时已知大小的数组

      如果大小仅在运行时已知,则可以使用动态内存分配。 即:

      char bufferMessDNS[messageSize];
      // replace with
      char* bufferMessDNS = new char[messageSize];
      
      // and at the end of your function don't forget to release the memory
      delete[] bufferMessDNS;
      

      详细解答为什么编译器必须在编译时知道栈变量的大小,请看这篇文章: Why does a C/C++ compiler need know the size of an array at compile time?

      【讨论】:

        【解决方案5】:

        这是一个非常严格的 C 编译器吗?也许您只需要将声明与初始化分开?

        int messageSize;
        messageSize = dnsStyle();
        

        【讨论】:

          猜你喜欢
          • 2023-03-10
          • 1970-01-01
          • 2013-03-28
          • 1970-01-01
          • 2017-06-18
          • 2018-09-02
          • 2019-09-05
          • 2019-10-13
          • 2015-09-09
          相关资源
          最近更新 更多