【问题标题】:C++ socket only sends first 4 bytes of dataC++ 套接字只发送前 4 个字节的数据
【发布时间】:2016-11-30 06:37:55
【问题描述】:

我目前正在用 C++ 为 Linux 编写一个套接字包装器。它基本上是处理 TCP 套接字的创建、连接、发送、读取和关闭的类的集合。

在我的套接字类中,除了发送和接收功能外,所有功能都运行良好。它们不返回错误;相反,它只发送数据的前四个字节。

我的发送功能:

int Socket::sends(char* buffer){

    int bytes; // for number of bytes sent

    /* First, send the size of buffer */
    int datalen = strlen(buffer); // get sizeof buffer
    int len     = htonl(datalen); // reformat

    // send the size of the buffer
    bytes = send(socketfd, (char*)&len, sizeof(len), 0); // send the size
    if (bytes < 0){
        cerr << "Error sending size of buffer to socket" << endl;
        return 1;
    }

    /* Now acutally send the data */

    bytes = send(socketfd, buffer, datalen, 0);
    if (bytes < 0){
        cerr << "Error writing buffer to socket" << endl;
        return 1;
    }

    cout << bytes << " written" << endl;

    return 0;

}

其背后的想法是,它发送缓冲区(char* buffer)首先发送缓冲区的大小,然后发送实际的缓冲区。如果遇到错误(返回 -1),则函数通过返回 1 终止。

现在,这里是读取方法:

 int Socket::reads(char* buffer){

    int bytes, buflen; // for bytes written and size of buffer

    /* Read the incoming size */
    bytes = recv(socketfd, (char*)&buflen, sizeof(buflen), 0);
    if (bytes < 0){
        cerr << "Error reading size of data" << endl;
        return 1;
    }
    buflen = ntohl(buflen);

    /* Read the data */

    bytes = recv(socketfd, buffer, buflen, 0);
    if (bytes < 0){
        cerr << "Error reading data" << endl;
        return 1;
    }

    return 0;
}

这里的想法是先读取数据的大小,然后将缓冲区设置为该大小并读入。该函数在出错时返回 1(recv 返回 -1)。

使用这些方法看起来像这样:

socket.sends("Hello World"); // socket object sends the message

char* buffer;
socket.reads(buffer); // reads into the buffer

但是,当我使用这些函数时,我只收到前 4 个字节的数据,然后是奇怪的非 ASCII 字符。我不知道为什么会这样。在sendrecv 函数中没有遇到任何错误,并且函数说只写入了4 个字节。有没有更好的方法来发送或接收数据?我忽略了一个非常简单的错误?

感谢您的帮助!

【问题讨论】:

  • 请注意,C 和 C++ 是不同的语言。请只使用相关标签。
  • 你怎么知道有足够的内存分配给读取?示例代码创建了一个名为 buffer 的指针,但没有将它指向任何已分配的内存。
  • 如果您使用的是非阻塞套接字,recv 可能会读取包括 0 在内的任意字节数,您需要调用 recv 直到您获得所有数据或返回错误。跨度>
  • int datalen = strlen(buffer); // get sizeof buffer 这看起来很可疑
  • char* buffer; socket.reads(buffer); 是您的真实代码还是您“简化”了它?

标签: c++ sockets


【解决方案1】:

您将一个未初始化的指针 (buffer) 传递给您的 reads 方法,这可能解释了它部分工作(未定义的行为)。

而且你不应该将buffer 作为参数传递,因为它不会被修改(而且你还不知道大小)

另外,您必须在收到消息时将其终止。

我会这样做:

 char *Socket::reads(){
    char* buffer;
    int bytes, buflen; // for bytes written and size of buffer

    /* Read the incoming size */
    bytes = recv(socketfd, (char*)&buflen, sizeof(buflen), 0);
    if (bytes < 0){
        cerr << "Error reading size of data" << endl;
        return 1;
    }
    buflen = ntohl(buflen);
    buffer = new char[buflen+1]; // +1 for the NUL-terminator
    /* Read the data */

    bytes = recv(socketfd, buffer, buflen, 0);
    if (bytes < 0){
        cerr << "Error reading data" << endl;
        return 1;
    }
    buffer[buflen] = '\0'; // NUL-terminate the string

    return buffer;
}

主要:

socket.sends("Hello World"); // socket object sends the message

char* buffer = socket.reads(); // reads into the buffer

最后别忘了delete []缓冲区。

也可以使用std::stringstd::vector&lt;char&gt; 来避免newdelete

【讨论】:

  • 这是个好建议,但如果 OP 的 buffer 足够大,则没有 UB。它不是未初始化的,它大概是分配的,然后传递给函数。
  • 你可能是对的。也许我回答得太早了,无法确定。我确定的空终止部分。如果你没有 null 终止,你会得到垃圾,因为它没有被发送,即使缓冲区足够大。
  • buffer 在 OP 末尾的代码中出现 socket.reads(buffer); 时显然未初始化。
  • 我也是这么想的。但阿兰的意思是,它可能是一个不具代表性的main
  • @Jean-FrançoisFabre 哦,我没注意到main .. 你说得对,+1。
猜你喜欢
  • 2012-12-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-11-13
  • 2012-04-26
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多