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

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

Страниц: [1]   Вниз
  Печать  
Автор Тема: pipe каналы  (Прочитано 2899 раз)
Firefox
Гость
« : Июль 19, 2011, 23:42 »

добрый день. вот начала разбираться с pipe каналами между двумя программами. я делаю это на одном компе не по сети.  написала 2 класса один подключается к программе 1 она будет сервером, второй к программе 2 она будет клиентом. написала отдельными классами, так как у каждой программы есть свое предназначение и создание каналов служит лишь для обмена данными. столкнулась с такой проблемой: если при создании канала пользоваться флагом PIPE_WAIT, то виснет вся программа(даже форму не развернуть), но данные по каналу передаются, если же флагом PIPE_NOWAIT, то никак не конектится клиент к серверу. вот программы
Код:
//СЕРВЕР
//.h
#include <QtGui/QMainWindow>
#include "ui_server_pipe.h"
#include <QTimer>
#include <QString>
#include <QThread>
class channel: public QThread  {
Q_OBJECT
public:
channel();
~channel();
QTimer *tpipe;
void run();
void createChannel();
void writeChannel();
private slots:
void readChannel();


};

//.cpp
#include "channel.h"
#include <windows.h>
#include <stdio.h>
#include <conio.h>
#include <QTimer>

QString str;
// Флаг успешного создания канала
BOOL   fConnected;

// Идентификатор канала Pipe
HANDLE hNamedPipe;

// Имя создаваемого канала Pipe
LPCTSTR  lpszPipeName =L"\\\\.\\pipe\\$MyPipe$";

// Буфер для передачи данных через канал
char   szBuf[512];

// Количество байт данных, принятых через канал
DWORD  cbRead;
// Количество байт данных, переданных через канал
DWORD  cbWritten;
bool flag=0,flag_exit=0;

