source: trunk/Packages/CoolWeb/Network/TCPServer.pas

Last change on this file was 151, checked in by chronos, 8 months ago
File size: 3.8 KB
Line 
1unit TCPServer;
2
3interface
4
5uses
6 Classes, SysUtils,
7 {$IFDEF WINDOWS}
8 WinSock,
9 {$ELSE}
10 baseunix, sockets,
11 //LibC,
12 {$ENDIF}
13 BlckSock, ResetableThread;
14
15type
16 TTCPServer = class;
17
18 { TTCPClientThread }
19
20 TTCPClientThread = class(TResetableThread)
21 Id: Integer;
22 Parent: TTCPServer;
23 Socket: TTCPBlockSocket;
24 procedure Execute;
25 constructor Create;
26 destructor Destroy; override;
27 end;
28
29 { TClientThreadedPool }
30
31 TClientThreadedPool = class(TThreadPool)
32 protected
33 function NewItemObject: TObject; override;
34 private
35 FActive: Boolean;
36 procedure SetActive(const AValue: Boolean);
37 public
38 property Active: Boolean read FActive write SetActive;
39 end;
40
41 { TAcceptThread }
42
43 TAcceptThread = class(TThread)
44 Parent: TTCPServer;
45 procedure Execute; override;
46 end;
47
48 { TTCPServer }
49
50 TTCPServer = class
51 private
52 FOnClientConnect: TNotifyEvent;
53 Socket: TTCPBlockSocket;
54 FActive: Boolean;
55 AcceptThread: TAcceptThread;
56 NewId: Integer;
57 procedure SetActive(const AValue: Boolean);
58 public
59 ThreadPool: TClientThreadedPool;
60 Address: string;
61 Port: Word;
62 constructor Create;
63 destructor Destroy; override;
64 property Active: Boolean read FActive write SetActive;
65 property OnClientConnect: TNotifyEvent read FOnClientConnect
66 write FOnClientConnect;
67 end;
68
69
70implementation
71
72{ TTCPServer }
73
74procedure TTCPServer.SetActive(const AValue: Boolean);
75begin
76 if AValue and not FActive then begin
77 with Socket do begin
78 ThreadPool.Active := True;
79 CreateSocket;
80 SetLinger(True, 10);
81 WriteLn(Address + ':' + IntToStr(Port));
82 Bind(Address, IntToStr(Port));
83 WriteLn(LastError);
84 if LastError <> 0 then raise Exception.Create('Socket bind error');
85 Listen;
86 if LastError <> 0 then raise Exception.Create('Socket listen error');
87 AcceptThread := TAcceptThread.Create(True);
88 AcceptThread.Parent := Self;
89 AcceptThread.FreeOnTerminate := False;
90 AcceptThread.Resume;
91 end;
92 end else
93 if not AValue and FActive then begin
94 with Socket do begin
95 AcceptThread.Terminate;
96 AcceptThread.WaitFor;
97 FreeAndNil(AcceptThread);
98 ThreadPool.Active := False;
99 CloseSocket;
100 end;
101 end;
102 FActive := AValue;
103end;
104
105constructor TTCPServer.Create;
106begin
107 ThreadPool := TClientThreadedPool.Create;
108 ThreadPool.TotalCount := 10;
109 ThreadPool.Active := True;
110
111 Socket := TTCPBlockSocket.Create;
112 Address := '0.0.0.0';
113 Port := 80;
114end;
115
116destructor TTCPServer.Destroy;
117begin
118 Active := False;
119 FreeAndNil(ThreadPool);
120 FreeAndNil(Socket);
121 inherited;
122end;
123
124{ TAcceptThread }
125
126procedure TAcceptThread.Execute;
127var
128 NewSocket: TSocket;
129 NewObject: TTCPClientThread;
130begin
131 repeat
132 if Parent.Socket.CanRead(1000) then begin
133 NewSocket := Parent.Socket.Accept;
134 if Parent.Socket.LastError = 0 then begin
135 NewObject := TTCPClientThread(Parent.ThreadPool.Acquire);
136 NewObject.Parent := Parent;
137 NewObject.Socket.Socket := NewSocket;
138 NewObject.Start;
139 NewObject.Id := Parent.NewId;
140 Inc(Parent.NewId);
141 end;
142 end;
143 until Terminated;
144end;
145
146{ TTCPClientThread }
147
148procedure TTCPClientThread.Execute;
149begin
150 if Assigned(Parent.FOnClientConnect) then
151 Parent.FOnClientConnect(Self);
152
153 Parent.ThreadPool.Release(Self);
154end;
155
156constructor TTCPClientThread.Create;
157begin
158 inherited;
159 Method := Execute;
160 Socket := TTCPBlockSocket.Create;
161end;
162
163destructor TTCPClientThread.Destroy;
164begin
165 FreeAndNil(Socket);
166 inherited;
167end;
168
169{ TClientThreadedPool }
170
171function TClientThreadedPool.NewItemObject: TObject;
172begin
173 Result := TTCPClientThread.Create;
174 TResetableThread(Result).OnException := ThreadException;
175end;
176
177procedure TClientThreadedPool.SetActive(const AValue: Boolean);
178begin
179 FActive := AValue;
180end;
181
182end.
183
Note: See TracBrowser for help on using the repository browser.