Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

[named pipes] Как? [D7, XP]


Страницы:   1 2 3

vegarulez ©   (2012-04-24 00:26:00) 

Всем дорбого времени суток!
Уважаемые мастреа, подскажите как сделать тоже самое что написано в статье
http://www.delphimaster.ru/articles/named_pipes/index.html
только в обычном окне на форме - чтобы при нажатии кнопки на форме происходил коннект к именованному каналу а при нажатии другой кнопки происходила отправка данных в канал к примеру из мемо1 и чтение ответа к примеру в мемо2. Прочитав пример - и запустив приложение которе прилагается к статье - понял что это то что нужно. но вот не задача - там всё сделано на диалоговом окне как я понимаю... и у меня не хватает знаний чтобы перенести это всё на форму [тут он краснеет потупив взгляд в пол], там очень много непонятных мне моментов. Прошу помочь с переносом на обычную форму.


Сергей М.   (2012-04-25 22:02:00) [41]

самое простое решение - воспользоваться сообщением wm_copydata


vegarulez   (2012-04-25 09:51:00) [42]

получается чтобы её обновлять (если она будет описна в public или private) надо тоже синхронизацию делать с главным потоком.


vegarulez   (2012-04-25 09:49:00) [43]

всмысле если описание переменно помещу в public или private


vegarulez   (2012-04-25 09:48:00) [44]

1. BeginThread аха поменял.
2. Вопрос как сделать syncronize(updatememo)в процедуре:

procedure ReadPipe (hPipe: PHANDLE); stdcall;
var
 inBuf: array[0..IN_BUF_SIZE] of WideChar;
 bytesRead: DWORD;
 rc: Boolean;
 lastError: DWORD;
 hEventRd: THANDLE;
 OverLapRd: OVERLAPPED;
 bytesTrans: DWORD;
begin
 inBuf[0] := #0;
 hEventRd := CreateEventW (nil, true, false, nil);
 FillChar (OverLapRd, sizeof(OVERLAPPED), 0);
 OverLapRd.hEvent := hEventRd;
 // Бесконечный цикл чтения из канала, до тех пор,пока не разорвется соединение
 // Чтение происходит асинхронно, с ожиданием по событию. После того, как сооб-
 // щение прочитано, оно помещается в элемент редактирования.
 while true do begin
   rc := ReadFile (hPipe^, inBuf, IN_BUF_SIZE*sizeof(WideChar), bytesRead,
     @OverLapRd);    // перменная булеан , пытаемся прочитать из pipe

   if not rc then begin
     lastError := GetLastError;
     // Проверка на три вида ошибки:
     // IO_PENDING (ожидать завершения операции), BROKEN_PIPE (выйти из цикла)
     // и остальные (выдать сообщение, выйти из цикла и умереть)
     if lastError = ERROR_IO_PENDING then begin
       WaitForSingleObject (hEventRd, INFINITE);
     end else begin
       if lastError = ERROR_BROKEN_PIPE then
         MessageBoxW (hWndClient,
           'The connection to this client has been broken.', '', MB_OK)
       else
         ShowLastErrorMessage(hWndClient,
           PAnsiChar('Client: Debug():ReadFile'));
       Break;
     end;
   end;
   GetOverlappedResult (hPipe^, OverLapRd, bytesTrans, false);
   inBuf[bytesTrans div SizeOf(WideChar)] := #0; // Завершить полученную строку

   SendMessageW (GetDlgItem (hWndClient, IDD_EDITREAD), EM_REPLACESEL,
     0, LPARAM(@inBuf));
   // Перевести курсор на следующую строку в элементе редактирования :)
   SendMessageW (GetDlgItem (hWndClient, IDD_EDITREAD), EM_REPLACESEL,
     0, LPARAM(PWideChar(CrLf)));
   Form1.Memo2.Lines.Add(inBuf);
   Form1.Memo2.Lines.Add(CrLf);

 end;
 // Если соединение с каналом разорвано, завершить программу
 PostMessageW (hWndClient, WM_GO_AWAY, 0,0);
 ExitThread(0);
end;


если переменная inBuf определена только для этой процедуры. если же я её сделаю доступной для всего приложения чтобы использовать её в syncronize (updatememo) это же будет наверно тоже не правильно - она является тоже переменной главного потока а не дополнительного. Как быть?


Cobalt   (2012-04-25 09:20:00) [45]

> как мне передать в канал пакет "нулевой длины"?
для этого уже нужно обзавестись протоколом.
Т.е. не "банально передавать все данные что есть", а вначале передавать длину пакета данных (целое число строго определенной разрядности), а потом сами данные.


Сергей М.   (2012-04-24 22:57:00) [46]


> CreateThread


Мало, видать, тебе по балде грабли долбили - еще хочешь)


vegarulez   (2012-04-24 21:47:00) [47]

вот так вроде работает xml запихивается в канал...сервер вроде получает - отправляет клиентам - обмен происходит.
теперь вопрос - как мне передать в канал пакет "нулевой длины"?


