前段时间,因项目需求,需要用到管道通讯。感觉管道通讯就是一层窗户纸,捅破了就好了。
需求是:客户端(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;