如何避免在TCP / IP SSH隧道的数据传输中重复读取数据?

时间:2019-05-06 14:04:57

标签: c++ matlab tcp

我使用tcp / ip ssh隧道从计算机向服务器发送包含120000个double类型数字的向量。每次我发送250个号码。因此,我发送了120000/250 = 480次。为确保服务器正确显示我的数据,请提前等待服务器接收250个数字,然后将其发送回去。在计算机上,我使用Matlab。在服务器中,我使用c ++。

我比较发送的向量和接收的向量。它们不一样。经过相同的数字后,接收到的向量开始重复元素,然后再继续显示元素。例如:发送向量:123456789,接收向量:123454567

Ynew是发送的向量,Yrecieve是接收的向量,matlab代码:

tcp = tcpip('127.0.0.1', 54321, 'NetworkRole', 'server');

linput=250;

set(tcp, 'OutputBufferSize', 8*linput);
set(tcp, 'InputBufferSize', 8*linput);

Yrecieve=zeros(size(Ynew));

fopen(tcp);

i=0;
while(i<length(Ynew))    
    din=Ynew(i+1:i+linput);
    while(sum(isnan(swapbytes(din)))~=0)
        din(isnan(swapbytes(din)))=din(isnan(swapbytes(din)))*1.00001;
    end
    fwrite(tcp, swapbytes(din), 'double');

    dout = fread(tcp, linput, 'double');
    Yrecieve(i+1:i+linput)=swapbytes(dout);    

    i=i+linput;
end

fclose(tcp);

c ++代码:

#include <stdio.h>
#include <iostream>
#include<vector>
#include <math.h>

extern "C"
void useCUDA();

#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>

using namespace std;



int main()
{

    vector<double> Y;

    int lread = 250, nMu = 4, ltotal = 120000;

    int sock = socket(AF_INET, SOCK_STREAM, 0);

    struct sockaddr_in serv_addr;
    memset(&serv_addr, 0, sizeof(serv_addr));
    serv_addr.sin_family = AF_INET;
    serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
    serv_addr.sin_port = htons(54321);
    connect(sock, (struct sockaddr*)&serv_addr, sizeof(serv_addr));


    double* block_buffer_input;
    block_buffer_input = new double[lread];
    double* block_buffer_output;
    block_buffer_output = new double[lread];

    int Ylength = Y.size();

    while (Y.size() < ltotal)
    {

        while (Y.size() == Ylength)
        {
            read(sock, reinterpret_cast<char*>(block_buffer_input), lread * sizeof(double));
            Y.insert(Y.end(), &block_buffer_input[0], &block_buffer_input[lread]);
        }

        Ylength = Y.size();

        int Sp = Y.size() - lread;
        for (int i = 0; i != lread; ++i)
        {
            block_buffer_output[i] = Y[Sp + i];
        }
        write(sock, (char*)block_buffer_output, lread * sizeof(double));



    }


    delete[] block_buffer_input;
    delete[] block_buffer_output;
    close(sock);

    return 0;
}

如何更改我的c ++代码以使接收的矢量与发送的矢量相同?

1 个答案:

答案 0 :(得分:0)

使用read时,需要使用其返回值来知道实际上已接收了多少个字节。在您的代码中,您假设每次通话都会获得lread = 250个号码

read(sock, reinterpret_cast<char*>(block_buffer_input), lread * sizeof(double));
Y.insert(Y.end(), &block_buffer_input[0], &block_buffer_input[lread]);

但是,read可能只读取了一个字节或两个或更多字节...在这种情况下,您仍然将block_buffer_input中的旧垃圾插入向量中。假设read只能读取100个数字并将其写入缓冲区,然后您仍要复制到&block_buffer_input[lread]

相反,您的代码应更像这样:

size_t bytes_expected = xy;
size_t bytes_read = 0;
while (bytes_read < bytes_expected) {        
   auto r = read(sock,buffer,bytes_expected);  // last parameter is just the maximum, but less might be read
   // copy only that part of the buffer that contains valid data
   Y.insert(Y.end(),buffer.begin(),buffer.begin()+r);
   bytes_read += r;
}

这只是概述基本概念,希望对您有所帮助。