vegarulez   (2012-04-24 21:37:00) [48]

procedure TForm1.bt_sendClick(Sender: TObject);
var
 rc:boolean;
 bytesWritten: DWORD;
 Dummy: DWORD;
 tmp:PAnsiChar;
 outBuf: array[0..OUT_BUF_SIZE] of WideChar;
 sendBuf: array[0..OUT_BUF_SIZE] of WideChar;
begin
     tmp:=PAnsiChar(Form1.Memo1.Text);
     // Сообщить серверу свое имя
     ClntName[0]:='A';

         GetWindowTextW (Form1.Memo1.Handle, outBuf,
           MAX_WRITE);
      //Form1.Memo1.Handle
      lstrcpyw(sendBuf, ClntName);
      lstrcatw(sendBuf, ':');
      lstrcatw(sendBuf, outBuf);

     // перменная типа булеан смотрим есть ли запись в pipe или произошла ошибка при записи
     WriteFile (hPipe, outBuf, MAX_WRITE, bytesWritten,@OverLapWrt);
     if not rc then // Если IO_PENDING, ожидать звершения операции
       if GetLastError = ERROR_IO_PENDING then
         WaitForSingleObject (hEventWrt, INFINITE);
     // Создать поток чтения из канала.
     CreateThread (nil, 0, @ReadPipe, @hPipe, 0, Dummy);

end;


Сергей М.   (2012-04-24 15:04:00) [49]


> как бы их обойти?


1. Использовать BeginThread вместо CreateThread
2. Недопускать обращений к визуальным vcl-контролам из доп.потоков.


vegarulez   (2012-04-24 14:17:00) [50]

var
 tmp:PAnsiChar;
begin
     tmp:=PAnsiChar(Form1.Memo1.Text);
     WriteFile (hPipe, tmp, Length(tmp), bytesWritten,@OverLapWrt);


но что-то абракадабра приходит:

䳄•㉷@


vegarulez   (2012-04-24 14:00:00) [51]

CRLF   (24.04.12 13:52) [7] >
не, у мну ругается (
D7


vegarulez   (2012-04-24 13:53:00) [52]

))) как бы их обойти? :) и так весь лоб в шишках )


CRLF   (2012-04-24 13:52:00) [53]


>  Как при передаче передать значение memo1.Text?
>      rc := WriteFile (hPipe, ClntName, MAX_WRITE, bytesWritten,
>        @OverLapWrt);

rc := WriteFile (hPipe, PChar(Memo1.Text), Length(Memo1.Text), bytesWritten,
       @OverLapWrt); для делфи 2009 и выше


Сергей М.   (2012-04-24 13:47:00) [54]


> CreateThread


> Form1.Memo2.Lines.Add(inBuf);


ждут тебя грабли малыя и великия)


vegarulez   (2012-04-24 13:07:00) [55]

Вот весь код используемый

procedure ReadPipe (hPipe: PHANDLE); stdcall;
var
 inBuf: array[0..IN_BUF_SIZE] of WideChar;
 bytesRead: DWORD;
 rc: Boolean;
 lastError: DWORD;
 hEventRd: THANDLE;
 OverLapRd: OVERLAPPED;
 bytesTrans: DWORD;
begin
 inBuf[0] := #0;
 hEventRd := CreateEventW (nil, true, false, nil);
 FillChar (OverLapRd, sizeof(OVERLAPPED), 0);
 OverLapRd.hEvent := hEventRd;
 // Бесконечный цикл чтения из канала, до тех пор,пока не разорвется соединение
 // Чтение происходит асинхронно, с ожиданием по событию. После того, как сооб-
 // щение прочитано, оно помещается в элемент редактирования.
 while true do begin
   rc := ReadFile (hPipe^, inBuf, IN_BUF_SIZE*sizeof(WideChar), bytesRead,
     @OverLapRd);    // перменная булеан , пытаемся прочитать из pipe

   if not rc then begin
     lastError := GetLastError;
     // Проверка на три вида ошибки:
     // IO_PENDING (ожидать завершения операции), BROKEN_PIPE (выйти из цикла)
     // и остальные (выдать сообщение, выйти из цикла и умереть)
     if lastError = ERROR_IO_PENDING then begin
       WaitForSingleObject (hEventRd, INFINITE);
     end else begin
       if lastError = ERROR_BROKEN_PIPE then
         MessageBoxW (hWndClient,
           'The connection to this client has been broken.', '', MB_OK)
       else
         ShowLastErrorMessage(hWndClient,
           PAnsiChar('Client: Debug():ReadFile'));
       Break;
     end;
   end;
   GetOverlappedResult (hPipe^, OverLapRd, bytesTrans, false);
   inBuf[bytesTrans div SizeOf(WideChar)] := #0; // Завершить полученную строку

   SendMessageW (GetDlgItem (hWndClient, IDD_EDITREAD), EM_REPLACESEL,
     0, LPARAM(@inBuf));
   // Перевести курсор на следующую строку в элементе редактирования :)
   SendMessageW (GetDlgItem (hWndClient, IDD_EDITREAD), EM_REPLACESEL,
     0, LPARAM(PWideChar(CrLf)));
   Form1.Memo2.Lines.Add(inBuf);
   Form1.Memo2.Lines.Add(CrLf);
 end;
 // Если соединение с каналом разорвано, завершить программу
 PostMessageW (hWndClient, WM_GO_AWAY, 0,0);
 ExitThread(0);
