L'envoi et de la réception d'un TMemoryStream à l'aide de IdTCPClient et IdTCPServer
J'ai trouvé Remy Lebeau la démo de chat de IdTCP composants dans XE2 et je voulais jouer avec elle un peu. (Il peut être trouvé ici) je voudrais envoyer une photo à l'aide de ces éléments et de la meilleure approche semble être l'utilisation d'TMemoryStream. Si je envoyer des chaînes, la connexion fonctionne très bien, les cordes sont transmises avec succès, cependant, quand je l'ai changer pour diffuser au lieu de cela, il ne fonctionne pas. Voici le code:
Serveur
procedure TMainForm.IdTCPServerExecute(AContext: TIdContext);
var rcvdMsg: string;
ms:TMemoryStream;
begin
// This commented code is working, it receives and sends strings.
// rcvdMsg:=AContext.Connection.IOHandler.ReadLn;
// LogMessage('<ServerExec> '+rcvdMsg);
//
// TResponseSync.SendResponse(AContext, rcvdMsg);
try
ms:=TMemoryStream.Create;
AContext.Connection.IOHandler.ReadStream(ms);
ms.SaveToFile('c:\networked.bmp');
except
LogMessage('Failed to receive',clred);
end;
end;
Client
procedure TfrmMain.Button1Click(Sender: TObject);
var ms: TMemoryStream;
bmp: TBitmap;
pic: TPicture;
s: string;
begin
// Again, this code is working for sending strings.
// s:=edMsg.Text;
// Client.IOHandler.WriteLn(s);
ms:=TMemoryStream.Create;
pic:=TPicture.Create;
pic.LoadFromFile('c:\Back.png');
bmp:=TBitmap.Create;
bmp.Width:=pic.Width;
bmp.Height:=pic.Height;
bmp.Canvas.Draw(0,0,pic.Graphic);
bmp.SaveToStream(ms);
ms.Position:=0;
Client.IOHandler.Write(ms);
ms.Free;
end;
Lorsque j'essaie d'envoyer le flux de la part du client, rien observables qui se passe (point d'arrêt dans le OnExecute ne pas le feu). Cependant, lors de la fermeture de programmes(après l'envoi de la MemoryStream), deux choses se produisent:
- Si le Client est fermé tout d'abord, alors seulement le
except
partie de traiter (le journal affiche le "pas d'erreur". Cependant, même si je place un point d'arrêt sur la première ligne de l'essai, à l'exception de bloc, de toute façon il a sauté et seul le message d'erreur est affiché). - Si le Serveur est fermé tout d'abord, l'IDE ne change pas de retour de debug, le Client ne change pas son état de déconnecté (comme il le fait normalement lorsque le serveur se déconnecte) et après que le Client est fermé ainsi, une erreur de Violation d'Accès de l'application de Serveur s'affiche. Je suppose que cela signifie qu'il y a un thread du Serveur toujours en cours d'exécution et le maintien de la connexion. Mais peu importe combien de temps je le donne, il ne se termine jamais la tâche de la réception de la MemoryStream.
Remarque: Le serveur utilise IdSchedulerOfThreadDefault
et IdAntiFreeze
, si ce qui compte.
Que je ne trouve pas de source fiable d'aide pour la nouvelle Indy 10 (il semble tout à appliquer pour les plus âgés d'Indy 10, ou même Indy 9), j'espère que vous pouvez me dire quel est le problème. Grâce
- RÉPONSE -
SERVEUR
procedure TMainForm.IdTCPServerExecute(AContext: TIdContext);
var size: integer;
ms:TMemoryStream;
begin
try
ms:=TMemoryStream.Create;
size:=AContext.Connection.IOHandler.ReadLongInt;
AContext.Connection.IOHandler.ReadStream(ms, size);
ms.SaveToFile('c:\networked.bmp');
except
LogMessage('Failed to receive',clred);
end;
end;
CLIENT
procedure TfrmMain.Button1Click(Sender: TObject);
var ms: TMemoryStream;
bmp: TBitmap;
pic: TPicture;
begin
ms:=TMemoryStream.Create;
pic:=TPicture.Create;
pic.LoadFromFile('c:\Back.png');
bmp:=TBitmap.Create;
bmp.Width:=pic.Width;
bmp.Height:=pic.Height;
bmp.Canvas.Draw(0,0,pic.Graphic);
bmp.SaveToStream(ms);
ms.Position:=0;
Client.IOHandler.Write(ms, 0, True);
ms.Free;
end;
OriginalL'auteur Martin Melka | 2012-08-28
Vous devez vous connecter pour publier un commentaire.
Suffit d'utiliser les bons paramètres:
sa fait la même chose, seulement que cette functunality est déjà inclus.
Génial, maintenant cela fonctionne même sans avoir besoin de déconnecter et de reconnecter le client. Je vais mettre à jour ma question pour le bien de l'intégrité. Parce que les réponses à la fois de vous les gars ont été pratiquement le même, je ne sais pas qui a donner le accepté de répondre à.. je vais le donner à la version la plus courte, mais merci néanmoins, whosrdaddy
C'est la meilleure réponse 🙂
Pour info, c'est la combinaison de la
AByteCount
etAReadUntilDisconnect
paramètres de travailler ensemble qui détermine siReadStream()
va s'attend à un précédent nombre d'octets ou pas. Ce n'est pas laAByteCount
paramètre par lui-même. Seulement quandAByteCount=-1
etAReadUntilDisconnect=False
seraReadStream()
s'attendre à un précédent nombre d'octets. Et ce sont les valeurs par défaut pour les deux paramètres.OriginalL'auteur markus_ja
Envoyer la taille du flux initial de sorte que le serveur ne sait combien d'octets il faut lire.
Serveur:
Client (ressources Fixes de manutention)
Le serveur tente pour recevoir la prochaine image dans l'Exécution de la boucle. Débranchez simplement le client après l'envoi de l'image devrait résoudre le problème que le serveur à l'avis de la socket fermée et s'arrête.
Est-ce vraiment la bonne façon? Je veux dire, j'ai peut-être envoyer plus de photos, uniquement sur le client le demande, de sorte que la connexion et la déconnexion de tous les temps semble un peu bizarre pour moi. De toute façon, OnExecute ne doit être déclenché lorsque les données sur le serveur, ce n'est pas une boucle, non?
c'EST une boucle.
ne pas avaler les exceptions dans le gestionnaire Execute comme Indy utilise des exceptions pour détecter la déconnexion. C'est ce qui explique pourquoi le serveur convives coincé. Et btw, l'envoi d'images dans une boucle sans déconnecter fonctionne très bien avec le code ci-dessus.
OriginalL'auteur whosrdaddy