Russian Qt Forum
Апреля 04, 2025, 00:46 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

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

Страниц: [1]   Вниз
  Печать  
Автор Тема: Финансовая благодарность за правильный ответ: ошибка при чтении порта по сети  (Прочитано 10896 раз)
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.021 секунд. Запросов: 20.