1. 程式人生 > >delphi 程序間通訊(管道通訊)

delphi 程序間通訊(管道通訊)

前段時間,因專案需求,需要用到管道通訊。感覺管道通訊就是一層窗戶紙,捅破了就好了。

需求是:客戶端(client),按鈕被觸發後,傳送指令給伺服器端(server),server接收到指令後進行相應的操作,並立馬返回資訊給client。對於client而言,只是主動呼叫了一個傳送和接收資訊的函式;對於server而言,需要有一個執行緒或者timer,一直在重新整理等待接收來自client端的資訊。與此同時,server被多次開啟和關閉,不影響兩者間的通訊。

話不多說,上程式碼:

server端:

1、server開啟時,建立管道

FPipe := CreateNamedPipe(pipeName,
    PIPE_ACCESS_DUPLEX or FILE_FLAG_OVERLAPPED, PIPE_TYPE_MESSAGE or PIPE_NOWAIT,PIPE_UNLIMITED_INSTANCES,255, 255, 100, nil);
  if FPipe < 0 then  RaiseLastOsError;//Fpipe為全域性變數
2、重新整理資訊
procedure TForm2.Timer1Timer(Sender: TObject);
var
  Data: TBytes;
  nRead, nWrite: DWORD;
  Buffer: array[0..255] of Byte;
  Msg: string;
begin
  FillChar(Buffer[0], 0, SizeOf(Buffer));
  if ReadFile(FPipe, Buffer[0], 255, nRead, nil) then
  begin
    SetLength(Data, nRead);
    Move(Buffer[0], Data[0], nRead);
    Msg := TEncoding.UTF8.GetString(Data);

    mmLogs.Lines.Add(DateTimeToStr(Now) +  ' client said: ');
    mmLogs.Lines.Add(Msg);
    Data := TEncoding.UTF8.GetBytes('hello: ' + Msg);
    if not WriteFile(FPipe, Data[0], Length(Data), nWrite, nil) then
    RaiseLastOsError;
    SetLength(Data, 0);
  end;
end;
3、最後server關閉時
CloseHandle(FPipe);

Client端:

只需要提供一個函式,向server傳送訊息並接收返回的訊息

procedure TForm1.btnSendClick(Sender: TObject);
var
  Data: TBytes;
  nSent, nRead: DWORD;
  Buffer: array[0..255] of Byte;
  Msg: string;
begin
  if (mmMsg.Text = '') then
    raise Exception.Create('you can not send an empty msg!  ');


  if WaitNamedPipe(pipeName,100) then
  begin
    FPipe := CreateFile(pipeName, GENERIC_READ or GENERIC_WRITE,
      FILE_SHARE_READ or FILE_SHARE_WRITE, nil, OPEN_EXISTING, 0, 0);
  end;

  if (FPipe <= 0) then
  begin
    mmLogs.Lines.Add('server伺服器還沒有開啟');
    RaiseLastOsError;
    exit;
  end;
  try
    Data := TEncoding.UTF8.GetBytes(mmMsg.Text);

    if not WriteFile(FPipe, Data[0], Length(Data), nSent, nil) then
    begin
       mmLogs.Lines.Add('server伺服器被關閉');
       RaiseLastOsError;
    end;

    mmLogs.Lines.Add(DateTimeToStr(Now) +  ' I said: ');
    mmLogs.Lines.Add(mmMsg.Text);

    FillChar(Buffer[0], 0, SizeOf(Buffer));
    if not ReadFile(FPipe, Buffer[0], 255, nRead, nil) then
      RaiseLastOsError;

    SetLength(Data, nRead);
    Move(Buffer[0], Data[0], nRead);
    Msg := TEncoding.UTF8.GetString(Data);
    SetLength(Data, 0);

    mmLogs.Lines.Add(DateTimeToStr(Now) +  ' they reply: ');
    mmLogs.Lines.Add(Msg);
  finally
    //CloseHandle(FPipe);
  end;
end;