【问题标题】:How to get the exact message from recv() in winsock programming?如何在winsock编程中从recv()获取确切的消息?
【发布时间】:2015-02-16 02:35:22
【问题描述】:

我正在使用 C++ 中的 Winsock 开发服务器-客户端应用程序,但遇到了问题。

为了让服务器从客户端获取消息,我使用下面的代码。

int result;
char buffer[200];

while (true)
{
    result = recv(client, buffer, 200, NULL);

    if (result > 0)
        cout << "\n\tMessage from client: \n\n\t" << message << ";";
}

我将消息“Hello”从客户端发送到服务器。然而缓冲区实际上是这样的:

HelloÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌ

我错过了什么?

【问题讨论】:

  • 如果你想要一个空终止符,你必须自己添加一个。
  • 谢谢。空终止符到底是什么?假设我添加了一个空终止符或任何类似的东西。如何从缓冲区中检索字符串?请给我一个示例代码好吗?
  • 通过网络发送以空字符结尾的字符串会引发各种安全问题。从头开始编写协议是一项艰巨的任务。您可以使用 google 协议缓冲区之类的东西来编码/解码数据包的内容,从而为自己节省大量工作。
  • std::string str(buffer);
  • 真正的艾伦,我的错。 memcpy(缓冲区+结果,“\0”,1); // 我猜这应该可行。

标签: c++ winsock


【解决方案1】:

memset(&receive[0], 0, sizeof(receive));
清除缓冲区

【讨论】:

  • 请在您的回答中添加更多描述。
【解决方案2】:

你没有初始化你的缓冲区

char buffer[200] = {0};

while (true)
{
    result = recv(client, buffer, 200, NULL);

    if (result > 0)
        cout << "\n\tMessage from client: \n\n\t" << message << ";";
    memset(buffer, 0, 200);
}

【讨论】:

    【解决方案3】:

    由于recv 可能没有收到你告诉它的那么多字节,你通常使用一个函数 像这样接收指定的字节数。修改自here

    int receiveall(int s, char *buf, int *len)
    {
        int total = 0;        // how many bytes we've received
        int bytesleft = *len; // how many we have left to receive
        int n = -1;
    
        while(total < *len) {
            n = recv(s, buf+total, bytesleft, 0);
            if (n <= 0) { break; }
            total += n;
            bytesleft -= n;
        }
    
        *len = total; // return number actually received here
    
        return (n<=0)?-1:0; // return -1 on failure, 0 on success
    } 
    

    如果您收到的字符串不是空终止的,则由您决定是否终止该字符串。

    【讨论】:

    • 我实际上通过在客户端发送的消息末尾添加空终止符'\0'来解决问题。
    • @user3530012:是的,但总的来说,您应该记住,recv 正如我所说的可能不会收到您告诉它的所有数据(阅读我提供的链接了解更多详细信息)跨度>
    【解决方案4】:

    结果告诉您收到了多少字节。 recv 不添加终止符,因为通常网络数据是二进制数据,可能无法用作 C 样式的字符串。

    如果您知道消息不包含终止字符,您可以自己添加终止符:

    buffer[result] = 0;  // make sure the buffer is large enough
    

    或从中创建一个字符串(或向量,或其他):

    std::string message_str(message, result);
    

    请注意,您收到的可能不是单个“消息”,尤其是当您使用 TCP 等流协议时。它可能包含不止一条消息,或者只是一条消息的开头。

    【讨论】:

      猜你喜欢
      • 2017-04-28
      • 1970-01-01
      • 1970-01-01
      • 2019-08-06
      • 2013-10-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多