channel::channel()
{




}
channel::~channel()
{
DisconnectNamedPipe(hNamedPipe);
CloseHandle(hNamedPipe);
}
void channel::createChannel()
{



metka: ;
// Создаем канал Pipe, имеющий имя lpszPipeName
hNamedPipe = CreateNamedPipe(
lpszPipeName,
PIPE_ACCESS_DUPLEX,
PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_NOWAIT,
PIPE_UNLIMITED_INSTANCES,
512, 512, 10000, NULL);

// Если возникла ошибка, выводим ее код и завершаем
// работу приложения
if(hNamedPipe == INVALID_HANDLE_VALUE)
{
str+="CreateNamedPipe: Error %ld\n"+GetLastError();
fprintf(stdout,"CreateNamedPipe: Error %ld\n",
GetLastError());
getch();
goto metka;
}

// Выводим сообщение о начале процесса создания канала

fprintf(stdout,"Waiting for connect...\n");

tpipe->start(500);
exec();

}
void channel::readChannel()
{
bool flag_read=false;
if(!fConnected)
// Ожидаем соединения со стороны клиента
fConnected = ConnectNamedPipe(hNamedPipe, NULL);

// При возникновении ошибки выводим ее код
if(!fConnected)
{
flag_read=1;
//switch(GetLastError())
//{
//case ERROR_NO_DATA:
// str+="ConnectNamedPipe: ERROR_NO_DATA";
// //uicl->textEdit->setText(str);
// //fprintf(stdout,"ConnectNamedPipe: ERROR_NO_DATA");
// flag_read=1;
//// getch();
//// CloseHandle(hNamedPipe);
//// return;
// break;

//case ERROR_PIPE_CONNECTED:
// str+="ConnectNamedPipe: ERROR_PIPE_CONNECTED";
//
// //uicl->textEdit->setText(str);
// //fprintf(stdout,"ConnectNamedPipe: ERROR_PIPE_CONNECTED");
// flag_read=1;
// //getch();
// //return;
// break;

//case ERROR_PIPE_LISTENING:
// //str+="ConnectNamedPipe: ERROR_PIPE_LISTENING";
// //ui.textEdit->setText(str);
// //fprintf(stdout,"ConnectNamedPipe: ERROR_PIPE_LISTENING");
// flag_read=1;
// //getch();
// //CloseHandle(hNamedPipe);
// //return;
// break;

//case ERROR_CALL_NOT_IMPLEMENTED:
// str+="ConnectNamedPipe: ERROR_CALL_NOT_IMPLEMENTED";
// //uicl->textEdit->setText(str);
//// fprintf(stdout,"ConnectNamedPipe: ERROR_CALL_NOT_IMPLEMENTED");
// flag_read=1;
//// getch();
// //CloseHandle(hNamedPipe);
// //return;
// break;

//default:
// str+="ConnectNamedPipe: Error %ld\n"+GetLastError();
// // ui.textEdit->setText(str);
//// fprintf(stdout,"ConnectNamedPipe: Error %ld\n", GetLastError());
// flag_read=1;
//// getch();
// //CloseHandle(hNamedPipe);
//// return;
// break;
//}
//CloseHandle(hNamedPipe);
//getch();
//return;
}


// Цикл получения команд через канал
if(flag_read==false)
{

if(flag==0)
{

flag=1;
}
                // Выводим сообщение об успешном создании канала
fprintf(stdout,"\nConnected. Waiting for command...\n");
QString last_command="";
// Получаем очередную команду через канал Pipe
if(ReadFile(hNamedPipe, szBuf, sizeof(szBuf), &cbRead, NULL))
{

for (int i=0;i<512 && szBuf[i]!='\0';i++)
{

last_command+=szBuf[i];

}

fprintf(stdout,/*"Received:\n"*/szBuf);

if(last_command=="exit")
{
exit();
flag_exit=1;
}
else flag_exit=0;
}
else
{

fprintf(stdout,"ReadFile: Error %ld\n #330033", GetLastError());
getch();
}
if(flag_exit==1)
{
szBuf[0]='c';
szBuf[1]='l';
szBuf[2]='o';
szBuf[3]='s';
szBuf[4]='e';
for (int i=5;i<512;i++) szBuf[i]='\0';
WriteFile(hNamedPipe, szBuf, strlen(szBuf) + 1,&cbWritten, NULL);
}
}
}
void channel::run()
{
tpipe= new QTimer();
connect(tpipe,SIGNAL(timeout()),SLOT(readChannel()));
createChannel();         
}


//КЛИЕНТ
//.h
#include <QString>
#include <windows.h>
#include <stdio.h>
#include <conio.h>
#include <QTimer>
#include <QThread>

class chanel_pipe: public QThread
{
Q_OBJECT
public:
chanel_pipe();
~chanel_pipe();
QTimer *Ttime;
void run();
bool read_chanel();
void write_chanel(char string_ch[20]);

protected:
private slots:
void slot_read();
};
 // .cpp
#include "chanel_pipe.h"

// Идентификатор канала Pipe
HANDLE hNamedPipe;

// Количество байт, переданных через канал
DWORD  cbWritten;

// Количество байт, принятых через канал
DWORD  cbRead;

// Буфер для передачи данных
char   szBuf[256];