end;

procedure TForm1.bt_connectClick(Sender: TObject);
var
 rc:boolean;
 bytesWritten: DWORD;
 Dummy: DWORD;
 APipeName: string;
 fileName: array[0..LINE_LEN+NAME_SIZE+sizeof(WideChar)*2] of WideChar;
begin
      //APipeName:= Format('\\%s\pipe\test', [WideCharToString(ShrName)]);
      APipeName:=Edit1.Text;
     // Соединиться с сервером
     hPipe := CreateFileW ('\\.\pipe\test',
       GENERIC_WRITE or // Доступ на чтение/запись
       GENERIC_READ,
       FILE_SHARE_READ or // Разделенный доступ
       FILE_SHARE_WRITE,
       nil,
       OPEN_EXISTING,   // Канал должен существовать
       FILE_FLAG_OVERLAPPED, // Использовать асинхронный ввод/вывод
       0);

     hEventWrt := CreateEvent (nil, true, false, nil);
     OverLapWrt.hEvent := hEventWrt;
end;

procedure TForm1.bt_sendClick(Sender: TObject);
var
 rc:boolean;
 bytesWritten: DWORD;
 Dummy: DWORD;

begin

     // Сообщить серверу свое имя
     ClntName[0]:='A';
     rc := WriteFile (hPipe, ClntName, MAX_WRITE, bytesWritten,
       @OverLapWrt);  // перменная типа булеан смотрим есть ли запись в pipe или произошла ошибка при записи
     if not rc then // Если IO_PENDING, ожидать звершения операции
       if GetLastError = ERROR_IO_PENDING then
         WaitForSingleObject (hEventWrt, INFINITE);
     // Создать поток чтения из канала.
     CreateThread (nil, 0, @ReadPipe, @hPipe, 0, Dummy);

end;


vegarulez   (2012-04-24 13:05:00) [56]

пара вопросов:

1. ClntName: array [0..NAME_SIZE] of WideChar; // Имя клиента
Это переменная массив чаров. Вопрос он используется для передачи имени клиента на сервер:

     rc := WriteFile (hPipe, ClntName, MAX_WRITE, bytesWritten,
       @OverLapWrt);  

Вопрос получается что там просто набор [t],[e],[s],[t] как мне обычный стринг перегнать в эту переменную? И вопрос почему нельзя просто стринговую переменную использовать при передачи имени?
Ну да ладно это как нибудь разложу в массив  for i:=0 to length(s)-1 do и т.д.
Просто интересно как стринг сразу использовать.

2. Как при передаче передать значение memo1.Text?
     rc := WriteFile (hPipe, ClntName, MAX_WRITE, bytesWritten,
       @OverLapWrt);  

Получается мне его также перегонять в array of char?

BOOL WriteFile(

   HANDLE hFile, // handle to file to write to
   LPCVOID lpBuffer, // pointer to data to write to file
   DWORD nNumberOfBytesToWrite, // number of bytes to write
   LPDWORD lpNumberOfBytesWritten, // pointer to number of bytes written
   LPOVERLAPPED lpOverlapped  // pointer to structure needed for overlapped I/O
  );

и подставлять вместо ClntName? Просто у меня там лежит xml довольно большой. Судя из описания WriteFile там требуется лишь указатель на данные. Подскажите как мне просто создать указатель на данные из TMemo?


vegarulez   (2012-04-24 10:25:00) [57]

Аха так и сделал. Пока тестирую... вопросы накапливаются. как соберу - напишу вопросы которые появились.


CRLF   (2012-04-24 07:52:00) [58]

Кусок из WM_INITCLIENT переносишь в обработчик события OnClick первой кнопки, для начала диалог убери и имя сервера задавай константой. Кусок из IDB_SEND перенеси в обработчик OnClick второй кнопки.


vegarulez   (2012-04-24 00:49:00) [59]

Основная функция которая отвечает за отправку сообщений в pipe ClientDlgProc для кнопки коннект к каналу я так полагаю нужно то что находится в  

case Message of
 WM_COMMAND:


подскаэитье что это за значения case Message???
 WM_COMMAND:
 WM_INITCLIENT:
и т.д.
что это за case с чем с равнение идёт?  где выдаются эти ... сообщения или как правильно назвать? т.е. я так полагаю в это диалоговое окно формирует эти состояния, или сообщения... подскажите плиз где про это прочитать?


Страницы:   1 2 3

Наверх

Титульная страница Поиск, карта сайта Написать письмо