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

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

Страниц: [1]   Вниз
  Печать  
Автор Тема: Необработанное исключение при отправке ответа через сокет  (Прочитано 2847 раз)
niklep
Гость
« : Апрель 26, 2011, 23:18 »

Доброго времени суток. Есть слот, связанный с сигналом:
Код:
connect(clientSocket, SIGNAL(readyRead()),
this, SLOT(slotReadClient())); // при поступлении запросов от клиентов
Код:
void ServerSocket::slotReadClient()
{
QTcpSocket* clientSocket = (QTcpSocket*)sender();
QDataStream in(clientSocket);
in.setVersion(QDataStream::Qt_4_5);
for (;;)
{
if (!m_nNextBlockSize)
{
if (clientSocket->bytesAvailable() < sizeof(quint16))
break;
in >> m_nNextBlockSize;
}
if (clientSocket->bytesAvailable() < m_nNextBlockSize)
break;
QTime time;
QString str="";
in >> time >> str;
QByteArray ba = str.toLatin1(); // переводим QString
char *str2 = ba.data(); // в char
m_nNextBlockSize=0;
strcat(str2, "\r");
temp_com->writeToPort(str2);
                sendToClient(clientSocket, temp_com->getQba());
}
}

И так. Объясняю, в чем смысл. На серверный сокет приходит из другого приложения команда. Естественно, при приходе этой команды вызывается слот slotReadClient(). В нем происходит прием команды, далее к команде добавляется "\r" и она передается оборудованию, который висит на COM-порту (с помощью метода temp_com->writeToPort(...)).
Когда COM-порт получает эту команду, он передает ее оборудованию, и оно отвечает также на COM-порт. Необходимо этот ответ словить и выдать обратно на сокет clientSocket, чтобы приложение, которое послало команду, получило ответ.
Естественно, сразу после строчки
Код:
temp_com->writeToPort(str2);
писать следующее:
Код:
sendToClient(clientSocket, temp_com->getQba());
нельзя, так как COM-порт еще не успеет выполнить всю свою работу, и получится, что я отправлю по сокету пустой ответ. (Но по крайней этот код выполняется без ошибок, просто не делает то, что мне надо)

Поэтому я сделал решил попробовать сделать так:
Код:
void ServerSocket::slotReadClient()
{

// код без изменений

timer = new QTimer(this);
connect(timer, SIGNAL(timeout()), SLOT(slotSendToClient()));
temp_com->writeToPort(str2);
timer->start(2000);
}
}

И в слоте slotSendToClient()
Код:
void ServerSocket::slotSendToClient()
{
timer->stop();
delete timer;
sendToClient(clientSocket, temp_com->getQba());
}

Т.е. идея ясна: сделать небольшую задержку, которая позволит отработать COM-порту, и только потом выслать ответ на сокет (это по сути должно обеспечить то, что ответ будет не пустой).
НО! При вызове
Код:
sendToClient(clientSocket, temp_com->getQba());
внутри слота
Код:
slotSendToClient()
возникает необработанное исключение. Я понял, что именно из-за этой строчки когда закомментировал ее и исключения не получил. try catch на этой строчке исключение не ловит (да и вообще, NOKIA вроде как не рекомендует использовать исключения в QT). Еще раз повторюсь, что исключения не происходит, если вызывать sendToClient не из слота slotSendToClient. В чем причина такого поведения?...
Записан
niklep
Гость
« Ответ #1 : Апрель 26, 2011, 23:28 »

При оформлении темы в код слота slotReadClient() закралась ошибка в виде лишней закрывающей скобки, не обращайте внимания.
Записан
Ubuntu_linux
Гость
« Ответ #2 : Апрель 27, 2011, 00:35 »

Может не по таймеру ждать, а ловить сигнал ReadyRead() c COM порта? Так будет более правильно.
« Последнее редактирование: Апрель 27, 2011, 00:37 от Ubuntu_linux » Записан
niklep
Гость
« Ответ #3 : Апрель 27, 2011, 12:55 »

Действительно, ночь не лучшая пора для генерации идей=) Переделал код, теперь таймера нет. Ловлю сигнал от порта. Примерно так:
Код:
мoid ServerSocket::slotReadClient()
{
connect(temp_com->port, SIGNAL(readyRead()), this, SLOT(slotReadCom()));

QTcpSocket* clientSocket = (QTcpSocket*)sender();
QDataStream in(clientSocket);
in.setVersion(QDataStream::Qt_4_5);
for (;;)
{
if (!m_nNextBlockSize)
{
if (clientSocket->bytesAvailable() < sizeof(quint16))
break;
in >> m_nNextBlockSize;
}
if (clientSocket->bytesAvailable() < m_nNextBlockSize)
break;
QTime time;
QString str="";
in >> time >> str;
QByteArray ba = str.toLatin1(); // переводим QString
char *str2 = ba.data(); // в char

qDebug() << "STR2: " << "'" << str2 << "'";
qDebug() << "BA: " << "'" << ba << "'";
m_nNextBlockSize=0;
strcat(str2, "\r");

temp_com->writeToPort(str2);
}
}

Код:
void ServerSocket::slotReadCom()
{
qba = temp_com->readFromPort();
qDebug() << "Slot Read: " << qba;
qDebug() << "Count of bytes Readed: " << qba.size();
sendToClient(clientSocket, qba);
qba.clear();
}

Код:
QByteArray ComHandler::readFromPort()
{
return port->readAll();
}

Код:
void ComHandler::writeToPort(const char *str)
{
qint64 bw = 0; //count of bytes really writed
bw = port->write(str);
qDebug() << "Count of bytes writed: " << "'" << bw << "'" << "\n";
qDebug() << "Writed info: " << "'" << str << "'";
str="";
}

И опять при отправке данных через
Код:
sendToClient(clientSocket, qba);
(см. слот ServerSocket::slotReadCom()) вылазит необработанное исключение. При этом если на сокет обратно ответ не посылать, а просто просматривать инфу через отладочный вывод в данном приложении, можно сделать вывод, что все работает. Кроме отправки по сокету ответа... В чем трабл?
Записан
niklep
Гость
« Ответ #4 : Апрель 29, 2011, 08:28 »

Проблема решилась. Учитывая, что у меня clientSocket прописан как поле в классе, необходимо было его инициализировать иначе. Я делал:
Код:
QTcpSocket* clientSocket = (QTcpSocket*)sender();
А надо было:
Код:
clientSocket = (QTcpSocket*)sender();
Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


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