Myślę że na forum powinno się pomagać bardziej początkującym użytkownikom, zamiast odsyłać ich do Google, gdzie już od pewnego czasu szukam informacji o synchronizacji wątków.
Nie widziałem sensu w umieszczaniu kodu, ale mogę dać ;).
Przepraszam że trochę zasyfiony.
Unit1:
Kopiuj
unit Unit1;
{$mode objfpc}{$H+}
interface
uses
{$IFDEF UNIX}{$IFDEF UseCThreads}cthreads, cmem,{$ENDIF}{$ENDIF}
Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls,
blcksock, Unit2, Unit3, ExtCtrls, Unit5;
type
TForm1 = class(TForm)
Button1: TButton;
Button2: TButton;
Edit1: TEdit;
Edit2: TEdit;
Edit3: TEdit;
GroupBox1: TGroupBox;
GroupBox2: TGroupBox;
Label1: TLabel;
ToggleBox1: TToggleBox;
ToggleBox2: TToggleBox;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
procedure Button3Click(Sender: TObject);
procedure Edit1Change(Sender: TObject);
procedure Label1Click(Sender: TObject);
procedure ToggleBox1Change(Sender: TObject);
procedure ToggleBox2Change(Sender: TObject);
private
public
end;
var
Form1: TForm1;
implementation
{$R *.lfm}
var tueserWer:TUEServerThread;
var tueKlient:TUEClient;
procedure TForm1.Button2Click(Sender: TObject);
begin
tueklient.sendecho(edit2.text);
end;
procedure TForm1.Button3Click(Sender: TObject);
begin
end;
procedure TForm1.Edit1Change(Sender: TObject);
begin
end;
procedure TForm1.Label1Click(Sender: TObject);
begin
Label1.caption:=buforek;
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
tueklient := tueclient.create();
TUEKlient.Connect(Edit3.Text);
end;
procedure TForm1.ToggleBox1Change(Sender: TObject);
begin
ajpi:=Edit1.text;
if ToggleBox1.Checked=true then
begin
tueserwer:=tueserverthread.create(false);
ToggleBox1.Caption:='Stop';
end
else begin
tueserwer.destroy;
ToggleBox1.Caption:='Start';
end;
end;
procedure TForm1.ToggleBox2Change(Sender: TObject);
begin
if ToggleBox2.Checked=true then
begin
tueklient := tueclient.create();
TUEKlient.Connect(Edit3.Text);
ToggleBox2.Caption:='Disconnect';
end
else begin
tueklient.Disconnect;
tueklient.Destroy;
ToggleBox2.Caption:='Connect';
end;
end;
end.
Unit2:
Kopiuj
unit Unit2;
{$mode objfpc}{$H+}
interface
uses
{$IFDEF UNIX}{$IFDEF UseCThreads}cthreads, cmem,{$ENDIF}{$ENDIF}
Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls,
blcksock, ExtCtrls, Unit5;
type
TUEServerThread = class(TThread)
protected
procedure Execute; override;
end;
TUEServer = class
private
FUEServerThread: TUEServerThread;
function GetRunning: Boolean;
public
procedure Stop;
procedure Start;
property Running: Boolean read GetRunning;
end;
implementation
function TUEServer.GetRunning: Boolean;
begin
Result := FUEServerThread <> nil;
end;
procedure TUEServer.Start;
begin
FUEServerThread := TUEServerThread.Create(False);
end;
procedure TUEServer.Stop;
begin
if FUEServerThread <> nil then
begin
FUEServerThread.Terminate;
FUEServerThread.WaitFor;
FreeAndNil(FUEServerThread);
end;
end;
procedure TUEServerThread.Execute;
var
Socket: TUDPBlockSocket;
Buffer: string;
Size: string;
begin
Socket := TUDPBlockSocket.Create;
try
Socket.Bind(ajpi, '7');
try
if Socket.LastError <> 0 then
begin
raise Exception.CreateFmt('Bind failed with error code %d', [Socket.LastError]);
Exit;
end;
while not Terminated do
begin
Buffer := Socket.RecvPacket(1000);
if Socket.LastError = 0 then
begin
Socket.SendString(Buffer);
end;
if Buffer = '' then
Sleep(10) else begin showmessage(Buffer); end;
end;
finally
Socket.CloseSocket;
end;
finally
Socket.Free;
end;
end;
end.
Unit3:
Kopiuj
unit Unit3;
{$mode objfpc}{$H+}
interface
uses
{$IFDEF UNIX}{$IFDEF UseCThreads}cthreads, cmem,{$ENDIF}{$ENDIF}
{$IFDEF WINDOWS}Windows,{$ENDIF}Classes, SysUtils, DateUtils,
blcksock;
const
cReceiveTimeout = 2000;
cBatchSize = 100;
type
TUEClient = class
private
FSocket: TUDPBlockSocket;
FResponseTime: Int64;
public
constructor Create;
destructor Destroy; override;
procedure Disconnect;
function Connect(const Address: string): Boolean;
function SendEcho(const Message: string): string;
property ReponseTime: Int64 read FResponseTime;
end;
TUEAnalyzerThread = class(TThread)
private
FAddress: string;
FBatchDelay: Cardinal;
FDropedPackets: Cardinal;
FAverageResponse: Extended;
FCriticalSection: TRTLCriticalSection;
function GetAverageResponse: Extended;
function GetDropedPackets: Cardinal;
protected
procedure Execute; override;
public
destructor Destroy; override;
constructor Create(const Address: string; const BatchDelay: Cardinal);
property DropedPackets: Cardinal read GetDropedPackets;
property AverageResponse: Extended read GetAverageResponse;
end;
TUEAnalyzer = class
private
FAddress: string;
FBatchDelay: Cardinal;
FAnalyzerThread: TUEAnalyzerThread;
function GetAverageResponse: Extended;
function GetDropedPackets: Cardinal;
function GetRunning: Boolean;
public
procedure StopAnalyzer;
procedure StartAnalyzer;
property Running: Boolean read GetRunning;
property Address: string read FAddress write FAddress;
property DropedPackets: Cardinal read GetDropedPackets;
property AverageResponse: Extended read GetAverageResponse;
property BatchDelay: Cardinal read FBatchDelay write FBatchDelay;
end;
implementation
function TUEAnalyzerThread.GetAverageResponse: Extended;
begin
EnterCriticalsection(FCriticalSection);
try
Result := FAverageResponse;
finally
LeaveCriticalsection(FCriticalSection);
end;
end;
function TUEAnalyzerThread.GetDropedPackets: Cardinal;
begin
EnterCriticalsection(FCriticalSection);
try
Result := FDropedPackets;
finally
LeaveCriticalsection(FCriticalSection);
end;
end;
procedure TUEAnalyzerThread.Execute;
var
UEClient: TUEClient;
Connected: Boolean;
SendString: string;
SendCounter: Int64;
SumResponse: Cardinal;
SumDropedPackets: Cardinal;
begin
UEClient := TUEClient.Create;
try
Connected := UEClient.Connect(FAddress);
try
if not Connected then
begin
raise Exception.CreateFmt('Could not connect UPD client to address %s', [FAddress]);
Exit;
end;
SumDropedPackets := 0;
FAverageResponse := 0;
FDropedPackets := 0;
SumResponse := 0;
SendCounter := 1;
while not Terminated do
begin
SendString := IntToStr(SendCounter);
if not (UEClient.SendEcho(SendString) = SendString) then
Inc(SumDropedPackets);
Inc(SumResponse, UEClient.ReponseTime);
Inc(SendCounter);
if (SendCounter mod cBatchSize) = 0 then
begin
EnterCriticalsection(FCriticalSection);
try
FAverageResponse := SumResponse / cBatchSize;
FDropedPackets := SumDropedPackets;
finally
LeaveCriticalsection(FCriticalSection);
end;
Sleep(FBatchDelay * 1000);
SumDropedPackets := 0;
SumResponse := 0;
end;
Sleep(10);
end;
finally
UEClient.Disconnect;
end;
finally
UEClient.Free;
end;
end;
destructor TUEAnalyzerThread.Destroy;
begin
{$IFDEF MSWINDOWS}
DeleteCriticalSection(FCriticalSection)
{$ELSE}
DoneCriticalSection(FCriticalSection)
{$ENDIF};
inherited Destroy;
end;
constructor TUEAnalyzerThread.Create(const Address: string; const BatchDelay: Cardinal);
begin
{$IFDEF MSWINDOWS}
InitializeCriticalSection(FCriticalSection)
{$ELSE}
InitCriticalSection(FCriticalSection)
{$ENDIF};
FBatchDelay := BatchDelay;
FreeOnTerminate := True;
FAddress := Address;
inherited Create(False);
end;
procedure TUEAnalyzer.StartAnalyzer;
begin
FAnalyzerThread := TUEAnalyzerThread.Create(FAddress, FBatchDelay);
end;
function TUEAnalyzer.GetRunning: Boolean;
begin
Result := FAnalyzerThread <> nil;
end;
function TUEAnalyzer.GetAverageResponse: Extended;
begin
Result := FAnalyzerThread.AverageResponse;
end;
function TUEAnalyzer.GetDropedPackets: Cardinal;
begin
Result := FAnalyzerThread.DropedPackets;
end;
procedure TUEAnalyzer.StopAnalyzer;
begin
if Running then
begin
FAnalyzerThread.Terminate;
FAnalyzerThread := nil;
end;
end;
constructor TUEClient.Create;
begin
FSocket := TUDPBlockSocket.Create;
end;
destructor TUEClient.Destroy;
begin
FreeAndNil(FSocket);
inherited Destroy;
end;
procedure TUEClient.Disconnect;
begin
FSocket.CloseSocket;
end;
function TUEClient.Connect(const Address: string): Boolean;
begin
FSocket.Connect(Address, '7');
Result := FSocket.LastError = 0;
end;
function TUEClient.SendEcho(const Message: string): string;
var
StartTime: TDateTime;
begin
Result := '';
StartTime := Now;
FSocket.SendString(Message);
if FSocket.LastError = 0 then
begin
Result := FSocket.RecvPacket(cReceiveTimeout);
FResponseTime := MilliSecondsBetween(Now, StartTime);
if FSocket.LastError <> 0 then
begin
FResponseTime := -1;
Result := '';
end;
end;
end;
end.
Unit5:
Kopiuj
unit Unit5;
{$mode objfpc}{$H+}
interface
uses
{$IFDEF UNIX}{$IFDEF UseCThreads}cthreads, cmem,{$ENDIF}{$ENDIF}
Classes, SysUtils;
var ajpi:string;
implementation
end.