C++ QLocalSocket真的用于命名管道吗
根据th Qt文档,如果我们想在windows上使用命名管道,我们可以使用QLocalSocket。 我正在用Qt编写一个服务器和客户端程序。如果我尝试使用WIN32 API在管道中写入一些消息,Qt客户端不会显示它。此外,如果客户端再次使用WIN32 API进行写入,则Qt服务器不会回显发送的消息。是否真的建议命名管道使用QLocalSocket 这是Win32服务器代码C++ QLocalSocket真的用于命名管道吗,c++,qt,qt5,qlocalsocket,C++,Qt,Qt5,Qlocalsocket,根据th Qt文档,如果我们想在windows上使用命名管道,我们可以使用QLocalSocket。 我正在用Qt编写一个服务器和客户端程序。如果我尝试使用WIN32 API在管道中写入一些消息,Qt客户端不会显示它。此外,如果客户端再次使用WIN32 API进行写入,则Qt服务器不会回显发送的消息。是否真的建议命名管道使用QLocalSocket 这是Win32服务器代码 wcout << "Creating an instance of a named pipe..."
wcout << "Creating an instance of a named pipe..." << endl;
// Create a pipe to send data
HANDLE pipe = CreateNamedPipeW(
L"\\\\.\\pipe\\ServicePipe", // name of the pipe
PIPE_ACCESS_OUTBOUND, // 1-way pipe -- send only
PIPE_TYPE_BYTE, // send data as a byte stream
100, // only allow 1 instance of this pipe
0, // no outbound buffer
0, // no inbound buffer
0, // use default wait time
NULL // use default security attributes
);
if (pipe == NULL || pipe == INVALID_HANDLE_VALUE) {
wcout << "Failed to create outbound pipe instance.";
// look up error code here using GetLastError()
system("pause");
return 1;
}
wcout << "Waiting for a client to connect to the pipe..." << endl;
// This call blocks until a client process connects to the pipe
BOOL result = ConnectNamedPipe(pipe, NULL);
if (!result) {
wcout << "Failed to make connection on named pipe." << endl;
// look up error code here using GetLastError()
CloseHandle(pipe); // close the pipe
system("pause");
return 1;
}
wcout << "Sending data to pipe..." << endl;
// This call blocks until a client process reads all the data
wcout <<endl<<"Input your message: ";
wstring data=L"";
getline(wcin,data);
DWORD numBytesWritten = 0;
result = WriteFile(
pipe, // handle to our outbound pipe
data.c_str(), // data to send
wcslen(data.c_str()) * sizeof(wchar_t), // length of data to send (bytes)
&numBytesWritten, // will store actual amount of data sent
NULL // not using overlapped IO
);
if (result) {
wcout << "Number of bytes sent: " << numBytesWritten << endl;
} else {
wcout << "Failed to send data." << endl;
// look up error code here using GetLastError()
}
// Close the pipe (automatically disconnects client too)
CloseHandle(pipe);
wcout << "Done." << endl;
wcout不必通读所有代码,我可以肯定地回答这个问题。下面是一个工作应用程序中的一些代码,它从一个Qt应用程序写入另一个Qt应用程序中的命名管道(它还原另一个最小化的应用程序):
要还原的应用程序设置如下:
localServer = new QLocalServer(this);
connect(localServer, SIGNAL(newConnection()), this,
SLOT(messageFromOtherInstance()));
localServer->listen("Restore Server");
当需要阅读信息时,我会这样做:
QLocalSocket *localSocket = localServer->nextPendingConnection();
if (!localSocket->waitForReadyRead(5000))
{
qDebug(localSocket->errorString().toLatin1());
return;
}
QByteArray byteArray = localSocket->readAll();
QString message = QString::fromUtf8(byteArray.constData());
if (message == "raise")
bringToTop(this);
很可能Qt命名管道和M$命名管道在某种程度上不兼容。我建议编写一个M$framework应用程序来写入M$framework客户端,并编写一个M$framework应用程序来读取,以确保它们都正常工作。然后,替换一个Qt应用程序从Qt服务器读取数据。如果这不起作用,那就是某种框架不兼容(尽管我希望它们都能正确地与操作系统交互)。在这种情况下需要确保的一件事是确保进程不会阻塞。这就是为什么我在阅读之前要确保阅读准备就绪。在M$side上写下之后,您可能还需要冲洗管道,尽管我没有使用Qt
(请注意,我后来发现,如果“打印”、“打印预览”、“页面设置”或“浏览文件”对话框打开,它将停止Qt消息循环,应用程序将对此类消息无响应。选择字体对话框OTOH不会阻止父应用程序。如图所示。)测试使用的是哪个版本的Windows?是指定命名管道文件的完整路径,还是仅使用文件名?如果只是文件名,可能就是找不到管道。我使用完整路径(\\.\pipe\ServicePipe)Win32代码是如何读取和写入的QLocalServer
使用CreateNamedPipeW(…管道类型{U字节}管道读取模式{U字节}管道等待…)创建管道
和QLocalSocket
连接CreateFileW(…通用{READ,WRITE},打开现有…
)。Qt为异步I/O打开管道(文件标志重叠
)。这意味着您对ConnectNamedPipe
的调用失败(您没有传递有效的OVERLAPPED
结构)。同样,您正在本机Windows代码中创建同步I/O管道,但Qt尝试以异步模式连接到它。您必须使用匹配设置。
LocalSocketIpcClient::LocalSocketIpcClient(QString remoteServername, QObject *parent) :
QObject(parent) {
m_socket = new QLocalSocket(this);
m_serverName = remoteServername;
connect(m_socket, SIGNAL(connected()), this, SLOT(socket_connected()));
connect(m_socket, SIGNAL(disconnected()), this, SLOT(socket_disconnected()));
connect(m_socket, SIGNAL(readyRead()), this, SLOT(socket_readReady()));
connect(m_socket, SIGNAL(error(QLocalSocket::LocalSocketError)),
this, SLOT(socket_error(QLocalSocket::LocalSocketError)));
}
LocalSocketIpcClient::~LocalSocketIpcClient() {
m_socket->abort();
delete m_socket;
m_socket = NULL;
}
QString LocalSocketIpcClient::Read()
{
QDataStream in(this->m_socket);
in.setVersion(QDataStream::Qt_5_1);
if (m_socket->bytesAvailable() < (int)sizeof(quint16)) {
return "No data available";
}
QString message;
in >> message;
return message;
}
void LocalSocketIpcClient::send_MessageToServer(QString message) {
m_socket->abort();
m_message = message;
m_socket->connectToServer(m_serverName,QIODevice::ReadWrite);
}
void LocalSocketIpcClient::socket_connected(){
QByteArray block;
QDataStream out(&block, QIODevice::ReadWrite);
out.setVersion(QDataStream::Qt_5_1);
out << m_message;
out.device()->seek(0);
m_socket->write(block);
m_socket->flush();
}
void LocalSocketIpcClient::socket_disconnected() {
//showMessage("Client socket_disconnected");
}
void LocalSocketIpcClient::socket_readReady() {
//showMessage("Client socket read Ready");
QDataStream in(this->m_socket);
in.setVersion(QDataStream::Qt_5_1);
if (m_socket->bytesAvailable() < (int)sizeof(quint16)) {
return;
}
QString message;
in >> message;
emit RecievedDataFromServer(message);
}
void LocalSocketIpcClient::socket_error(QLocalSocket::LocalSocketError e) {
/*
QString errorMessage="Client socket_error:";
switch (e) {
case QLocalSocket::ConnectionRefusedError:
errorMessage+="The connection was refused by the peer (or timed out).";
break;
case QLocalSocket::PeerClosedError:
errorMessage+="The remote socket closed the connection. Note that the client socket (i.e., this socket) will be closed after the remote close notification has been sent.";
break;
case QLocalSocket::ServerNotFoundError:
errorMessage+="The local socket name was not found.";
break;
case QLocalSocket::SocketAccessError:
errorMessage+="The socket operation failed because the application lacked the required privileges.";
break;
case QLocalSocket::SocketResourceError:
errorMessage+="The local system ran out of resources (e.g., too many sockets).";
break;
case QLocalSocket::SocketTimeoutError:
errorMessage+="The socket operation timed out.";
break;
case QLocalSocket::DatagramTooLargeError:
errorMessage+="The datagram was larger than the operating system's limit (which can be as low as 8192 bytes).";
break;
case QLocalSocket::ConnectionError:
errorMessage+="An error occurred with the connection.";
break;
case QLocalSocket::UnsupportedSocketOperationError:
errorMessage+="The requested socket operation is not supported by the local operating system.";
break;
case QLocalSocket::UnknownSocketError:
errorMessage+="An unidentified error occurred.";
break;
default:
break;
}
showMessage(errorMessage);
*/
}
void LocalSocketIpcClient::showMessage(QString msg)
{
QMessageBox m;
m.setText(msg);
m.exec();
}
LocalSocketIpcClient::SingleMessageSend(QWidget *parent) :
QDialog(parent),
ui(new Ui::SingleMessageSend)
{
ui->setupUi(this);
client = new LocalSocketIpcClient("\\\\.\\pipe\ServicePipe", this);
connect(this->client,SIGNAL(RecievedDataFromServer(QString)),this,SLOT(UpdateGUI(QString)));
}
LocalSocketIpcClient::~SingleMessageSend()
{
delete ui;
}
void SingleMessageSend::on_pushButton_clicked()
{
QString msg=this->ui->lineEdit->text().trimmed();
client->send_MessageToServer(msg);
}
void SingleMessageSend::UpdateGUI(QString message)
{
ui->textEdit->insertPlainText(message+"\n");
}
void SingleMessageSend::on_pushButton_2_clicked()
{
ui->textEdit->insertPlainText(client->Read()+QString("\n"));
}
QLocalSocket ls;
ls.connectToServer("Restore Server", QIODevice::WriteOnly);
if (!ls.waitForConnected(5000))
{
qDebug(ls.errorString().toUtf8());
return false;
}
ls.write("raise");
if (!ls.waitForBytesWritten(5000))
{
qDebug(ls.errorString().toUtf8());
return false;
}
ls.disconnectFromServer();
localServer = new QLocalServer(this);
connect(localServer, SIGNAL(newConnection()), this,
SLOT(messageFromOtherInstance()));
localServer->listen("Restore Server");
QLocalSocket *localSocket = localServer->nextPendingConnection();
if (!localSocket->waitForReadyRead(5000))
{
qDebug(localSocket->errorString().toLatin1());
return;
}
QByteArray byteArray = localSocket->readAll();
QString message = QString::fromUtf8(byteArray.constData());
if (message == "raise")
bringToTop(this);