我正在使用QLocalSocket和QLocalServer在Windows 7上使用VS 2010和Qt 5.5.1进行进程间通信。
向另一个进程发送超过256条消息后,CIPSocket中的析构函数冻结。我将问题追溯到qtbase \ src \ corelib \ ioqwinoverlappedionotifier.cpp中的信号槽问题,其中通知中发出的信号_q_notify()(DWORD numberOfBytes,DWORD errorCode,OVERLAPPED *重叠)不会导致调用_q_notified() 。因此,信号量hSemaphore超出其最大计数,导致析构函数死锁。
信号槽无法正常工作的原因是什么?我找不到任何断开连接或阻塞信号。
提前致谢。
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
答案 0 :(得分:1)
由于事件循环未运行而发生错误。启动QCoreApplication启动事件循环,但等待应用程序退出。因此,发送必须在另一个线程中完成。 附加的代码显示正确的用法。
main.cpp中:
#include "main.h"
int main(int argc, char *argv[])
{
QCoreApplication app(argc, argv);
printf("Server (0) or Socket (1)?\n");
char c = getchar();
if (c == '0') {
CIPServer server;
QCoreApplication::exec();
}
else if (c == '1') {
CIPSocket socket;
CSender sender(500);
QObject::connect(&sender, SIGNAL(sendMessage(int)), &socket, SLOT(update(int)));
QObject::connect(&sender, SIGNAL(allMessagesSent()), &socket, SLOT(close()));
sender.start();
QCoreApplication::exec();
}
}
/*--------------------------------------------------------------------------
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; }
void CIPSocket::close()
{ QCoreApplication::exit(); }
/*--------------------------------------------------------------------------
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()));
connect(m_pConnection, SIGNAL(disconnected()), this, SLOT(close()));
}
void CIPServer::update()
{
if (m_pConnection->bytesAvailable() >= 4) {
int i;
m_stream >> i;
qDebug() << i;
}
}
void CIPServer::close()
{ QCoreApplication::exit(); }
/*--------------------------------------------------------------------------
CSender
----------------------------------------------------------------------------*/
CSender::CSender(int iNumMessages)
: m_iNumMessages(iNumMessages)
{}
CSender::~CSender()
{}
void CSender::run()
{
while (m_iNumMessages > 0) {
emit sendMessage(m_iNumMessages);
msleep(10);
m_iNumMessages--;
}
emit allMessagesSent();
}
main.h:
#include <QtNetwork/QLocalServer>
#include <QtNetwork/QLocalSocket>
#include <QtCore/QDataStream>
#include <QtCore/QThread>
#include <QtCore/QCoreApplication>
/// \brief Creates a socket for inter-process communication
class CIPSocket
: public QObject
{
Q_OBJECT;
public:
/// Constructor
CIPSocket();
/// Destructor
virtual ~CIPSocket();
public slots:
/// Enables updating
void connectionReady();
/// Disables updating
void connectionLost();
/// Send the data
void update(int i);
/// Close the application
void close();
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();
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();
/// Close the application
void close();
private:
/// The currently connected socket
QLocalSocket* m_pConnection;
/// The incoming stream
QDataStream m_stream;
};
/// \brief Sends the messages via CIPSocket
class CSender
: public QThread
{
Q_OBJECT;
public:
/// Constructor
CSender(int iNumMessages);
/// Destructor
virtual ~CSender();
/// Sends the requestet number of messages in 10 ms steps
virtual void run();
signals:
/// Sends the message via the CIPSocket
void sendMessage(int);
/// Informs about all messages being sent
void allMessagesSent();
private:
/// The number of messages to send
int m_iNumMessages;
};
答案 1 :(得分:0)
该程序在编程时运行良好:尝试以下方法:
启动服务器 - 启动客户端,发送数据 - 服务器接收数据 - 停止客户端 - 再次启动客户端,发送数据 - 服务器接收数据......
该程序没有死锁,也没有冻结!该程序正在等待第13行的Qt eventloop中的事件:
app.exec();
问题是:它该怎么办?
我假设你想在下班后退出程序,然后插入:
void CIPServer::socketConnected()
{ . . .
connect(m_pConnection, SIGNAL(disconnected()), this, SLOT(theend()));
}
void CIPServer::theend()
{
QCoreApplication::quit();
}
尝试以下操作: 启动服务器 - 启动客户端,发送数据 - 服务器接收数据 - 停止客户端 - 服务器也停止