Russian Qt Forum

Qt => Работа с сетью => Тема начата: EPr от Апрель 10, 2021, 11:52



Название: Финансовая благодарность за правильный ответ: ошибка при чтении порта по сети
Отправлено: EPr от Апрель 10, 2021, 11:52
В сети есть 4 машины.
От 1й машины данные проходят через 2ю машину, со 2й машины одинаковые данные поступают на 3ю и 4ю машины.

передача на 2й машине:

Код:
    socket = new QTcpSocket(this);

int writeDev::write(const QByteArray & pkg)
{
    int written = 0;
    written = socket->write(pkg, pkg.size());  
}

прием на 3й и 4й машинах:

Код:
#define BUF_SIZE  10000
#define FRAME_SIZE  10000

    clientsocket = new QTcpSocket(this);  
    tcpServer = new QTcpServer();
    connect(tcpServer, SIGNAL(newConnection()), this, SLOT(newConnect()));


void MainWindow::newConnect()
{
    clientsocket = tcpServer->nextPendingConnection();    
    
    connect(clientsocket, SIGNAL(readyRead()),
            this, SLOT(recPkg()));  
            
    connect(clientsocket, SIGNAL(disconnected()),
            clientsocket, SLOT(deleteLater()));            

}


void MainWindow::recPkg()
{
    int read_size = 0;
    char rpkg[FRAME_SIZE];

    read_size = clientsocket->read(rpkg, BUF_SIZE);

    //обработка данных
}


Когда данные передаются в сети: 1-2-3 или 1-2-4 машины, то ошибок нет.

В сети 1-2-3-4 данные передаются нормально, но периодически или на 3й, или на 4й машине вылетает программа приема. При этом если на 3й программа вылетела, то на 4й работает нормально, если вылетела на 4й, то на 3й работает нормально.

В отладчике на машине, где вылетела программа, выдает в разных случаях такие ошибки:

1. QIODevice:: read called on a WriteOnly device

2. Program received signal SIGSEGV. Segmentation fault.
0x6900529f in ZN9QIODevice4readEPcx from C:\Windows\system32\QtCore4.dll


Готов отблагодарить финансово за ответ, который полностью поможет решить проблему.




Название: Re: Финансовая благодарность за правильный ответ: ошибка при чтении порта по сети
Отправлено: RedDog от Апрель 10, 2021, 17:48
BUF_SIZE == FRAME_SIZE ?


Название: Re: Финансовая благодарность за правильный ответ: ошибка при чтении порта по сети
Отправлено: qate от Апрель 10, 2021, 17:54
Магия SSH https://habr.com/ru/post/331348/


Название: Re: Финансовая благодарность за правильный ответ: ошибка при чтении порта по сети
Отправлено: EPr от Апрель 10, 2021, 19:50
BUF_SIZE == FRAME_SIZE ?

Да.


Название: Re: Финансовая благодарность за правильный ответ: ошибка при чтении порта по сети
Отправлено: RedDog от Апрель 10, 2021, 21:57
Перед чтением, проверить сколько данных доступно в сокете и считывать этот доступный объем.


Название: Re: Финансовая благодарность за правильный ответ: ошибка при чтении порта по сети
Отправлено: kambala от Апрель 11, 2021, 00:49
https://wiki.qt.io/WIP-How_to_create_a_simple_chat_application в методе void ServerWorker::receiveJson() очень хорошо описано как правильно принимать данные из сокетов — вполне возможно, дело именно в этом


Название: Re: Финансовая благодарность за правильный ответ: ошибка при чтении порта по сети
Отправлено: Примерный ученик от Апрель 13, 2021, 11:54
Чтение удобнее в QByteArray.
Обычно при обработке нужно определенное количество данных и какая то часть может быть недостаточной для обработки.
А потому делаю обычно так:
Код:
QByteArray buff; // в объявлениях класса

void MainWindow::recPkg()
{    while (clientsocket->bytesAvailable()) // пока в сокете есть данные
    {
        buff.append(clientsocket->readAll()); // все что есть прочитали и добававили в буфер
// обработка данных
    }
)


Все принятые на текущий момент данные находятся в buff. Программа обработки удаляет использованную часть
и отдает управление для получения новой части.


Название: Re: Финансовая благодарность за правильный ответ: ошибка при чтении порта по сети
Отправлено: EPr от Апрель 18, 2021, 08:02
Выяснил, что при вылете программы приема портится сокет clientsocket.

При нормальной работе в программе приема после строки clientsocket = tcpServer->nextPendingConnection(); и перед строкой read_size = clientsocket->read(rpkg, BUF_SIZE); байты сокета одинаковые, а во время вылета программы в этих строках байты сокета разные.

Примерный ученик, ваш совет наиболее конкретен, но тоже не решил проблему.
А вы принимали вашим способом данные на две машины с одной машины?



Название: Re: Финансовая благодарность за правильный ответ: ошибка при чтении порта по сети
Отправлено: Примерный ученик от Апрель 19, 2021, 17:12
Не понял вопроса... Для каждого соединения создается на стороне сервера отдельный сокет, а посему, совершенно без разницы, на две, на пять, на сотню машин... Если сами не ограничили количество разрешенных одновременных подключений.


Название: Re: Финансовая благодарность за правильный ответ: ошибка при чтении порта по сети
Отправлено: ecspertiza от Апрель 19, 2021, 18:53
Если я верно понимаю как работает TCP. То в корне неверно с одной стороны слать 1000 байт, с другой всегда забирать 1000 байт. Пакеты могут быть разбиты. Отсюда нужен протокол. Отправляем пакет, в заголовке пишем размер пакета. На принимающей стороне, должны вычитать данные размером с пакет, после этого все что читается, идет в следующий. Такое заметили не только на tcp, но и на протоколах поверх tcp типа sctp которые якобы гарантируют доставку. Все они могут разбить ваш пакет. Если не путаю бьет размером с MTU, но на это лучше не закладываться.


Название: Re: Финансовая благодарность за правильный ответ: ошибка при чтении порта по сети
Отправлено: RedDog от Апрель 19, 2021, 21:06
Может не только разбить, но и склеить несколько мелких.
Я использовал заголовок в виде 2-х int содержащих длину пакета (2 раза одно и то жезначение,что то типа контрольной суммы), так была гарантия и понимание, где пакеты разделяются.