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

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

Страниц: [1] 2   Вниз
  Печать  
Автор Тема: QAbstractSocket - хочется уточнить возможные тонкости  (Прочитано 10286 раз)
Гурман
Гуру общения
******
Offline Offline

Сообщений: 1442

Qt 2.2, 3.3, 4.5, 4,7, 4.8, 5.3, 5.6, 5.9, 5.12


Просмотр профиля
« : Декабрь 26, 2013, 10:00 »

Надо передавать и принимать байты некоему устройству через LAN или физический порт принтера. Через порт принтера всё работает на ура. Через LAN с разбега не получилось. Вот код функций (то, что класс называется MainWindow пусть не смущает, приложение глухо консольное, просто так исторически сложилось).

собственно установка соединения:

Код:
bool MainWindow::EnableTransfer() // вызывается из конструктора MainWindow
{
if( ! ipusing )
{
qDebug( "Opening parallel port transfer... " );

h = CreateFileA( "\\\\.\\UserPort", GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if( h == INVALID_HANDLE_VALUE )
{
qDebug ("Error: could not get parallel port access.\n");
return false;
}
}
else
{
bool converted = false;
unsigned int port = a->arguments().at(2).toUInt( &converted ); // QCoreApplication* a
if( ! converted )
{
qDebug ("Error: invalid port number.\n");
return false;
}

qDebug( "Opening TCP/IP transfer... (to use paraller port add LPT after program name) " );

if( ( socket = new QAbstractSocket( QAbstractSocket::TcpSocket, a ) ) == 0 )
{
qDebug ("Error: could not create connection.\n");
return false;
}

socket->connectToHost( a->arguments().at(1), port );

if( ! socket->waitForConnected( PortTimeOut ) )
{
qDebug ("Error: Connection timeout.\n");
return false;
}
}
qDebug( "Running normal\n" );
return true;
}

и чтение-запись байтов данных:
Код:
void MainWindow::outport( BYTE data )
{
if( ipusing )
{
if( ! socket->putChar( data ) )
{
qDebug( "Error: Network write error.\n" );
a->exit( -1 );
}
socket->flush();
}
else // LPT
{
__asm
(
"outb %%al, %%dx;"
   : // нет ничего
   : "d" (lpt_addr), "a" (data) // AX:данные, DX:адрес
);
}
}

BYTE MainWindow::inport()
{
if( ipusing )
{
char data;
if( ! socket->getChar( &data ) )
{
qDebug( "Error: Network read error.\n" );
a->exit( -1 );
return -1;
}
return data;
}
// else LPT
__asm
(
"inb %%dx, %%al;"
   : // возврат в AX
   : "d" (lpt_addr+1) // DX:адрес AX:данные
);
// return уже на месте
}

Устройство открывается, сетевых ошибок нет, байты по сети в него улетают, ошибок передачи тоже нет, но при приеме ответа прилетает белиберда, чаще 0, иногда нет. Но совсем не то, что ожидается. Конечно, могут быть ошибки при передаче самим устройством. Через параллельный порт работает всё правильно, то есть устройство правильно формирует ответные данные - ошибки могут быть в реализации сетевых функций на устройстве. Или - может есть какие-то тонкости при работе с сокетами в Qt? Кто опытный в реализации подобного обмена - подскажите.
« Последнее редактирование: Декабрь 27, 2013, 11:59 от Гурман » Записан

2^7-1 == 127, задумайтесь...
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4350



Просмотр профиля
« Ответ #1 : Декабрь 26, 2013, 10:18 »

А почему создаете QAbstractSocket вместо QTcpSocket?
Записан
Гурман
Гуру общения
******
Offline Offline

Сообщений: 1442

Qt 2.2, 3.3, 4.5, 4,7, 4.8, 5.3, 5.6, 5.9, 5.12


Просмотр профиля
« Ответ #2 : Декабрь 26, 2013, 10:33 »

А почему создаете QAbstractSocket вместо QTcpSocket?

а какая разница? у QTcpSoclet нет своих методов, это просто враппер над QAbstractSocket

Код:
//#define QTCPSOCKET_DEBUG
/*!
\class QTcpSocket
\brief The QTcpSocket class provides a TCP socket.
\reentrant
\ingroup io
\inmodule QtNetwork
TCP (Transmission Control Protocol) is a reliable,
stream-oriented, connection-oriented transport protocol. It is
especially well suited for continuous transmission of data.
QTcpSocket is a convenience subclass of QAbstractSocket that
allows you to establish a TCP connection and transfer streams of
data. See the QAbstractSocket documentation for details.
\bold{Note:} TCP sockets cannot be opened in QIODevice::Unbuffered mode.
\sa QTcpServer, QUdpSocket, QFtp, QNetworkAccessManager,
{Fortune Server Example}, {Fortune Client Example},
{Threaded Fortune Server Example}, {Blocking Fortune Client Example},
{Loopback Example}, {Torrent Example}
*/
#include "qlist.h"
#include "qtcpsocket_p.h"
#include "qtcpsocket.h"
#include "qhostaddress.h"
QT_BEGIN_NAMESPACE
/*!
Creates a QTcpSocket object in state \c UnconnectedState.
\a parent is passed on to the QObject constructor.
\sa socketType()
*/
QTcpSocket::QTcpSocket(QObject *parent)
: QAbstractSocket(TcpSocket, *new QTcpSocketPrivate, parent)
{
#if defined(QTCPSOCKET_DEBUG)
qDebug("QTcpSocket::QTcpSocket()");
#endif
d_func()->isBuffered = true;
}
/*!
Destroys the socket, closing the connection if necessary.
\sa close()
*/
QTcpSocket::~QTcpSocket()
{
#if defined(QTCPSOCKET_DEBUG)
qDebug("QTcpSocket::~QTcpSocket()");
#endif
}
/*!
\internal
*/
QTcpSocket::QTcpSocket(QTcpSocketPrivate &dd, QObject *parent)
: QAbstractSocket(TcpSocket, dd, parent)
{
d_func()->isBuffered = true;
}
QT_END_NAMESPACE
« Последнее редактирование: Декабрь 26, 2013, 10:39 от Гурман » Записан

2^7-1 == 127, задумайтесь...
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4350



Просмотр профиля
« Ответ #3 : Декабрь 26, 2013, 10:42 »

а какая разница?
Ну как-бы это сейчас может нет разницы, а дальше (в следующих версиях Qt) она может появиться. Улыбающийся

Попробуйте вначале дождаться данных: waitForReadyRead или ожиданием сигнала.

Записан
Гурман
Гуру общения
******
Offline Offline

Сообщений: 1442

Qt 2.2, 3.3, 4.5, 4,7, 4.8, 5.3, 5.6, 5.9, 5.12


Просмотр профиля
« Ответ #4 : Декабрь 26, 2013, 15:40 »

а какая разница?
Ну как-бы это сейчас может нет разницы, а дальше (в следующих версиях Qt) она может появиться. Улыбающийся

меня интересует исключительно сейчас Веселый

Попробуйте вначале дождаться данных: waitForReadyRead или ожиданием сигнала.

а без разницы - что socket->getChar( &data ) вернет ошибку, потому что данных нет, что будет ожидание - не приходят они...
Записан

2^7-1 == 127, задумайтесь...
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4350



Просмотр профиля
« Ответ #5 : Декабрь 26, 2013, 16:13 »

не приходят они...
Остается поснифать сетевой трафик и посмотреть что происходит.
Записан
Гурман
Гуру общения
******
Offline Offline

Сообщений: 1442

Qt 2.2, 3.3, 4.5, 4,7, 4.8, 5.3, 5.6, 5.9, 5.12


Просмотр профиля
« Ответ #6 : Декабрь 27, 2013, 07:54 »

То есть, у меня в коде всё правильно, и никаких тонкостей, которые я бы упустил, у QAbstractSocket нет?
Записан

2^7-1 == 127, задумайтесь...
Bepec
Гость
« Ответ #7 : Декабрь 27, 2013, 08:24 »

Оригинально только чтение по одному байту, а не всего пришедшего пакета.

Посоветовал бы сделать тестовый вариант программы для устройства, посылающей инкрементируемый счётчик в цикле по сокету.

Тогда сразу можно будет сказать где проблема.
Записан
Гурман
Гуру общения
******
Offline Offline

Сообщений: 1442

Qt 2.2, 3.3, 4.5, 4,7, 4.8, 5.3, 5.6, 5.9, 5.12


Просмотр профиля
« Ответ #8 : Декабрь 27, 2013, 09:26 »

а устройство посылает и принимает байты, если делать обмен пакетами, то надо прошивку устройства переделывать
Записан

2^7-1 == 127, задумайтесь...
Bepec
Гость
« Ответ #9 : Декабрь 27, 2013, 10:02 »

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

Ну переделайте прошивку в болванку, которая эхо генерирует. Я не думаю, что это сложно.

PS а как вы вообще разрабатываете под устройство, если не проверяете систему связи?
Записан
Гурман
Гуру общения
******
Offline Offline

Сообщений: 1442

Qt 2.2, 3.3, 4.5, 4,7, 4.8, 5.3, 5.6, 5.9, 5.12


Просмотр профиля
« Ответ #10 : Декабрь 27, 2013, 10:30 »

вот это и есть проверка

получать пакет нет смысла, обмен идет по одному байту - передача-прием-передача-прием, то есть, команда-ответ-команда-ответ...

добавил задание размера буфера в 1 байт, и ожидание его заполнения - получаю таймаут...

ну ясно, в общем, придется нашим друзьям ковырять прошивку, очевидно, дело всё-таки, в ней
« Последнее редактирование: Декабрь 27, 2013, 10:45 от Гурман » Записан

2^7-1 == 127, задумайтесь...
Bepec
Гость
« Ответ #11 : Декабрь 27, 2013, 10:57 »

WireShark скачайте и посмотрите, что от устройства и к устройству идёт. Будет гораздо лучше вам и вашим друзьям, если вы увидите - устройство что-то посылает, или нет.

WireShark так же покажет, если придёт некорректная информация. И будет уже на что опираться. То ли молчит, то ли говорит не по протоколу Улыбающийся
Записан
Гурман
Гуру общения
******
Offline Offline

Сообщений: 1442

Qt 2.2, 3.3, 4.5, 4,7, 4.8, 5.3, 5.6, 5.9, 5.12


Просмотр профиля
« Ответ #12 : Декабрь 27, 2013, 11:02 »

WireShark скачайте и посмотрите

это, кстати, дело...
Записан

2^7-1 == 127, задумайтесь...
Гурман
Гуру общения
******
Offline Offline

Сообщений: 1442

Qt 2.2, 3.3, 4.5, 4,7, 4.8, 5.3, 5.6, 5.9, 5.12


Просмотр профиля
« Ответ #13 : Январь 10, 2014, 08:08 »

Приходится поднять тему... С помощью сторонней программы установили, что связь с устройством работает - в него прошили простой loopback, посылающий на выход то, что оно получает. И отдельная софтина на Борланде нормально получает то, что послала. Но код на Qt, который выше - банан. Соединение есть, дополнительные проверки

Код:
		if( ! socket->isValid() )
{
qDebug ("Error: Socket is not valid.\n");
return false;
}
if( ! socket->isOpen() ) // MUST be opened before
{
if( ! socket->open( QIODevice::ReadWrite ) )
{
qDebug ("Error: Socket is not open.\n");
return false;
}
}

ничего не дали - сокет валидный, открытый. Функция передачи putChar() ошибку не возвращает. Но при чтении getChar() ошибка. А если перед ней waitForReadyRead(), то всегда таймаут. Без ожидания готовности докопался до ошибки getChar() - Error: Network read error: Invalid socket descriptor.  Непонимающий Как это? Почему инвалид? Только что туда запись была, всё было валид.  Грустный Сокет никто не закрывал, вообще с ним ничего не делал, кроме записи. И причем - если последовательно писать и читать несколько раз, то каждая запись проходит без ошибки, но каждое чтение возвращает ошибку. Как это может быть? На всякий случай явно указал, хотя это по дефолту:

socket->connectToHost( a->arguments().at(1), port, QIODevice::ReadWrite );

разумеется, не помогло.

Проверил значение дескриптора сокета после открытия и при чтении - всё нормально, значение совпадает. При чтении состояние Connection established. Что вообще не так?

« Последнее редактирование: Январь 10, 2014, 09:04 от Гурман » Записан

2^7-1 == 127, задумайтесь...
Bepec
Гость
« Ответ #14 : Январь 10, 2014, 09:36 »

Как вариант привести сюда программу на борланде. Посмотрим, сравним.

PS хотя некорректный сокет это плохо. Может в борланде где то инициализация какая нибудь происходит?
Записан
Страниц: [1] 2   Вверх
  Печать  
 
Перейти в:  


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