-
Notifications
You must be signed in to change notification settings - Fork 7
/
Copy pathserver.dpr
157 lines (139 loc) · 4.77 KB
/
server.dpr
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
////////////////////////////////////////////////////////////////////////////////
//
// ****************************************************************************
// * Unit Name : server
// * Purpose : Äåìîíñòðàöèîííûé ïðèìåð ðàáîòû ñåðâåðà
// * Author : Àëåêñàíäð (Rouse_) Áàãåëü
// * Copyright : © Fangorn Wizards Lab 1998 - 2012.
// * Version : 1.01
// * Home Page : http://rouse.drkb.ru
// ****************************************************************************
//
// Ïîêàçàí ïðèìåðíûé ïðèíöèï ðàáîòû ñ êëàññîì TFWPipeServer
// Çàäà÷à äåìîñåðâåðà ïîëó÷èòü îò êëèåíòà íåêóþ ñòðîêó,
// äîáàâèòü ê íåé êîíñòàíòó "DONE" è îòïðàâèòü ðåçóëüòàò êëèåíòó.
// Ïðè ïîëó÷åíèè îò êëèåíòà ÷èñëà -1 ñåðâåð äîëæåí çàâåðøèòü ñâîþ ðàáîòó.
program server;
{$APPTYPE CONSOLE}
uses
Windows,
FWIOCompletionPipes,
SysUtils;
type
TSimpleObject = class
private
FServer: TFWPipeServer;
NeedStop: Boolean;
protected
procedure Connect(Sender: TObject; PipeHandle: PFWPipeData);
procedure Disconnect(Sender: TObject; PipeHandle: PFWPipeData);
procedure Read(Sender: TObject; PipeInstance: PFWPipeData);
procedure Idle(Sender: TObject);
public
constructor Create;
destructor Destroy; override;
property Server: TFWPipeServer read FServer;
end;
{ TSimpleObject }
// Èíèöèàëèçàöèÿ ñåðâåðà
// =============================================================================
constructor TSimpleObject.Create;
begin
// Ôëàã NeedStop èñïîëüçóåòñÿ äëÿ îñòàíîâêè ñåðâåðà
NeedStop := False;
// Ñîçäàåì ñåðâåð
FServer := TFWPipeServer.Create('FWIOCompletionPipeServer');
// Íàçíà÷àåì îáðàáîò÷èêè
FServer.OnConnect := Connect;
FServer.OnDisconnect := Disconnect;
FServer.OnNeedProcessReadAndWrite := Read;
FServer.OnIdle := Idle;
end;
destructor TSimpleObject.Destroy;
begin
FServer.Free;
inherited;
end;
// Ìåòîä âûçûâàåòñÿ ïðè ïîäñîåäèíåíèè íîâîãî êëèåíòà
// =============================================================================
procedure TSimpleObject.Connect(Sender: TObject; PipeHandle: PFWPipeData);
begin
Writeln('New client connected. Handle ', PipeHandle^.PipeHandle);
end;
// Ìåòîä âûçûâàåòñÿ ïðè îòñîåäèíåíèè êëèåíòà
// =============================================================================
procedure TSimpleObject.Disconnect(Sender: TObject; PipeHandle: PFWPipeData);
begin
Writeln('Client with handle ', PipeHandle^.PipeHandle, ' disconnected');
end;
// Ìåòîä âûçûâàåòñÿ â òîò ìîìåíò êîãäà ñåðâåð íè÷åì íå çàíÿò
// =============================================================================
procedure TSimpleObject.Idle(Sender: TObject);
begin
if NeedStop then
FServer.Active := False;
end;
// Ìåòîä âûçûâàåòñÿ ïðè ïîëó÷åíèè äàííûõ îò êëèåíòà
// =============================================================================
procedure TSimpleObject.Read(Sender: TObject; PipeInstance: PFWPipeData);
var
Len: Integer;
Buff: AnsiString;
begin
// Ïðîâåðÿåì ðàçìåð ïðèåìíîãî áóôôåðà.
// Â äàííîì äåìî ðåæèìå êëèåíò âñåãäà äîëæåí
// îòïðàâëÿòü äàííûå ðàçìåðîì íå ìåíåå 4 áàéò
if PipeInstance^.ReadBuffSize < 4 then
raise Exception.Create('Wrong readbuff size.');
// ×èòàåì ðàçìåð äàííûõ
Move(PipeInstance^.ReadBuff[0], Len, 4);
// Ïðîâåðêà, ïîëó÷åíî ëè ÷èñëî -1?
if Len = -1 then
// Åñëè ïîëó÷åíî - òî âûñòàâëÿåì ôëàã î íåîáõîäèìîñòè îñòàíîâêè ñåðâåðà
// Äàííûé ôëàã áóäåò çà÷èòàí â ðåæèìå IDLE è ñåðâåð áóäåò êîððåêòíî îñòàíîâëåí
// Åñëè îñòàíàâëèâàòü ñåðâåð ïðÿìî ñåé÷àñ êîìàíäîé FServer.Active := False,
// òî êëèåíò ïîëó÷èò îøèáêó î òîì ÷òî íà äðóãîé ñòîðîíå ïàéïà íèêîãî íåò.
NeedStop := True
else
begin
// Åñëè ïîëó÷åíî ÷èñëî îòëè÷íîå îò -1, çà÷èòûâàåì áóôåð ñ òåêñòîì
// äîáàâëÿåì ê íåìó ñëîâî "DONE" è îòïðàâëÿåì îáðàòíî
if Len > 0 then
begin
SetLength(Buff, Len);
Move(PipeInstance^.ReadBuff[4], Buff[1], Len);
Buff := Buff + 'DONE';
Len := Length(Buff);
Move(Len, PipeInstance^.WriteBuff[0], 4);
Move(Buff[1], PipeInstance^.WriteBuff[4], Len);
// Ïðè ýòîì íå çàáûâàåì óêàçàòü ðàçìåð îòïðàâëÿåìîãî áóôôåðà
PipeInstance^.WriteBuffSize := Len + 4;
end;
end;
end;
function ToOEM(str: string): AnsiString;
begin
SetLength(Result, Length(str));
AnsiToOem(@AnsiString(str)[1], @Result[1]);
end;
var
SimpleObj: TSimpleObject;
begin
try
SimpleObj := TSimpleObject.Create;
try
// òîíêèé ìîìåíò, ïîñëå êîìàíäû Server.Active := True óïðàâëåíèå íà
// ñëåäóþùóþ ñòðîêó êîäà íå ïðîèçîéäåò äî òåõ ïîð, ïîêà ñåðâåð
// íå áóäåò îñòàíîâëåí, ò.å. íå áóäåò âûïîëíåíà êîìàíäà
// Server.Active := False
SimpleObj.Server.Active := True;
Writeln('Server stopped');
finally
SimpleObj.Free;
end;
except
on E:Exception do
Writeln(ToOEM(E.Classname+': '+ E.Message));
end;
Readln;
end.