Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2013.03.22;
Скачать: CL | DM;

Вниз

[named pipes] Как?   Найти похожие ветки 

 
vegarulez   (2012-04-24 00:26) [0]

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


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

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

case Message of
 WM_COMMAND:


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


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

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


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

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


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

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

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 13:07) [5]

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

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;


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


> CreateThread


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


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


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


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

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


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

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


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

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


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

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


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

䳄•㉷@


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


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


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


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

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;


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

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


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


> CreateThread


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


 
Cobalt ©   (2012-04-25 09:20) [15]

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


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

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) это же будет наверно тоже не правильно - она является тоже переменной главного потока а не дополнительного. Как быть?


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

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


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

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


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

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


 
vegarulez   (2012-05-09 22:26) [20]

хм... странно сначала не обратил внимания...
но оказывается при создании потока
через

BeginThread  (nil, 0, @ReadPipe, @hPipe, 0, Dummy)

при вызове процедуры
procedure ReadPipe (hPipe: PHANDLE); stdcall;

hPipe=$DBFFDC

и ничего при этом не работает - вываливает ошибку  - неверный дескриптор.

а при

CreateThread (nil, 0, @ReadPipe, @hPipe, 0, Dummy);    

hPipe=$455C0C

и всё нормально пашет ошибка не появляется... хотя смотрю переменную прям перед вызовом функций CreateThread или BeginThread - она одна и таже (hpipe=1880).

Вопрос почему тогда в при запуски потока проверяя в нём значение приходящей переменной они разняться???? функция CreateThread или BeginThread  же передаёт в поток только адрес переменной(указатель) правильно я понимаю???


 
Сергей М. ©   (2012-05-09 22:34) [21]

stdcall ты от балды напмсал, когда BeginThread() объявлял ?


 
vegarulez   (2012-05-09 22:43) [22]

аха убрал - ошибки нет...  спасибо.
что значит stdcall ???


 
vegarulez   (2012-05-09 22:59) [23]

а... всё... вроде почитал...
это типа когда используются функции не апишные а из внешних библиотек... а так как CreateThread скорее всего не апишная в примере и стоит stdcall...
Gо умолчанию делфи использует fastcall.
Надо теперь только догнать почему оно не работает с этим вызовом.


 
Dennis I. Komarov ©   (2012-05-09 23:21) [24]


> vegarulez   (09.05.12 22:59) [23]

Овсянка, Сэр...


 
Германн ©   (2012-05-09 23:45) [25]


> vegarulez   (09.05.12 22:59) [23]
>
> а... всё... вроде почитал...


> Надо теперь только догнать почему оно не работает с этим
> вызовом.

Теперь это называется почитал?


 
vegarulez   (2012-05-10 07:40) [26]

просто много чего не понятно там... слов всяких незнакомых... не совсем понятен смысл. в общих чертах описал, как я понял.


 
Inovet ©   (2012-05-10 09:12) [27]

> [26] vegarulez   (10.05.12 07:40)
> в общих чертах

вызовы функций с различными модификаторами различаются последовательностью передачи параметров и местом их расположения: стек и/или регистры. Соответсвенно формируется различный вход в функцию, обращение к параметрам в ней, и освобождение стека при выходе. Также различается скорость вызова функции. Также возможность/невозможность передать в функцию заранее неизвестное количество параметров - освобождать стек в самой функции или же в месте её вызова.


 
Сергей М. ©   (2012-05-11 14:24) [28]


> CreateThread скорее всего не апишная в примере и стоит stdcall.


Самая что ни на есть "апишная" она)
Потому и stdcall в примере фигурирует.

А BeginThread, напротив, не "апишная", а нативная дельфийская.
И писана она с дифолтным дельфийским соглашением fastcall
Потому и stdcall для нее НЕприменим.


 
vegarulez   (2012-05-11 21:23) [29]

оки. спасибо большое.

ребят теперь следующая проблема - вроде всё работает - на тестовом сервере который вместе с примером идёт.
делаю с тем приложением с которым программа и должна взаимодействовать  - приходит в ответ на запрос :

?????????•??????????????????????????????????????????????????????????????????? ???????????????

логи программы поднимаю - она в канал вроде всё правильно шлёт. подскажите что не так делаю при чтении из канала. У меня подозрением что это utf8. Как правильно перекодировать чтобы читабельно было?


 
vegarulez   (2012-05-11 21:24) [30]

хотя может и не в utf8 вовсе дело.


 
Сергей М. ©   (2012-05-11 22:01) [31]


> приходит в ответ на запрос


И нафих нужно любоваться этими вопросами ?
Ты гекс-дамп ответа приведи - тогда наверняка что-то проояснится ..


 
vegarulez   (2012-05-11 22:05) [32]