chanel_pipe::chanel_pipe()
{

// Создаем канал с процессом PIPES
hNamedPipe = CreateFile(
L"\\\\.\\pipe\\$MyPipe$", GENERIC_READ | GENERIC_WRITE,
0, NULL, OPEN_EXISTING, 0, NULL);

// Если возникла ошибка, выводим ее код и
// завершаем работу приложения
if(hNamedPipe == INVALID_HANDLE_VALUE)
{
fprintf(stdout,"CreateFile: Error %ld\n",
GetLastError());
getch();
}

}
chanel_pipe::~chanel_pipe()
{

}
bool chanel_pipe::read_chanel()
{
if(!hNamedPipe)
{
// Создаем канал с процессом PIPES
hNamedPipe = CreateFile(
L"\\\\.\\pipe\\$MyPipe$", GENERIC_READ | GENERIC_WRITE,
0, NULL, OPEN_EXISTING, 0, NULL);

// Если возникла ошибка, выводим ее код и
// завершаем работу приложения
if(hNamedPipe == INVALID_HANDLE_VALUE)
{
fprintf(stdout,"CreateFile: Error %ld\n",
GetLastError());
getch();
}
}

bool rez=ReadFile(hNamedPipe, szBuf, strlen(szBuf)+1, &cbRead, NULL);
QString str;
for(int i=0;i<512;i++)str=str+szBuf[i];
if(str=="exit")
{
return 0;
}
return 1;
}
void chanel_pipe::write_chanel(char string_ch[20])
{
if(!hNamedPipe)
{
// Создаем канал с процессом PIPES
hNamedPipe = CreateFile(
L"\\\\.\\pipe\\$MyPipe$", GENERIC_READ | GENERIC_WRITE,
0, NULL, OPEN_EXISTING, 0, NULL);

// Если возникла ошибка, выводим ее код и
// завершаем работу приложения
if(hNamedPipe == INVALID_HANDLE_VALUE)
{
fprintf(stdout,"CreateFile: Error %ld\n",
GetLastError());
getch();
}
else
WriteFile(hNamedPipe, string_ch, strlen(string_ch) + 1,
&cbWritten, NULL);
}
else
WriteFile(hNamedPipe, string_ch, strlen(string_ch) + 1,
&cbWritten, NULL);
}
void chanel_pipe::slot_read()
{
bool rr=false;
if(hNamedPipe)
rr=read_chanel();
}
void chanel_pipe::run()
{
Ttime=new QTimer;
connect(Ttime,SIGNAL(timeout()),this,SLOT(slot_read()));
Ttime->start(500);
exec();
}

получается что если флаг PIPE_WAIT то при чтении с канала до следующего чтения блокируется все. как это можно изменить не знаю. или как так сделать чтою клиент смог подключиться без использования ожтдания. вроде классы создала в отдельном потоке а всеравно основной тоже грузиться. я только начала каналы изучать буду рада помощи.
Записан
LisandreL
Птица говорун
*****
Offline Offline

Сообщений: 984


Надо улыбаться


Просмотр профиля
« Ответ #1 : Июль 20, 2011, 06:43 »

goto metka;
http://xkcd.ru/292/

если при создании канала пользоваться флагом PIPE_WAIT
Потоки запускаете, разумеется, через run(), а не через start?

P.S. Да и вообще есть QLocalSocket + QLocalServer. Зачем изобретать велосипед на WinAPI?
Цитировать
On Windows this is a named pipe and on Unix this is a local domain socket.
Записан
Firefox
Гость
« Ответ #2 : Июль 20, 2011, 09:34 »

запускаю конечно через start(). ну раз уж начала таким путем то хочется его все же разобрать. да и на работе стоит qt 4.3.3 и там как я посмотрела в хелпе нет этих классов.
« Последнее редактирование: Июль 20, 2011, 09:35 от Firefox » Записан
Firefox
Гость
« Ответ #3 : Июль 20, 2011, 11:19 »

вот немного поразбиралась с асинхронным режимом передачи. получилось следующее, но всеравно не конектится:
Код:
// СЕРВЕР
//.h
#include <QtGui/QMainWindow>
#include "ui_server_pipe.h"
#include <windows.h>
#include <stdio.h>
#include <conio.h>
#include <QTimer>
#include <QString>
#include <QThread>
class channel: public QThread  {
Q_OBJECT
public:
channel();
~channel();
QTimer *tpipe;
OVERLAPPED StrOverlapp;
//Ui_server_pipeClass uicl;
void run();
void createChannel();
void writeChannel();
private slots:
void readChannel();


};
//.cpp
#include "channel.h"


