Название: pipe каналы
Отправлено: Firefox от Марта 26, 2012, 12:38
Добрый день. Хочу сделать передачу данных между процессами через именованные каналы. у меня сервер читает данные которые пишет клиент и в зависимости от данных делает те или иные команды. когда клиент один то все в порядке. но при подключении второго с обоих каналов данные уже не читаются. может я не правильно делаю. подскажите пожалуйста. класс для подключения канала на сервере: //.h #include <QtGui/QMainWindow> #include <windows.h> #include <stdio.h> #include <conio.h> #include <QTimer> #include <QString> #include <QThread> #include <QProcess> #include <QTextCodec> #define BUFFER_SIZE 512
class channel: public QThread { Q_OBJECT public: channel(); ~channel(); OVERLAPPED StrOverlapp; OVERLAPPED StrOverlappW; QString Data_pipe; bool Flag_ext_proc; LPCTSTR PipeName; int N_pipe; void run(); void createChannel(); //void analize_data(char buff[BUFFER_SIZE]); void disconnect_pipe(); void WriteChannel();
};
//.cpp #include "channel.h"
QString str; // Флаг успешного создания канала BOOL fConnected; // Идентификатор события HANDLE hEvent;
// Идентификатор канала Pipe HANDLE hNamedPipe;
// Имя создаваемого канала Pipe LPCTSTR lpszPipeName =L"\\\\.\\pipe\\$cv_r$"; LPCTSTR lpszPipeName1 =L"\\\\.\\pipe\\$cvc$"; // Буфер для передачи данных через канал char szBuf[BUFFER_SIZE];
// Количество байт данных, принятых через канал DWORD cbRead; // Количество байт данных, переданных через канал DWORD cbWritten; bool flag=0,flag_exit=0; bool flag_read=false; DWORD BytesTransferred; struct Pointer{ HWND CurrWnd[50]; HWND hwnd; int Lenght; QStringList ListItem; QString ProcName[50];
}; QTextCodec* code = QTextCodec::codecForName("CP1251"); channel::channel() { Data_pipe=""; Flag_ext_proc=0; } channel::~channel() { DisconnectNamedPipe(hNamedPipe); CloseHandle(hNamedPipe); } void channel::createChannel() { DWORD Ret; DWORD Pipe; Flag_ext_proc=0; if (N_pipe==1)PipeName=lpszPipeName; if (N_pipe==2)PipeName=lpszPipeName1; // Создаем канал Pipe, имеющий имя lpszPipeName hNamedPipe = CreateNamedPipe( PipeName, // имя канала. PIPE_ACCESS_DUPLEX, PIPE_TYPE_MESSAGE |PIPE_READMODE_MESSAGE |PIPE_WAIT, PIPE_UNLIMITED_INSTANCES, // максимальное количество экземпляров канала. BUFFER_SIZE, // размер выходного буфера по умолчанию. BUFFER_SIZE, // рахмер входного буфера по умолчанию. INFINITE, // клиент ждет связь бесконечно долго. NULL // безопасность по умолчанию. );
// Если возникла ошибка, выводим ее код и завершаем // работу приложения if(hNamedPipe == INVALID_HANDLE_VALUE) { str+="CreateNamedPipe: Error %ld\n"+GetLastError(); fprintf(stdout,"CreateNamedPipe: Error %ld\n", GetLastError()); }
if(!fConnected) // Ожидаем соединения со стороны клиента fConnected = ConnectNamedPipe(hNamedPipe, NULL);
// При возникновении ошибки выводим ее код if(!fConnected) { if (GetLastError() != ERROR_IO_PENDING) { printf("ConnectNamedPipe for pipe %d failed with", " error %d\n", GetLastError()); CloseHandle(hNamedPipe); return; } } else { printf("Server is now running\n"); while(1) { bool rez=0; DWORD BRead; if(Flag_ext_proc==1) { Data_pipe=""; break; } rez=ReadFile(hNamedPipe, szBuf,BUFFER_SIZE, &BRead,NULL); if ( rez ==false) { if (GetLastError() != ERROR_IO_PENDING) { printf("ReadFile failed with error %d\n", GetLastError()); } } if(strlen(szBuf)>0) { fprintf(stdout, szBuf); analize_data(szBuf); }
} } }
void channel::run() { createChannel(); } void channel::disconnect_pipe() { DisconnectNamedPipe(hNamedPipe); Data_pipe="";
} Использование channel *chan; channel *chan1; chan= new channel(); chan->N_pipe=1; chan->start(); chan1= new channel(); chan1->N_pipe=2; chan1->start(); . . . . . delete chan; delete chan1;
Клиентский класс: //.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; OVERLAPPED StrOverlapp; void run(); void write_chanel(char string_ch[20]); protected: private slots: }; //.cpp #include "chanel_pipe.h" #define BUFFER_SIZE 512 // Идентификатор канала Pipe HANDLE hNamedPipe; // Идентификатор события HANDLE hEndWrite; // Количество байт, переданных через канал DWORD cbWritten;
// Количество байт, принятых через канал DWORD cbRead; DWORD BytesTransferred; // Идентификатор события HANDLE hEvent;
// Буфер для передачи данных char szBuf[BUFFER_SIZE];
chanel_pipe::chanel_pipe() {
} chanel_pipe::~chanel_pipe() { CloseHandle(hNamedPipe); } void chanel_pipe::write_chanel(char string_ch[20]) { for(int i=0;i<20;i++)szBuf[i]=string_ch[i]; WriteFile(hNamedPipe, szBuf, BUFFER_SIZE, &cbWritten, NULL); } void chanel_pipe::run() { hEndWrite=CreateEvent(NULL,TRUE,TRUE,NULL); OVL.Offset=0; OVL.OffsetHigh=0; OVL.hEvent=hEndWrite; bool PRezWait=WaitNamedPipe( L"\\\\.\\pipe\\$cvc$", NMPWAIT_WAIT_FOREVER );
// Создаем канал с процессом PIPES hNamedPipe = CreateFile( L"\\\\.\\pipe\\$cvc$", GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING,0, NULL);
// Если возникла ошибка, выводим ее код и // завершаем работу приложения if(hNamedPipe == INVALID_HANDLE_VALUE) { fprintf(stdout,"CreateFile: Error %ld\n", GetLastError());
} }
Название: Re: pipe каналы
Отправлено: mutineer от Марта 26, 2012, 12:43
ммм... вот сервер открывает два канала с разными именами. А клиенты оба открывают один и тот же. так и должно быть?
Название: Re: pipe каналы
Отправлено: Firefox от Марта 26, 2012, 14:01
спасибо. уже разобралась. ;D
Название: Re: pipe каналы
Отправлено: mutineer от Марта 26, 2012, 14:34
спасибо. уже разобралась. ;D
и что было не так?
Название: Re: pipe каналы
Отправлено: Firefox от Марта 28, 2012, 09:26
действительно при подключении разных клиентов должно быть одинаковое имя канала у всех.
Название: Re: pipe каналы
Отправлено: Firefox от Марта 28, 2012, 09:35
но теперь у меня есть другая проблема. проблема отключить канал. то есть алгоритм такой: подключается один клиент, поработав с который, надо его закрыть и открыть другой клиент. вот и получается что, когда закрывается первый клиент, то данные в канале при подключении второго почему-то остаются. то есть при подключении второго клиента, функция ReadFile считывает последние данные которые были в канале перед закрытием первого. использую я это так: channel *chan; chan= new channel(); chan->start();// создаем канал и ждем клиента if(chan->Data_pipe.left(6)=="reg2")// пришла команда по каналу запустить второго клиента и закрыть первого { chan->terminate(); chan->disconnect_pipe(); parametr="rm1 "; parametr+="0 "; parametr+=Zakaz+" "; parametr+=Form_IN2+" "; parametr+=Form_OUT2+" "; parametr+=IP_BOR; k=parametr.toWCharArray(Code_par); Code_par[k]='\0'; chan->start(); ShellExecute(Handle,L"open",L"reg2.exe",Code_par,NULL,SW_RESTORE); parametr="taskkill /F /IM "; parametr+=Tek_regim; ::WinExec(parametr.toAscii(), SW_HIDE); Tek_regim="reg2.exe";
Название: Re: pipe каналы
Отправлено: Firefox от Марта 28, 2012, 12:50
вот как все выглядит полностью, но все равно старые данные остаются: //Сервер //.h #include <QtGui/QMainWindow> #include <windows.h> #include <stdio.h> #include <conio.h> #include <QTimer> #include <QString> #include <QThread> #include <QProcess> #include <QTextCodec> #define BUFFER_SIZE 512
class channel: public QThread { Q_OBJECT public: channel(); ~channel(); OVERLAPPED StrOverlapp; OVERLAPPED StrOverlappW; QString Data_pipe; bool Flag_ext_proc; LPCTSTR PipeName; int N_pipe; void run(); void createChannel(); void analize_data(char buff[BUFFER_SIZE]); void disconnect_pipe(); };
//.cpp #include "channel.h"
QString str; // Флаг успешного создания канала BOOL fConnected; // Идентификатор события HANDLE hEvent;
// Идентификатор канала Pipe HANDLE hNamedPipe;
// Имя создаваемого канала Pipe LPCTSTR lpszPipeName =L"\\\\.\\pipe\\$cv_r$"; // Буфер для передачи данных через канал char szBuf[BUFFER_SIZE];
// Количество байт данных, принятых через канал DWORD cbRead; // Количество байт данных, переданных через канал DWORD cbWritten; bool flag=0,flag_exit=0; bool flag_read=false; DWORD BytesTransferred; struct Pointer{ HWND CurrWnd[50]; HWND hwnd; int Lenght; QStringList ListItem; QString ProcName[50];
}; QTextCodec* code = QTextCodec::codecForName("CP1251"); channel::channel() { Data_pipe=""; Flag_ext_proc=0; } channel::~channel() { DisconnectNamedPipe(hNamedPipe); CloseHandle(hNamedPipe); } void channel::createChannel() { DWORD Ret; DWORD Pipe; // Создаем канал Pipe, имеющий имя lpszPipeName hNamedPipe = CreateNamedPipe( lpszPipeName, // имя канала. PIPE_ACCESS_DUPLEX, PIPE_TYPE_MESSAGE |PIPE_READMODE_MESSAGE |PIPE_WAIT, PIPE_UNLIMITED_INSTANCES, // максимальное количество экземпляров канала. BUFFER_SIZE, // размер выходного буфера по умолчанию. BUFFER_SIZE, // рахмер входного буфера по умолчанию. INFINITE, // клиент ждет связь бесконечно долго. NULL // безопасность по умолчанию. );
// Если возникла ошибка, выводим ее код и завершаем // работу приложения if(hNamedPipe == INVALID_HANDLE_VALUE) { str+="CreateNamedPipe: Error %ld\n"+GetLastError(); fprintf(stdout,"CreateNamedPipe: Error %ld\n", GetLastError()); } if(!fConnected) // Ожидаем соединения со стороны клиента fConnected = ConnectNamedPipe(hNamedPipe, NULL);
// При возникновении ошибки выводим ее код if(!fConnected) { if (GetLastError() != ERROR_IO_PENDING) { printf("ConnectNamedPipe for pipe %d failed with", " error %d\n", GetLastError()); CloseHandle(hNamedPipe); return; } } else { printf("Server is now running\n"); while(1) { bool rez=0; DWORD BRead; rez=ReadFile(hNamedPipe, szBuf,BUFFER_SIZE, &BRead,NULL); if ( rez ==false) { if (GetLastError() != ERROR_IO_PENDING) { printf("ReadFile failed with error %d\n", GetLastError()); } } if(strlen(szBuf)>0) { fprintf(stdout, szBuf); analize_data(szBuf); if(szBuf[0]=='r') break; } } DisconnectNamedPipe(hNamedPipe); CloseHandle(hNamedPipe); } }
void channel::run() { createChannel(); } void channel::analize_data(char buff[BUFFER_SIZE]) { QString str; HWND Id_prog=0; int numW; for(int i=0;i<BUFFER_SIZE; i++) str+=buff[i]; Data_pipe=str; } void channel::disconnect_pipe() { DisconnectNamedPipe(hNamedPipe); Data_pipe=""; }
// использование channel *chan; chan= new channel(); if(chan->Data_pipe.left(4)=="reg2") { chan->terminate(); parametr="rm2 "; parametr+="0 "; parametr+=Zakaz+" "; parametr+=Form_IN_2+" "; parametr+=Form_OUT_2+" "; parametr+=IP_BOR; k=parametr.toWCharArray(Code_par); Code_par[k]='\0'; chan->start(); ShellExecute(Handle,L"open",L"reg2.exe",Code_par,NULL,SW_RESTORE); parametr="taskkill /F /IM "; parametr+=Tek_regim; ::WinExec(parametr.toAscii(), SW_HIDE); Tek_regim="reg2.exe"; } .. .. .. delete chan;
|