пытаюсь в анси стринг запихнуть... там же аррэй оф вайдчар... но что-то он ошибку выдаёт когда делаю
for i:=0 to sizeof(inBuf)
s:=s+inBuf[i];
как правильно приведение типов данных произвести??? чтобы в стринге всё содержалось?


 
Anatoly Podgoretsky ©   (2012-05-11 22:07) [33]


> vegarulez   (11.05.12 21:23) [29]

Это не utf8


 
vegarulez   (2012-05-11 22:11) [34]

ну это в мемо у меня такая картина наблюдается. хотя до этого с тестовым сервером делал - там нормально всё отображалось.
а что это может быть?


 
vegarulez   (2012-05-11 22:23) [35]


   s:="";
   for i:=0 to Length(inBuf)-1 do
    s:=s+inBuf[i];
   Form1.Memo2.Lines.Add(s);

в строку пытаюсь запихнуть и посомтреть  - но тоже самое получаю... в мемо... как мне hex содержимое именно в меме получить???


 
Сергей М. ©   (2012-05-11 22:36) [36]


> там же аррэй оф вайдчар


"там же" это где ?


> как мне hex содержимое именно в меме получить?


ты уже выяснил что из чебя представляет тип widechar


 
vegarulez   (2012-05-11 22:42) [37]

в процедуре приведённой выше
для чтения из канала

procedure ReadPipe (hPipe: PHANDLE);
var
inBuf: array[0..IN_BUF_SIZE] of WideChar;


"WideChar  Тип переменной содержащий отдельный Интернациональный символ"

но просто при тестовом сервере у меня там содержались символы сразу в нормальном виде а не в hex виде... т.е. когда в компиляторе смотрел что в переменной.


 
vegarulez   (2012-05-11 22:51) [38]

по логам по идее сервер на мой запрос должен отвечать:

<Acv version="3.04">
              <file>
                             <reqReadfile/>
              </file>
</Acv>

ну т.е.  в логах якобы он это в канал плюёт... но приходят вопросики (((


 
Сергей М. ©   (2012-05-11 23:19) [39]


> но просто при тестовом сервере


А теперь, т.е. в ситуации с "вопросами", это не "просто тестовый сервер" - это  другой сервер, который вовсе не обязан отвечать на запросы текстом вообще и юникодовым текстом в частности.

И неизвестно на каком основании клиента одного сервера ты  пытаешься присобачить для работы совсем с другим сервером.


 
Сергей М. ©   (2012-05-11 23:21) [40]


> в логах якобы он это в канал плюёт


Так он же вовсе не обязан "плевать" юникодом)
Может он ansi-текст выплевывает)...


 
vegarulez   (2012-05-11 23:25) [41]

может быть... как тогда мне его привести в требуемый вид???

Вот кусок начинаю чтение

 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)));

   s:="";
   for i:=0 to Length(inBuf)-1 do
    s:=s+utf8decode(inBuf[i]);
   Form1.Memo2.Lines.Add(s);
   Form1.Memo2.Lines.Add(CrLf);

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



и помешаю в мемо. Как привести ansi к читабельному виду?


 
vegarulez   (2012-05-11 23:28) [42]

Сергей М. ©   (11.05.12 23:19) [39]

ну имеется ввиду сервер из тестового примера.
Да это совсем другой сервер и совсем другая песня. мне нужен был именнованый канал - т.к. по нему идёт обмен данными. Поискал в инете - нашёл стсатью и описание с примерами - вот взял пример и  пытаюсь клиента прикруть на другой сервер. Ты абсолютно прав.


 
Сергей М. ©   (2012-05-11 23:35) [43]


> имеется ввиду сервер из тестового примера


Нам отсюда не видно что там за сервер и из какого тестового примера.


> Как привести ansi к читабельному виду?


Так ты сначала выясни анси там на самом деле или не анси ..
Если анси, то нахрена его принимать в юникодовом виде и потом героически преодолевать проблемы ?


 
vegarulez   (2012-05-11 23:40) [44]

Я не знаю в каком виде тот сервер выплёвывает данные - это чёрный ящик так сказать... я лиш знаю что это плоский текст в формате xml в кодировке windows-1251


 
vegarulez   (2012-05-11 23:43) [45]

я ему отправляю запрос тоже в xml - и программисты с сервера смотря логи - говорят ну да ваш запрос успешно дошёл - сервер вам успешно ответил. ответ я приводил выше. приведу ещё раз:

<Acv version="3.04">
              <file>
                             <reqReadfile/>
              </file>
</Acv>

но я не знаю в анси он или юникоде.
подскажи как мне его попробовать прочитать в анси?


 
Сергей М. ©   (2012-05-11 23:47) [46]


> в кодировке windows-1251


Так ведь Win-1251 - это однобайтный код !
Какого же тогда лешего, зная это, ты пытаешься его трактовать как 2-байтный ?)


 
Сергей М. ©   (2012-05-11 23:50) [47]


> как мне его попробовать прочитать в анси?