QString str;
// Флаг успешного создания канала
BOOL   fConnected;
// Идентификатор события
HANDLE hEvent;

// Идентификатор канала Pipe
HANDLE hNamedPipe;

// Имя создаваемого канала Pipe
LPCTSTR  lpszPipeName =L"\\\\.\\pipe\\$MyPipe$";

// Буфер для передачи данных через канал
char   szBuf[512];

// Количество байт данных, принятых через канал
DWORD  cbRead;
// Количество байт данных, переданных через канал
DWORD  cbWritten;
bool flag=0,flag_exit=0;

Ui_server_pipeClass uicl;
channel::channel()
{

}
channel::~channel()
{
DisconnectNamedPipe(hNamedPipe);
CloseHandle(hNamedPipe);
}
void channel::createChannel()
{

hEvent=CreateEvent(NULL,FALSE,FALSE, NULL);
StrOverlapp.hEvent=hEvent;
StrOverlapp.Offset=0; // TRANSFER HANDLE TEST >!
StrOverlapp.OffsetHigh=0;

while(!hNamedPipe)
{
// Создаем канал Pipe, имеющий имя lpszPipeName
hNamedPipe = CreateNamedPipe(
lpszPipeName, // имя канала.
PIPE_ACCESS_DUPLEX |FILE_FLAG_OVERLAPPED , /*асинхрон*/
PIPE_TYPE_MESSAGE,
10, // максимальное количество экземпляров канала.
512, // размер выходного буфера по умолчанию.
512, // рахмер входного буфера по умолчанию.
INFINITE, // клиент ждет связь бесконечно долго.
NULL // безопасность по умолчанию.
);

// Если возникла ошибка, выводим ее код и завершаем
// работу приложения
if(hNamedPipe == INVALID_HANDLE_VALUE)
{
str+="CreateNamedPipe: Error %ld\n"+GetLastError();
fprintf(stdout,"CreateNamedPipe: Error %ld\n",
GetLastError());
}
}
// Выводим сообщение о начале процесса создания канала
str+="Waiting for connect...\n";
fprintf(stdout,"Waiting for connect...\n");
tpipe->start(50);
exec();
}
void channel::readChannel()
{
bool flag_read=false;
if(!fConnected)
// Ожидаем соединения со стороны клиента
fConnected = ConnectNamedPipe(hNamedPipe, &StrOverlapp);

// При возникновении ошибки выводим ее код
if(!fConnected)
{
flag_read=1;
}


// Цикл получения команд через канал
if(flag_read==false)
{
// Выводим сообщение об успешном создании канала
fprintf(stdout,"\nConnected. Waiting for command...\n");
QString last_command="";
// Получаем очередную команду через канал Pipe
if(ReadFile(hNamedPipe, szBuf, sizeof(szBuf), &cbRead, NULL))
{
for (int i=0;i<512 && szBuf[i]!='\0';i++)
{
str+=szBuf[i];
last_command+=szBuf[i];

}
fprintf(stdout,/*"Received:\n"*/szBuf);

if(last_command=="exit")
{
exit();
flag_exit=1;
}
else flag_exit=0;
}
else
{
fprintf(stdout,"ReadFile: Error %ld\n #330033", GetLastError());
getch();
}
if(flag_exit==1)
{
szBuf[0]='c';
szBuf[1]='l';
szBuf[2]='o';
szBuf[3]='s';
szBuf[4]='e';
for (int i=5;i<512;i++) szBuf[i]='\0';
WriteFile(hNamedPipe, szBuf, strlen(szBuf) + 1,&cbWritten, NULL);
}
}
}
void channel::run()
{
tpipe= new QTimer();
connect(tpipe,SIGNAL(timeout()),SLOT(readChannel()));
createChannel();         
}

// запуск из главного потока:
ch=new channel();
ch->start(QThread::HighPriority);


//КЛИЕНТ
//.h
#include <QString>
#include <windows.h>
#include <stdio.h>
#include <conio.h>
#include <QTimer>
#include <QThread>

