Delphi 2009, Indy 10, TIdTCPServer.OnExecute, comment saisir tous les octets dans le InputBuffer
-
23-08-2019 - |
Question
Je suis de déconner avec l'Indy 10 fourni avec Delphi 2009 et ai du mal à obtenir toutes les données de la IOHandler quand OnExecute incendies ...
procedure TFormMain.IdTCPServerExecute(AContext: TIdContext);
var
RxBufStr: UTF8String;
RxBufSize: Integer;
begin
if AContext.Connection.IOHandler.Readable then
begin
RxBufSize := AContext.Connection.IOHandler.InputBuffer.Size;
if RxBufSize > 0 then
begin
SetLength(RxBufStr, RxBufSize);
AContext.Connection.IOHandler.ReadBytes(TBytes(RxBufStr), RxBufSize, False);
end;
end;
end;
AContext.Connection.IOHandler.InputBuffer.Size ne semble pas fiable et retourne souvent 0, mais sur la prochaine course throug le OnExecute il va prendre le bon nombre d'octets, mais trop tard.
Essentiellement, je veux être en mesure de saisir simplement toutes les données, le farcir dans un UTF8String ( pas une chaîne Unicode), puis analyser pour un marqueur spécial. Donc, je n'ai pas en-têtes et les messages sont de longueur variable. Il semble que les Indy 10 IOHandlers ne sont pas configuré pour cela ou je suis juste en utilisant mal.
Il serait bien de faire quelque chose comme passer un tampon d'une certaine taille, remplir autant que possible et renvoyer le nombre d'octets remplis puis continuer s'il y a plus.
En aparté ce qui est de l'état TIdSchedulerOfFiber, cela semble très intéressant, ça marche? Quelqu'un est-il l'utiliser? Je remarque que ce n'est pas dans la norme de l'installation Delphi 2009 cependant.
Mise à jour: J'ai trouvé Msg: = AContext.Connection.IOHandler.ReadLn (# 0, enUTF8); qui fonctionne, mais je voudrais encore connaître la réponse à la question ci-dessus, est-ce parce qu'elle est basée sur le blocage IO? Ce qui rend encore plus vif sur cette TIdSchedulerOfFiber.
La solution
Vous ne devriez pas utiliser Readable () comme ça. Essayez ce qui suit à la place:
procedure TFormMain.IdTCPServerExecute(AContext: TIdContext);
var
RxBuf: TIdBytes;
begin
RxBuf := nil;
with AContext.Connection.IOHandler do
begin
CheckForDataOnSource(10);
if not InputBufferIsEmpty then
begin
InputBuffer.ExtractToBytes(RxBuf);
// process RxBuf as needed...
end;
end;
end;
Vous pouvez également:
procedure TFormMain.IdTCPServerExecute(AContext: TIdContext);
var
RxBufStr: String; // not UTF8String
begin
with AContext.Connection.IOHandler do
begin
CheckForDataOnSource(10);
if not InputBufferIsEmpty then
begin
RxBufStr := InputBuffer.Extract(-1, enUtf8);
// Alternatively to above, you can set the
// InputBuffer.Encoding property to enUtf8
// beforehand, and then call TIdBuffer.Extract()
// without any parameters.
//
// Or, set the IOHandler.DefStringEncoding
// property to enUtf8 beforehand, and then
// call TIdIOHandler.InputBufferAsString()
// process RxBufStr as needed...
end;
end;
end;
En ce qui concerne TIdSchedulerOfFiber - le paquet SuperCore est effectivement mort à ce moment. Il n'a pas été travaillé dans un temps très long, et n'est pas mise à jour avec la dernière architecture Indy 10. Nous pouvons essayer de ressusciter à une date ultérieure, mais ce n'est pas dans nos plans pour l'avenir proche.
Autres conseils
procedure TFormMain.IdTCPServerExecute(AContext: TIdContext);
var
RxBufStr: UTF8String;
RxBufSize: Integer;
begin
if AContext.Connection.IOHandler.Readable then
begin
AContext.Connection.IOHandler.ReadBytes(TBytes(RxBufStr),-1, False);
end;
end;