source: PinConnection/UCommTCPClient.pas

Last change on this file was 440, checked in by chronos, 12 years ago
  • Fixed: Thread safe access to serial port pin interface using lock.
File size: 3.8 KB
Line 
1unit UCommTCPClient;
2
3{$mode Delphi}{$H+}
4
5interface
6
7uses
8 Classes, SysUtils, blcksock, synsock, UCommPin, UCommon, UThreading,
9 DateUtils, SpecializedList;
10
11type
12 TCommTCPClient = class;
13
14 TReceiveDataEvent = procedure(Stream: TMemoryStream) of object;
15
16 { TCommSocketReceiveThread }
17
18 TCommSocketReceiveThread = class(TListedThread)
19 public
20 Parent: TCommTCPClient;
21 Stream: TListByte;
22 procedure Execute; override;
23 constructor Create(CreateSuspended: Boolean;
24 const StackSize: SizeUInt = DefaultStackSize);
25 destructor Destroy; override;
26 end;
27
28 { TCommTCPClient }
29
30 TCommTCPClient = class(TCommNode)
31 private
32 FActive: Boolean;
33 //FOnReceiveData: TReceiveDataEvent;
34 FReceiveThread: TCommSocketReceiveThread;
35 procedure ReceiveData(Sender: TCommPin; Stream: TListByte);
36 protected
37 procedure SetActive(const AValue: Boolean); override;
38 procedure AssignTo(Dest: TPersistent); override;
39 public
40 Socket: TTCPBlockSocket;
41 Pin: TCommPin;
42 Address: string;
43 Port: Word;
44 property Active: Boolean read FActive write SetActive;
45 constructor Create(AOwner: TComponent); override;
46 destructor Destroy; override;
47 end;
48
49
50implementation
51
52resourcestring
53 SCantConnectToServer = 'Can''t connect to remote server';
54
55{ TCommTCPClient }
56
57procedure TCommTCPClient.ReceiveData(Sender: TCommPin; Stream: TListByte);
58var
59 Mem: TMemoryStream;
60begin
61 if FActive then begin
62 try
63 Mem := TMemoryStream.Create;
64 Stream.WriteToStream(Mem);
65 Mem.Position := 0;
66 Socket.SendStreamRaw(Mem);
67 finally
68 Mem.Free;
69 end;
70 end;
71end;
72
73procedure TCommTCPClient.SetActive(const AValue: Boolean);
74begin
75 if FActive = AValue then Exit;
76 FActive := AValue;
77
78 if AValue then begin
79 Socket.Connect(Address, IntToStr(Port));
80 if Socket.LastError <> 0 then begin
81 FActive := False;
82 raise Exception.Create(SCantConnectToServer);
83 end;
84 FReceiveThread := TCommSocketReceiveThread.Create(True);
85
86 FReceiveThread.FreeOnTerminate := False;
87 FReceiveThread.Parent := Self;
88 FReceiveThread.Start;
89 end else begin
90 Socket.CloseSocket;
91 FReceiveThread.Terminate;
92 FReceiveThread.WaitFor;
93 FreeAndNil(FReceiveThread);
94 end;
95end;
96
97procedure TCommTCPClient.AssignTo(Dest: TPersistent);
98begin
99 if Dest is TCommTCPClient then begin
100 TCommTCPClient(Dest).Address := Address;
101 TCommTCPClient(Dest).Port := Port;
102 end
103 else inherited;
104end;
105
106constructor TCommTCPClient.Create(AOwner: TComponent);
107begin
108 inherited;
109 Socket := TTCPBlockSocket.Create;
110 Pin := TCommPin.Create;
111 Pin.OnReceive := ReceiveData;
112 Pin.Node := Self;
113end;
114
115destructor TCommTCPClient.Destroy;
116begin
117 Active := False;
118 Socket.Free;
119 Pin.Free;
120 inherited Destroy;
121end;
122
123{ TCommSocketReceiveThread }
124
125procedure TCommSocketReceiveThread.Execute;
126var
127 InBufferUsed: Integer;
128 Buffer: array of Byte;
129begin
130 InBufferUsed := 0;
131 with Parent do begin
132 repeat
133 if InBufferUsed = 0 then Sleep(1);
134 //else Yield;
135 if Assigned(Socket) then
136 with Socket do
137 if CanRead(0) then begin
138 InBufferUsed := WaitingData;
139 if InBufferUsed > 0 then begin
140 SetLength(Buffer, InBufferUsed);
141 RecvBuffer(Buffer, Length(Buffer));
142
143 Stream.Count := Length(Buffer);
144 Stream.ReplaceBuffer(0, Pointer(Buffer)^, Length(Buffer));
145 Pin.Send(Stream);
146 end else InBufferUsed := 0;
147 end else InBufferUsed := 0;
148 until Terminated;
149 end;
150end;
151
152constructor TCommSocketReceiveThread.Create(CreateSuspended: Boolean;
153 const StackSize: SizeUInt);
154begin
155 inherited;
156 Stream := TListByte.Create;
157end;
158
159destructor TCommSocketReceiveThread.Destroy;
160begin
161 Stream.Free;
162 inherited;
163end;
164
165end.
166
Note: See TracBrowser for help on using the repository browser.