server.lpr 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224
  1. program server;
  2. {$mode objfpc}{$H+}
  3. uses
  4. {$IFDEF UNIX}
  5. CThreads,
  6. {$ENDIF}
  7. TcpIpServer, TcpIpClient, SysUtils, Classes;
  8. type
  9. { TServerThread }
  10. TServerThread = class(TThread)
  11. private
  12. FClients: TThreadList;
  13. FServer: TTcpIpServerSocket;
  14. public
  15. constructor Create;
  16. destructor Destroy; override;
  17. procedure Execute; override;
  18. procedure TerminateClients;
  19. property Clients: TThreadList read FClients;
  20. end;
  21. { TClientThread }
  22. TClientThread = class(TThread)
  23. private
  24. FData: string;
  25. FSocket: TTcpIpClientSocket;
  26. FOwner: TServerThread;
  27. protected
  28. procedure DoClientReceive;
  29. public
  30. constructor Create(AOwner: TServerThread; const ASocket: LongInt);
  31. destructor Destroy; override;
  32. procedure Execute; override;
  33. property Socket: TTcpIpClientSocket read FSocket;
  34. end;
  35. { TApp }
  36. TApp = class
  37. private
  38. FServer: TServerThread;
  39. public
  40. constructor Create;
  41. destructor Destroy; override;
  42. procedure Run;
  43. end;
  44. { TServerThread }
  45. constructor TServerThread.Create;
  46. begin
  47. inherited Create(True);
  48. FreeOnTerminate := True;
  49. FClients := TThreadList.Create;
  50. FServer := TTcpIpServerSocket.Create(4100);
  51. end;
  52. destructor TServerThread.Destroy;
  53. begin
  54. FClients.Free;
  55. FServer.Free;
  56. inherited Destroy;
  57. end;
  58. procedure TServerThread.Execute;
  59. var
  60. VSocket: LongInt;
  61. VClient: TClientThread;
  62. begin
  63. FServer.Bind;
  64. FServer.Listen;
  65. while (not Terminated) or (FServer.LastError = 0) do
  66. begin
  67. VSocket := FServer.Accept;
  68. if VSocket = -1 then
  69. Break;
  70. VClient := TClientThread.Create(Self, VSocket);
  71. if Assigned(VClient) then
  72. VClient.Start;
  73. end;
  74. end;
  75. procedure TServerThread.TerminateClients;
  76. var
  77. VList: TList;
  78. VItem: Pointer;
  79. VClient: TClientThread absolute VItem;
  80. begin
  81. VList := FClients.LockList;
  82. try
  83. for VItem in VList do
  84. if Assigned(VClient) and not VClient.Finished then
  85. begin
  86. VClient.FreeOnTerminate := False;
  87. VClient.Terminate;
  88. if Assigned(VClient.Socket) then
  89. VClient.Socket.Free;
  90. VClient.WaitFor;
  91. FreeAndNil(VClient);
  92. end;
  93. finally
  94. FClients.UnlockList;
  95. end;
  96. end;
  97. { TClientThread }
  98. constructor TClientThread.Create(AOwner: TServerThread; const ASocket: LongInt);
  99. begin
  100. inherited Create(True);
  101. FreeOnTerminate := True;
  102. FOwner := AOwner;
  103. FSocket := TTcpIpClientSocket.Create(ASocket);
  104. if Assigned(FOwner) then
  105. FOwner.Clients.Add(Self);
  106. end;
  107. destructor TClientThread.Destroy;
  108. begin
  109. if Assigned(FOwner) then
  110. FOwner.Clients.Remove(Self);
  111. if not Finished then
  112. FSocket.Free;
  113. inherited Destroy;
  114. end;
  115. procedure TClientThread.Execute;
  116. var
  117. VDataSize: Integer;
  118. begin
  119. WriteLn('Connected: ', FSocket.Socket.Handle);
  120. try
  121. while (not Terminated) or (FSocket.LastError = 0) do
  122. if FSocket.CanRead(1000) then
  123. begin
  124. //{$IFDEF UNIX}
  125. if FSocket.Socket.Closing then
  126. Break;
  127. //{$ENDIF}
  128. FData := '';
  129. VDataSize := FSocket.Waiting;
  130. if VDataSize < 1 then
  131. Break;
  132. SetLength(FData, VDataSize);
  133. VDataSize := FSocket.Read(Pointer(FData)^, VDataSize);
  134. if VDataSize < 1 then
  135. Break;
  136. DoClientReceive;
  137. end;
  138. finally
  139. WriteLn('Disconnected: ', FSocket.Socket.Handle);
  140. end;
  141. end;
  142. procedure TClientThread.DoClientReceive;
  143. var
  144. VList: TList;
  145. VItem: Pointer;
  146. VClient: TClientThread absolute VItem;
  147. begin
  148. if not Assigned(FOwner) then
  149. Exit;
  150. if not Assigned(FOwner.FServer) then
  151. Exit;
  152. if not FOwner.FServer.IsConnected then
  153. Exit;
  154. VList := FOwner.Clients.LockList;
  155. try
  156. for VItem in VList do
  157. begin
  158. if not Assigned(VClient.Socket) then
  159. Continue;
  160. FData := DateTimeToStr(Now) + '- ' + FData;
  161. VClient.Socket.Write(Pointer(FData)^, Length(FData));
  162. if VClient <> Self then
  163. WriteLn(FData);
  164. end;
  165. finally
  166. FOwner.Clients.UnlockList;
  167. end;
  168. end;
  169. { TApp }
  170. constructor TApp.Create;
  171. begin
  172. FServer := TServerThread.Create;
  173. FServer.Start;
  174. end;
  175. destructor TApp.Destroy;
  176. begin
  177. if Assigned(FServer) and not FServer.Finished then
  178. begin
  179. FServer.FreeOnTerminate := False;
  180. FServer.Terminate;
  181. FServer.TerminateClients;
  182. FreeAndNil(FServer);
  183. end;
  184. inherited Destroy;
  185. end;
  186. procedure TApp.Run;
  187. begin
  188. while not FServer.Finished do
  189. Sleep(100);
  190. end;
  191. begin
  192. with TApp.Create do
  193. try
  194. Run;
  195. finally
  196. Free;
  197. end;
  198. end.