Как избежать повторного чтения данных при передаче данных по туннелю tcp / ip ssh? - PullRequest
1 голос
/ 06 мая 2019

Я использую туннель tcp / ip ssh для отправки вектора, содержащего 120000 чисел типа double, с моего компьютера на сервер. Каждый раз я отправляю 250 номеров. Таким образом, я отправляю 120000/250 = 480 раз. Чтобы сервер правильно восстановил мои данные, каждый раз сервер получает 250 номеров и затем отправляет их обратно. В моем компьютере я использую Matlab. На сервере я использую с ++.

Я сравниваю отправленный вектор и полученный вектор. Они не то же самое. После того же номера полученный вектор начинает повторять элементы до, а затем продолжает показывать элементы позже. Например: отправленный вектор: 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;
}

Как изменить мой код на С ++, чтобы вектор получения совпадал с отправленным?

1 Ответ

0 голосов
/ 06 мая 2019

Когда вы используете 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 в вектор.Допустим, только 100 чисел были прочитаны read и записаны в буфер, тогда вы все равно копируете до &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;
}

Это просто для того, чтобы обрисовать в общих чертах основную идею, надеюсь, она поможет.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...