-
В MSDN есть такой список вариантов взаимодействия между приложениями (процессами):
The following IPC mechanisms are supported by Windows:
Clipboard COM Data Copy DDE File Mapping Mailslots Pipes RPC Windows Sockets
Кто может навскидку сказать что лучше выбрать с точки зрения скорости обмена данными с учетом того, что приложения могут взаимодействовать как в рамках одной машины так и на разных машинах (но в одной локальной сети).
-
> что приложения могут взаимодействовать как в рамках одной > машины так и на разных машинах (но в одной локальной сети) > .
> Windows Sockets
-
> > Windows Sockets
А трубы? Они вроде тоже могут по сети работать. Или они медленней получатся?
-
В рамках локалки - сокеты, пайпы поверх них сидят, т.е. лишний траффик (если уж так сильно оптимизировать надо) + некоторые заморочки с безопасностью могут вылезти.
-
Rouse_, здраствуйте. Скачал ваш пример FWIOCompletionPipes. Там пример с передачей чисел. Че-то туплю и не могу сделать передачу текста(String, PChar и т.д.). Не подскажете, как это можно сделать? Спасибо.
-
String, PChar и т.д. это указатели на данные. Стало быть, передавай их не их самих, а непосредственно то, на что они указывают.
-
> Кто может навскидку сказать что лучше выбрать с точки зрения > скорости обмена данными с учетом того, что приложения могут > взаимодействовать как в рамках одной машины
пайпы значительно быстрее
> так и на разных машинах
сокеты быстрее
-
> String, PChar и т.д. это указатели на данные. > Стало быть, передавай их не их самих, а непосредственно > то, на что они указывают.
Блин. Чего-то не получается у меня. Получаю EAccessViolation.
-
Не показывай код, дождись когда подтянутся телепаты.
-
Клиент: procedure TForm1.Button1Click(Sender: TObject);
var
InString, OutString: String;
PipeClient: TFWPipeClient;
InStream, OutStream: TMemoryStream;
begin
InString := Edit1.Text;
try
PipeClient := TFWPipeClient.Create('.', 'FWIOCompletionPipeServer');
try
PipeClient.Active := True;
InStream := TMemoryStream.Create;
try
OutStream := TMemoryStream.Create;
try
InStream.Clear;
InStream.WriteBuffer(Pointer(InString)^, Length(InString));
PipeClient.SendData(InStream, OutStream);
finally
OutStream.Free;
end;
finally
InStream.Free;
end;
finally
PipeClient.Free;
end;
except
on E:Exception do
Memo1.Lines.Add(E.Classname + ': ' + E.Message);
end;
end; Сервер: procedure TSimpleObject.Read(Sender: TObject; PipeInstance: PFWPipeData);
var
InString: String;
begin
Move(PipeInstance^.ReadBuff[0], InString, PipeInstance^.ReadBuffSize);
Form1.Memo1.Lines.Add('Str = ' + InString);
end;
-
Навскидку SetLength(InString,PipeInstance^.ReadBuffSize);
Move(PipeInstance^.ReadBuff[0], InString[1], PipeInstance^.ReadBuffSize);
-
1. PipeClient.SendData - проверь, по памяти не помню, правит ли он позицию перед отправкой. Если нет, то выставляй ее в ноль перед вызовом 2. Move(PipeInstance^.ReadBuff[0], InString, PipeInstance^.ReadBuffSize); Для начала желательно передавать размер строки и потом е саму, в противном случае поимееш проблем на склейке пакетов, ну есессно размер принимаещего буфера у тебя не выставлен, как и сказал Германн. 3. тоже проверь, если принимающий буфер не требуется то и создавать OutStream не нужно
ЗЫ: щас просто без кода сижу, поэтому по памяти все говорю...
-
Теперь AV нету, но принимает стоку коряво.
Отправляю: "Edit1", получаю: "Edu". Отп.: "kak dela?", пол.: "kak dipe\"
-
procedure TFWPipeClient.SendData(InStream, OutStream: TStream);
var
lpBytesRead: DWORD;
begin
InStream.Position := 0;
InStream.ReadBuffer(FBuff[0], InStream.Size);
Win32Check(TransactNamedPipe(FPipe, @FBuff[0], InStream.Size,
@FBuff[0], MAXWORD, lpBytesRead, nil));
OutStream.Size := 0;
OutStream.WriteBuffer(FBuff[0], lpBytesRead);
OutStream.Position := 0;
end;
-
Скорее всего тут проблема: InStream.WriteBuffer(Pointer(InString)^, Length(InString)); строки юникодные?
-
> Скорее всего тут проблема: > InStream.WriteBuffer(Pointer(InString)^, Length(InString)); > > строки юникодные?
InString := Edit1.Text; Вроде нет
-
> Вроде нет
Ну мы ж не бабки-гадалки, сделай все свои строки в виде AnsiString и проверь...
-
Добавил инфо: procedure TSimpleObject.Read(Sender: TObject; PipeInstance: PFWPipeData);
var
InString: String;
begin
WriteToFile('server.log', 'Length = ' + IntToStr(PipeInstance^.ReadBuffSize));
SetLength(InString, PipeInstance^.ReadBuffSize);
Move(PipeInstance^.ReadBuff[0], InString[1], PipeInstance^.ReadBuffSize);
WriteToFile('server.log', 'Str = ' + InString);
end;
При получении "Edit1" в файле имеется: Length = 5 Str = Ed???
-
После изменения String на AnsiString получаю:
Length = 5 Str = ?????
-
> krupt © (12.12.12 23:49) [18] > > После изменения String на AnsiString получаю:
В клиенте тоже такую замену сделал?
-
Блин. В одном месте забыл поменять. Изменил. Теперь все ок. Только есть проблема с приёмом сообщения клиентом. procedure TForm1.Button1Click(Sender: TObject);
var
InString, OutString: AnsiString;
PipeClient: TFWPipeClient;
InStream, OutStream: TMemoryStream;
begin
InString := Edit1.Text;
OutString := '';
try
PipeClient := TFWPipeClient.Create('.', 'FWIOCompletionPipeServer');
try
PipeClient.Active := True;
InStream := TMemoryStream.Create;
try
OutStream := TMemoryStream.Create;
try
InStream.Clear;
InStream.SetSize(Length(InString));
Memo1.Lines.Add('OutStr = ' + InString);
Data := Length(InString);
Memo1.Lines.Add('OutStrLen = ' + IntToStr(Data));
InStream.WriteBuffer(Pointer(InString)^, Length(InString));
PipeClient.SendData(InStream, OutStream);
SetLength(OutString, OutStream.Size);
OutStream.ReadBuffer(Pointer(OutString)^, OutStream.Size);
Memo1.Lines.Add('InStrLen = ' + IntToStr(OutStream.Size));
Memo1.Lines.Add('InStr = ' + OutString);
finally
OutStream.Free;
end;
finally
InStream.Free;
end;
finally
PipeClient.Free;
end;
except
on E:Exception do
Memo1.Lines.Add(E.Classname + ': ' + E.Message);
end;
end; Получаю обратное на "Edit1": InStrLen = 5 InStr = Ed
-
Где-то все-таки юникод остался. Скорее всего. В результате в какой-то функции приема/передачи принимается/передается вдвое меньше байт, чем следовало бы.
-
Вот что происходит когда строковый тип используется в качестве "простого буфера для функций приема/передачи"! Как хорошо всё выглядело когда тип String был простой "паскалевской" строкой. И как плохо с этим в Д2009+. Все "привычные" функции приема/передачи имеют параметр, который относится к количеству принятых/переданных байт. В то время как "длина" строки, которая определяется функцией Length и задаётся процедурой SetLength зависит от кодировки и не всегда равна количеству байт занимаемых строкой.
-
> Германн (13.12.2012 01:26:22) [22]
И разве это проблема
-
> 3. тоже проверь, если принимающий буфер не требуется то > и создавать OutStream не нужно
А куда тогда результат то девать?
-
Что в этом случае передавать в качестве второго параметра? nil?
-
-
> Rouse_ © (13.12.12 13:34) [26] > > Проверил - проблема была до кучи и в самом классе (буфера > юникодные использовались).
Ну я ж говорил, что где-то все-таки юникод остался. :)
-
> Anatoly Podgoretsky © (13.12.12 08:10) [23] > > > Германн (13.12.2012 01:26:22) [22] > > И разве это проблема >
Ну смотри. При переносе кода с 16-ти битной Дельфи на 32-х битную мне достаточно было лишь поставить в проекте опцию {$H-} и всё работало. А вот при переносе с Д2007 на Д2009+ нужно сделать гораздо больше "телодвижений". И больше всего меня смущает то, что написано в доквики: In Delphi code, Length returns the number of characters actually used in the string or the number of elements in the array. In C++ code, use the method of the same name on the AnsiString or DynamicArray class.
S is a string-valued or array-valued expression.
For single-byte and multibyte strings, Length returns the number of bytes used by the string. Example for UTF-8:
Writeln(Length(Utf8String('1¢'))); // displays 3
For Unicode (WideString) strings, Length returns the number of bytes divided by two.
-
Спасибо. Разобрался со всем этим. Для использования с формами сделал наследника от TThread и переназначил метов Execute: procedure TMyThread.Execute;
var
PipeServer: TPipeServer;
begin
try
PipeServer := TPipeServer.Create;
try
PipeServer.Server.Active := True;
finally
PipeServer.Free;
end;
except
end;
end;
-
Ах, да. Забыл. TPipeServer - это как TSimpleObject из примера :)
|