source: PinConnection/CommTCPServer.pas

Last change on this file was 575, checked in by chronos, 5 months ago
  • Modified: Remove U prefix from unit names of PinConnection package.
File size: 5.3 KB
Line 
1unit CommTCPServer;
2
3interface
4
5uses
6 Classes, SysUtils, blcksock, synsock, CommPin, Common, Threading,
7 DateUtils, SpecializedList;
8
9type
10 TCommTCPServer = class;
11
12 TReceiveDataEvent = procedure(Stream: TMemoryStream) of object;
13
14 { TCommSocketReceiveThread }
15
16 TCommSocketReceiveThread = class(TListedThread)
17 public
18 Parent: TCommTCPServer;
19 Stream: TListByte;
20 procedure Execute; override;
21 constructor Create(CreateSuspended: Boolean;
22 const StackSize: SizeUInt = DefaultStackSize);
23 destructor Destroy; override;
24 end;
25
26 TSocketConnectEvent = procedure(Sender: TCommTCPServer; Pin: TCommPin) of object;
27
28 { TCommTCPServerSession }
29
30 TCommTCPServerSession = class
31 private
32 procedure ReceiveData(Sender: TCommPin; Stream: TListByte);
33 public
34 Server: TCommTCPServer;
35 Socket: TTCPBlockSocket;
36 Pin: TCommPin;
37 constructor Create;
38 destructor Destroy; override;
39 end;
40
41 { TCommTCPServer }
42
43 TCommTCPServer = class(TCommNode)
44 private
45 FActive: Boolean;
46 FOnConnect: TSocketConnectEvent;
47 FOnDisconnect: TSocketConnectEvent;
48 //FOnReceiveData: TReceiveDataEvent;
49 FReceiveThread: TCommSocketReceiveThread;
50 protected
51 procedure SetActive(const AValue: Boolean); override;
52 public
53 Sessions: TListObject; // TListObject<TCommTCPServerSession>
54 Socket: TTCPBlockSocket;
55 Address: string;
56 Port: Word;
57 property Active: Boolean read FActive write SetActive;
58 property OnConnect: TSocketConnectEvent read FOnConnect write FOnConnect;
59 property OnDisconnect: TSocketConnectEvent read FOnDisconnect write FOnDisconnect;
60 constructor Create(AOwner: TComponent); override;
61 destructor Destroy; override;
62 end;
63
64
65implementation
66
67{ TCommTCPServerSession }
68
69procedure TCommTCPServerSession.ReceiveData(Sender: TCommPin; Stream: TListByte);
70var
71 Mem: TMemoryStream;
72begin
73 try
74 Mem := TMemoryStream.Create;
75 Stream.WriteToStream(Mem);
76 Mem.Position := 0;
77 Socket.SendStreamRaw(Mem);
78 finally
79 Mem.Free;
80 end;
81end;
82
83constructor TCommTCPServerSession.Create;
84begin
85 Socket := TTCPBlockSocket.Create;
86 Pin := TCommPin.Create;
87 Pin.OnReceive := ReceiveData;
88 Pin.Node := Server;
89end;
90
91destructor TCommTCPServerSession.Destroy;
92begin
93 FreeAndNil(Pin);
94 FreeAndNil(Socket);
95 inherited;
96end;
97
98{ TCommSocketReceiveThread }
99
100procedure TCommSocketReceiveThread.Execute;
101var
102 InBufferUsed: Integer;
103 Buffer: array of Byte;
104 NewSocket: TSocket;
105 NewSession: TCommTCPServerSession;
106 I: Integer;
107 DoSleep: Boolean;
108begin
109 with Parent do begin
110 repeat
111 DoSleep := True;
112
113 // Check if new connection is available
114 if Assigned(Socket) then
115 with Socket do
116 if CanRead(0) then begin
117 NewSocket := Accept;
118 if Assigned(FOnConnect) then begin
119 NewSession := TCommTCPServerSession.Create;
120 NewSession.Server := Parent;
121 NewSession.Socket.Socket := NewSocket;
122 if Assigned(FOnConnect) then FOnConnect(Parent, NewSession.Pin);
123 Parent.Sessions.Add(NewSession);
124 DoSleep := False;
125 end;
126 end;
127
128 // Check available data on all opened sockets
129 for I := 0 to Sessions.Count - 1 do
130 with TCommTCPServerSession(Sessions[I]) do begin
131 InBufferUsed := Socket.WaitingData;
132 if (not Pin.Connected) or (Socket.Socket = INVALID_SOCKET) or
133 (Socket.LastError <> 0) then begin
134 if Assigned(FOnDisconnect) then FOnDisconnect(Self.Parent, Pin);
135 end;
136
137 if InBufferUsed > 0 then begin
138 SetLength(Buffer, InBufferUsed);
139 Socket.RecvBuffer(Buffer, Length(Buffer));
140 //if Socket.Socket = INVALID_SOCKET then Break;
141
142 Stream.Count := Length(Buffer);
143 Stream.ReplaceBuffer(0, PByte(Buffer)^, Length(Buffer));
144 Pin.Send(Stream);
145 DoSleep := False;
146 end;
147 end;
148 if DoSleep and not Terminated then Sleep(1);
149 until Terminated;
150 end;
151end;
152
153constructor TCommSocketReceiveThread.Create(CreateSuspended: Boolean;
154 const StackSize: SizeUInt);
155begin
156 inherited;
157 Stream := TListByte.Create;
158end;
159
160destructor TCommSocketReceiveThread.Destroy;
161begin
162 FreeAndNil(Stream);
163 inherited;
164end;
165
166{ TCommTCPServer }
167
168procedure TCommTCPServer.SetActive(const AValue: Boolean);
169begin
170 if FActive = AValue then Exit;
171 FActive := AValue;
172
173 if AValue then begin
174 Socket.Bind(Address, IntToStr(Port));
175 if Socket.LastError <> 0 then raise Exception.Create('Bind error' + Socket.GetErrorDesc(Socket.LastError));
176 Socket.Listen;
177 if Socket.LastError <> 0 then raise Exception.Create('Listen error');
178 FReceiveThread := TCommSocketReceiveThread.Create(True);
179
180 FReceiveThread.FreeOnTerminate := False;
181 FReceiveThread.Parent := Self;
182 FReceiveThread.Start;
183 end else begin
184 Socket.CloseSocket;
185 FReceiveThread.Terminate;
186 FReceiveThread.WaitFor;
187 FreeAndNil(FReceiveThread);
188 end;
189end;
190
191constructor TCommTCPServer.Create(AOwner: TComponent);
192begin
193 inherited;
194 Sessions := TListObject.Create;
195 Socket := TTCPBlockSocket.Create;
196end;
197
198destructor TCommTCPServer.Destroy;
199begin
200 Active := False;
201 FreeAndNil(Socket);
202 FreeAndNil(Sessions);
203 inherited;
204end;
205
206end.
207
Note: See TracBrowser for help on using the repository browser.