Анси - однобайтный код.


 
vegarulez   (2012-05-11 23:54) [48]

спасибо за ликбез - почитаю статьи на эти темы - чтобы ликвидировать без грамотность. никогда просто обычно не сталкивался...
подскажи тогда как мне его правильно прочесть?
по идее чтение в inBuf  идёт вот тут:
ReadFile (hPipe^, inBuf, IN_BUF_SIZE*sizeof(WideChar), bytesRead,
     @OverLapRd);

что требуется изменить для правильного чтения?


 
vegarulez   (2012-05-11 23:55) [49]

ReadFile (hPipe^, inBuf, IN_BUF_SIZE*sizeof(AnsiChar), bytesRead,
     @OverLapRd);


так?


 
Сергей М. ©   (2012-05-11 23:59) [50]


>      // Сообщить серверу свое имя
>      ClntName[0]:="A";

ClntName - это у тебя и в случае с "тестовым сервером" (который отвечает в win1251) тоже юникодовый буфер ?

Стремный какой-то сервер - запросы ждет в юникоде, а ответы посылает в ansi win1251 ..


 
Сергей М. ©   (2012-05-12 00:03) [51]


> vegarulez   (11.05.12 23:55) [49]


Сам буфер объяви как array[...] of AnsiChar.

Тогда


> ReadFile (hPipe^, inBuf, sizeof(inBuf),


 
vegarulez   (2012-05-12 00:33) [52]

попробовал... что-то вообще пусто в буфере... даже вопросиков нет (


 
Германн ©   (2012-05-12 00:57) [53]


> попробовал... что-то вообще пусто в буфере... даже вопросиков
> нет (
>

Покажи исправленный код.


 
vegarulez   (2012-05-12 08:13) [54]

var
 inBuf: array[0..IN_BUF_SIZE] of AnsiChar;
 bytesRead: DWORD;
 rc: Boolean;
 lastError: DWORD;
 hEventRd: THANDLE;
 OverLapRd: OVERLAPPED;
 bytesTrans: DWORD;
 s:ansistring;
 i:integer;
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, sizeof(inBuf), 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(inBuf)] := #0; // Завершить полученную строку

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

   s:="";
   Form1.Memo2.Lines.Add(inttostr(Length(inBuf)));
   for i:=0 to Length(inBuf)-1 do
    s:=s+(inBuf[i]);
   Form1.Memo2.Lines.Add(s);
   Form1.Memo2.Lines.Add(CrLf);

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


 
Сергей М. ©   (2012-05-12 11:39) [55]


>  inBuf[bytesTrans div SizeOf(inBuf)] := #0; // Завершить
> полученную строку


А это что за выкрутасы ?
Ты вообще контролировал значение bytesTrans после GetOverlappedResult ?


 
vegarulez   (2012-05-12 22:43) [56]

Сергей М. ©   (12.05.12 11:39) [55]
аха - убрал - всё заработало... сейчас потестирую... скорее всего вопросы ещё появяться. Спасибо большое!
з.ы. сок\ пиво  нужное подчеркнуть - могу эквивалент на телефон.

честно говоря - для меня пока тёмный лес. Поэтому не контролировал. Всё с примера взято, делфимастера. Я так понимаю... что строка зануляла все элементы массива. только не совсем понятно она занулаля типа элемент в массиве inbuf, который высчитывался как количество переданных байт разделить на размер inbuf. я не понимаю суть этого действия ((


 
Германн ©   (2012-05-13 03:55) [57]


> честно говоря - для меня пока тёмный лес. Поэтому не контролировал.

Опять "метод ненаучного тыка".
Протокол общения с сервером кто должен знать? Ты или Пушкин?


 
Сергей М. ©   (2012-05-13 22:57) [58]


> я не понимаю суть этого действия


Нашиша тогда выполнял это действие ?)


 
AdeptLife ©   (2012-05-25 11:51) [59]

vegarulez.
Судя по описанию я сейчас столкнулся с подобной задачей: обмен с сервером через именованный канал xml запросами.
Выложи, пожалуйста, исходники или скинь на адрес adeptlife@mail.ru.
Буду очень признателен. Заранее огромное спасибо.



Страницы: 1 2 вся ветка

Текущий архив: 2013.03.22;
Скачать: CL | DM;

Наверх




Память: 0.65 MB
Время: 0.074 c
15-1338625099
Омлет
2012-06-02 12:18
2013.03.22
Kuru-Kuru Nabe - кострюля с конвекционным самоперемешиванием


2-1334607403
Непомнящий
2012-04-17 00:16
2013.03.22
Кончается память


15-1352705908
0xDEADBEEF
2012-11-12 11:38
2013.03.22
выбор субд


2-1340872916
vasa777
2012-06-28 12:41
2013.03.22
Опции


15-1339121462
Unk
2012-06-08 06:11
2013.03.22
Подскажите проигрыватель видео.