c++ - 发出 double over TCP 套接字的发送/接收 vector (丢失数据)

标签 c++ sockets vector send recv

我正在尝试通过 TCP 套接字从 vector 发送数据。 我正在处理一个 vector ,我用 0 到 4999 之间的值填充它,然后将它发送到套接字。

客户端,我将数据接收到一个 vector 中,然后我将其数据复制到另一个 vector ,直到我从服务器接收到所有数据。

我面临的问题是,当我收到我的数据时,有时我会得到所有的数据,有时我只会收到从 0 到 1625 的正确数据,然后我得到垃圾数据直到最后(请参阅下图)。例如,我什至收到了从 0 到 2600 的正确数据,然后从 2601 到 3500 是垃圾数据,最后从 3501 到 4999 又是正确的。

File containing received data
(左列是行号,右列是数据)。

这是服务器端:

vector<double> values2;
for(int i=0; i<5000; i++)
    values2.push_back(i);
skt.sendmsg(&values2[0], values2.size()*sizeof(double));

函数发送消息:

void Socket::sendmsg(const void *buf, size_t len){

    int bytes=-1;

    bytes = send(m_csock, buf, len, MSG_CONFIRM);

    cout << "Bytes sent: " << bytes << endl;

}

客户端:

vector<double> final;
vector<double> msgrcvd(4096);

do{

    bytes += recv(sock, &msgrcvd[0], msgrcvd.size()*sizeof(double), 0);
    cout << "Bytes received: " << bytes << endl;

    //Get rid of the trailing zeros
    while(!msgrcvd.empty() && msgrcvd[msgrcvd.size() - 1] == 0){
        msgrcvd.pop_back();

    }

    //Insert buffer content into final vector
    final.insert(final.end(), msgrcvd.begin(), msgrcvd.end());


}while(bytes < sizeof(double)*5000);


//Write the received data in a txt file

for(int i=0; i<final.size(); i++)
    myfile << final[i] << endl;

myfile.close();


字节的输出是正确的,服务端发送数据时输出40000,客户端接收数据时也输出40000。

删除尾随零,然后将缓冲区的内容插入到新 vector 中效率不是很高,但我认为这不是问题所在。如果您对如何提高效率有任何线索,那就太好了!

我真的不知道问题是在我发送数据时还是在我接收数据时出现,而且我也不明白为什么有时(很少)我会收到所有数据。

最佳答案

recv 接收 bytes,并且不一定等待发送的所有数据。所以您可以获得 double 的一部分。

如果您收到完整的 double 值,您的代码可以正常工作,但当您收到部分值时,代码将失败。您应该在 char 缓冲区中接收数据,然后将其解压缩为 double 值。 (如果服务器和客户端不同,可能会转换字节顺序。)

#include <cstring>    // For memcpy

std::array<char, 1024> msgbuf;
double d;
char data[sizeof(double)];
int carryover = 0;

do {
    int b = recv(sock, &msgbuf[carryover], msgbuf.size() * sizeof(msgbuf[0]) - carryover, 0);
    bytes += b;
    b += carryover;
    const char *mp = &msgbuf[0];
    while (b >= sizeof(double)) {
        char *bp = data;
        for (int i = 0; i < sizeof(double); ++i) {
            *bp++ = *mp++;
        }
        std::memcpy(&d, data, sizeof(double));
        final.push_back(d);
        b -= sizeof(double);
    }
    carryover = b % sizeof(double);
    // Take care of the extra bytes.  Copy them down to the start of the buffer
    for (int j = 0; j < carryover; ++j) {
        msgbuf[j] = *mp++;
    }
} while (bytes < sizeof(double) * 5000);

这使用了来自 What's a proper way of type-punning a float to an int and vice-versa? 的双关语类型将接收到的二进制数据转换为 double 据,并假定客户端和服务器的字节顺序相同。

顺便说一句,接收方如何知道它接收了多少值?您的服务器代码中混合了硬编码值 (5000) 和动态值 (.size())。

注意:代码未编译或测试

关于c++ - 发出 double over TCP 套接字的发送/接收 vector (丢失数据),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56331230/

相关文章:

Matlab:如何实现动态向量

c++ - 在循环中添加预期的调用

c++ - 为什么这个简单的 C++ 代码不能编译?

Java套接字发送数据

Flash XML 套接字阻塞

python - Numpy 矩阵乘法返回 nan

c++ - 除了 iostreams 之外,标准库中的哪些内容不能被复制?

c++ - 在 Cygwin 64 上包含 boost.asio 时出错

java - 设置单独的 SO_TIMEOUT

c++ - 初始化 vector 的 vector (外部 vector 和内部 vector )