(08-22-2018, 07:19 PM)krshin Wrote: I get memory error I try few scenarios with write but same error is here :-(
You need to keep the TIdTCPServer.Contexts list locked while you iterate through it, otherwise clients are free to (dis)connect from/to the server, modifying the contents of the list, while you are accessing it.
(08-22-2018, 07:19 PM)krshin Wrote: Is there some solution to send bytes, because another site is hardware with firmware who need array of bytes in TCP connection.
To send a byte array, use the TIdIOHandler.Write(TIdBytes) method instead of the TIdIOHandler.WriteLn(string) method. Also, TIdIOHandler.WriteLn() is subject to charset encoding, so you are going to corrupt your bytes sending them as a string anyway.
Try this:
Code:
procedure TFServer.btnSendClick(Sender: TObject);
var
bytes: TIdBytes;
tmpList: TList;
contexClient: TIdContext;
i: Integer;
begin
SetLength(bytes, 3);
bytes[0] := $ea;
bytes[1] := $89;
bytes[2] := $ef;
tmpList := IdTCPServer.Contexts.LockList;
try
for i := 0 to tmpList.Count-1 do
begin
contexClient := TIdContext(tmpList[i]);
if contexClient <> nil then
try
contexClient.Connection.IOHandler.Write(bytes);
except
end;
end;
finally
IdTCPServer.Contexts.UnlockList;
end;
end;
That being said, if your TIdTCPServer.OnExecute event handler also sends any data to clients, then this approach becomes very dangerous, as you risk inter-mixing your bytes with other data that OnExecute may send, corrupting your communications. In which case, the safer approach is to delegate the sending of the bytes to the OnExecute event handler, and let it decide when it is safe to send the bytes. For example:
Code:
procedure TFServer.bIdTCPServerConnect(AContext: TIdContext);
begin
AContext.Data := TIdThreadSafeList.Create;
end;
procedure TFServer.IdTCPServerDisconnect(AContext: TIdContext);
var
Data: TIdThreadSafeList;
tmpList: TList;
i: Integer;
P: Pointer;
begin
Data := TIdThreadSafeList(AContext.Data);
AContext.Data := nil;
try
tmpList := Data.LockList;
try
for i := 0 to tmpList.Count-1 do
begin
P := tmpList[i];
TIdBytes(P) := nil;
end;
finally
Data.UnlockList;
end;
finally
Data.Free;
end;
end;
procedure TFServer.bIdTCPServerExecute(AContext: TIdContext);
var
Data: TIdThreadSafeList;
tmpList: TList;
bytes: TIdBytes;
begin
...
Data := TIdThreadSafeList(AContext.Data);
tmpList := Data.LockList;
try
while tmpList.Count > 0 do
begin
bytes := TIdBytes(tmpList[0]);
tmpList.Delete(0);
AContext.Connection.IOHandler.Write(bytes);
bytes := nil;
end;
finally
Data.UnlockList;
end;
...
end;
procedure TFServer.btnSendClick(Sender: TObject);
var
tmpList: TList;
contexClient: TidContext;
i: integer;
bytes: TIdBytes;
begin
tmpList := IdTCPServer.Contexts.LockList;
try
for i := 0 to tmpList.Count-1 do
begin
contexClient := TIdContext(tmpList[i]);
if (contexClient <> nil) and (contexClient.Data <> nil) then
begin
SetLength(bytes, 3);
bytes[0] := $ea;
bytes[1] := $89;
bytes[2] := $ef;
TIdThreadSafeList(contexClient.Data).Add(Pointer(bytes));
Pointer(bytes) := nil;
end;
end;
finally
IdTCPServer.Contexts.UnlockList;
end;
end;