【发布时间】:2016-07-05 10:10:04
【问题描述】:
我正在使用 QLocalSocket 和 QLocalServer 在 Windows 7 上使用 VS 2010 和 Qt 5.5.1 进行进程间通信。
在向其他进程发送超过 256 条消息后,CIPSocket 中的析构函数冻结。我将问题追溯到 qtbase\src\corelib\ioqwinoverlappedionotifier.cpp 中的信号槽问题,其中在 notify(DWORD numberOfBytes, DWORD errorCode, OVERLAPPED *overlapped) 中发出的信号 _q_notify() 不会导致调用 _q_notified() .因此 Semaphore hSemaphore 超过了它的 max-count,导致析构函数死锁。
信号槽不工作的原因可能是什么?我找不到任何断开连接或阻塞信号。
提前致谢。
main.cpp:
#include "main.h"
#include <QtCore/QCoreApplication>
#include <QtCore/QThread>
#include <iostream>
int main(int argc, char *argv[])
{
printf("Server (0) or Socket (1)?\n");
char c = getchar();
if (c == '0') {
QCoreApplication app(argc, argv);
CIPServer server;
app.exec();
}
else if (c == '1') {
CIPSocket socket;
for (unsigned int i = 0; i <= 256; ++i) {
socket.update(i);
QThread::msleep(10);
}
}
}
/*--------------------------------------------------------------------------
CIPSocket
----------------------------------------------------------------------------*/
CIPSocket::CIPSocket()
: m_bIsReady(false)
{
m_pSocket = new QLocalSocket(this);
m_stream.setDevice(m_pSocket);
connect(m_pSocket, SIGNAL(connected()), this, SLOT(connectionReady()));
connect(m_pSocket, SIGNAL(disconnected()), this, SLOT(connectionLost()));
m_pSocket->connectToServer("DemoServer");
}
CIPSocket::~CIPSocket()
{
delete m_pSocket;
m_pSocket = NULL;
}
void CIPSocket::update(int i)
{
if (m_bIsReady)
m_stream << i;
}
void CIPSocket::connectionReady()
{ m_bIsReady = true; }
void CIPSocket::connectionLost()
{ m_bIsReady = false; }
/*--------------------------------------------------------------------------
CIPServer
----------------------------------------------------------------------------*/
CIPServer::CIPServer(QObject* parent)
: QLocalServer(parent)
{
if (!listen("DemoServer")) {
throw ("Could not connect to 'DemoServer'");
}
connect(this, SIGNAL(newConnection()), this, SLOT(socketConnected()));
}
CIPServer::~CIPServer()
{}
void CIPServer::socketConnected()
{
qDebug() << "Connected";
m_pConnection = nextPendingConnection();
m_stream.setDevice(m_pConnection);
connect(m_pConnection, SIGNAL(disconnected()), m_pConnection, SLOT(deleteLater()));
connect(m_pConnection, SIGNAL(readyRead()), this, SLOT(update()));
}
void CIPServer::update()
{
if (m_pConnection->bytesAvailable() >= 4) {
int i;
m_stream >> i;
qDebug() << i;
}
}
main.h:
#include <QtNetwork/QLocalServer>
#include <QtNetwork/QLocalSocket>
#include <QtCore/QDataStream>
#include <QtCore/QThread>
/// \brief Creates a socket for inter-process communication
class CIPSocket
: public QObject
{
Q_OBJECT;
public:
/// Constructor
CIPSocket();
/// Destructor
virtual ~CIPSocket();
/// Send the data
void update(int i);
public slots:
/// Enables updating
void connectionReady();
/// Disables updating
void connectionLost();
private:
/// The target stream
QDataStream m_stream;
/// The socket connecting to server
QLocalSocket* m_pSocket;
/// Indicates if the socket is connected
bool m_bIsReady;
};
/// \brief Creates a server for inter-process communication
class CIPServer
: public QLocalServer
{
Q_OBJECT;
public:
/// Constructor
CIPServer(QObject* parent = NULL);
/// Destructor
virtual ~CIPServer();
/// Starts the server
void start();
private slots:
/// Connects the socket to the stream and to the update function
void socketConnected();
/// Reads the data from the stream and emits a the results
void update();
private:
/// The currently connected socket
QLocalSocket* m_pConnection;
/// The incoming stream
QDataStream m_stream;
};
demo.pro:
CONFIG += qt debug
QT += network
HEADERS += main.h
SOURCES += main.cpp
CONFIG += console
【问题讨论】:
-
我试图重现您的示例,但由于未知的 CSocketThread,它无法编译。
-
抱歉,我忘了删除一些额外的代码。现在应该可以编译了。
-
一些想法:尝试
bool QLocalSocket::flush().. 可能你的一些数据卡在内部缓冲区中。另外,也许调整您的代码以使用bool QLocalSocket::waitForBytesWritten(int msecs = 30000) -
@Derick Schoonbee:我试过这个,但没有成功。数据传输正确。如上所述,问题在于 qtbase\src\corelib\ioqwinoverlappedionotifier.cpp 中的信号量溢出,因为异步通信的工件没有被删除,因为没有调用连接的插槽来执行此操作。问题是为什么没有调用连接的插槽。
-
@Roland:已经报告给 Qt:bugreports.qt.io/browse/QTBUG-54567。我以为我可能忘记了对套接字的一些准备工作,但似乎问题出在 Qt 上。
标签: c++ qt networking signals-slots