Russian Qt Forum
Ноябрь 22, 2024, 07:45 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1]   Вниз
  Печать  
Автор Тема: Финансовая благодарность за правильный ответ: ошибка при чтении порта по сети  (Прочитано 10442 раз)
EPr
Новичок

Offline Offline

Сообщений: 3


Просмотр профиля
« : Апрель 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


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


« Последнее редактирование: Апрель 10, 2021, 12:54 от EPr » Записан
RedDog
Частый гость
***
Offline Offline

Сообщений: 221


Просмотр профиля
« Ответ #1 : Апрель 10, 2021, 17:48 »

BUF_SIZE == FRAME_SIZE ?
Записан
qate
Супер
******
Offline Offline

Сообщений: 1177


Просмотр профиля
« Ответ #2 : Апрель 10, 2021, 17:54 »

Магия SSH https://habr.com/ru/post/331348/
Записан
EPr
Новичок

Offline Offline

Сообщений: 3


Просмотр профиля
« Ответ #3 : Апрель 10, 2021, 19:50 »

BUF_SIZE == FRAME_SIZE ?

Да.
Записан
RedDog
Частый гость
***
Offline Offline

Сообщений: 221


Просмотр профиля
« Ответ #4 : Апрель 10, 2021, 21:57 »

Перед чтением, проверить сколько данных доступно в сокете и считывать этот доступный объем.
Записан
kambala
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4747



Просмотр профиля WWW
« Ответ #5 : Апрель 11, 2021, 00:49 »

https://wiki.qt.io/WIP-How_to_create_a_simple_chat_application в методе void ServerWorker::receiveJson() очень хорошо описано как правильно принимать данные из сокетов — вполне возможно, дело именно в этом
Записан

Изучением C++ вымощена дорога в Qt.

UTF-8 has been around since 1993 and Unicode 2.0 since 1996; if you have created any 8-bit character content since 1996 in anything other than UTF-8, then I hate you. © Matt Gallagher
Примерный ученик
Бывалый
*****
Offline Offline

Сообщений: 450


И это не всегда помогает


Просмотр профиля
« Ответ #6 : Апрель 13, 2021, 11:54 »

Чтение удобнее в QByteArray.
Обычно при обработке нужно определенное количество данных и какая то часть может быть недостаточной для обработки.
А потому делаю обычно так:
Код:
QByteArray buff; // в объявлениях класса

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


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

Как мало времени и как много нужно узнать
EPr
Новичок

Offline Offline

Сообщений: 3


Просмотр профиля
« Ответ #7 : Апрель 18, 2021, 08:02 »

Выяснил, что при вылете программы приема портится сокет clientsocket.

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

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

Записан
Примерный ученик
Бывалый
*****
Offline Offline

Сообщений: 450


И это не всегда помогает


Просмотр профиля
« Ответ #8 : Апрель 19, 2021, 17:12 »

Не понял вопроса... Для каждого соединения создается на стороне сервера отдельный сокет, а посему, совершенно без разницы, на две, на пять, на сотню машин... Если сами не ограничили количество разрешенных одновременных подключений.
Записан

Как мало времени и как много нужно узнать
ecspertiza
Супер
******
Offline Offline

Сообщений: 1053


С уважением, мастер конфетного цеха!


Просмотр профиля
« Ответ #9 : Апрель 19, 2021, 18:53 »

Если я верно понимаю как работает TCP. То в корне неверно с одной стороны слать 1000 байт, с другой всегда забирать 1000 байт. Пакеты могут быть разбиты. Отсюда нужен протокол. Отправляем пакет, в заголовке пишем размер пакета. На принимающей стороне, должны вычитать данные размером с пакет, после этого все что читается, идет в следующий. Такое заметили не только на tcp, но и на протоколах поверх tcp типа sctp которые якобы гарантируют доставку. Все они могут разбить ваш пакет. Если не путаю бьет размером с MTU, но на это лучше не закладываться.
Записан
RedDog
Частый гость
***
Offline Offline

Сообщений: 221


Просмотр профиля
« Ответ #10 : Апрель 19, 2021, 21:06 »

Может не только разбить, но и склеить несколько мелких.
Я использовал заголовок в виде 2-х int содержащих длину пакета (2 раза одно и то жезначение,что то типа контрольной суммы), так была гарантия и понимание, где пакеты разделяются.
Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.052 секунд. Запросов: 23.