class chanel_pipe: public QThread
{
Q_OBJECT
public:
chanel_pipe();
~chanel_pipe();
QTimer *Ttime;
OVERLAPPED OVL;
void run();
bool read_chanel();
void write_chanel(char string_ch[20]);

protected:
private slots:
void slot_read();
}; //.cpp
#include "chanel_pipe.h"

// Идентификатор канала Pipe
HANDLE hNamedPipe;
// Идентификатор события
HANDLE hEndWrite;
// Количество байт, переданных через канал
DWORD  cbWritten;

// Количество байт, принятых через канал
DWORD  cbRead;

// Буфер для передачи данных
char   szBuf[256];

chanel_pipe::chanel_pipe()
{

}
chanel_pipe::~chanel_pipe()
{

}
bool chanel_pipe::read_chanel()
{
if(!hNamedPipe)
{
// Создаем канал с процессом PIPES
hNamedPipe = CreateFile(
L"\\\\.\\pipe\\$MyPipe$", GENERIC_READ | GENERIC_WRITE,
0, NULL, OPEN_EXISTING, 0, NULL);

// Если возникла ошибка, выводим ее код и
// завершаем работу приложения
if(hNamedPipe == INVALID_HANDLE_VALUE)
{
fprintf(stdout,"CreateFile: Error %ld\n",
GetLastError());
getch();
}
}

bool rez=ReadFile(hNamedPipe, szBuf, strlen(szBuf)+1, &cbRead, NULL);
QString str;
for(int i=0;i<512;i++)str=str+szBuf[i];
if(str=="exit")
{
return 0;
}
return 1;
}
void chanel_pipe::write_chanel(char string_ch[20])
{
if(!hNamedPipe)
{
// Создаем канал с процессом PIPES
hNamedPipe = CreateFile(
L"\\\\.\\pipe\\$MyPipe$", GENERIC_READ | GENERIC_WRITE,
0, NULL, OPEN_EXISTING, 0, NULL);

// Если возникла ошибка, выводим ее код и
// завершаем работу приложения
if(hNamedPipe == INVALID_HANDLE_VALUE)
{
fprintf(stdout,"CreateFile: Error %ld\n",
GetLastError());
//getch();
}
else
WriteFile(hNamedPipe, string_ch, strlen(string_ch) + 1,
&cbWritten, NULL);
}
else
WriteFile(hNamedPipe, string_ch, strlen(string_ch) + 1,
&cbWritten, NULL);
}
void chanel_pipe::slot_read()
{
bool rr=false;
if(hNamedPipe)
rr=read_chanel();
}
void chanel_pipe::run()
{

hEndWrite=CreateEvent(NULL,FALSE,FALSE,NULL);
OVL.Offset=0;
OVL.OffsetHigh=0;
OVL.hEvent=hEndWrite;
//bool PRezWait=WaitNamedPipe( L"\\\\.\\pipe\\$MyPipe$", NMPWAIT_WAIT_FOREVER );
while(!hNamedPipe)
{
// Создаем канал с процессом PIPES
hNamedPipe=CreateFile(
L"\\\\.\\pipe\\$MyPipe$", GENERIC_READ | GENERIC_WRITE,
0, NULL, OPEN_EXISTING,FILE_FLAG_OVERLAPPED, NULL);

// Если возникла ошибка, выводим ее код и
// завершаем работу приложения
if(hNamedPipe == INVALID_HANDLE_VALUE)
{
fprintf(stdout,"CreateFile: Error %ld\n",
GetLastError());


}
}
Ttime=new QTimer;
connect(Ttime,SIGNAL(timeout()),this,SLOT(slot_read()));
Ttime->start(50);
exec();
}
 // запускаю из основного процесса
ch_pipe=new chanel_pipe();
ch_pipe->start();
//
« Последнее редактирование: Июль 20, 2011, 11:21 от Firefox » Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


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