8
votes

Envoyer plus de données que ce qui peut être stocké dans l'envoi de tampon

J'utilise des sockets C # pour implémenter mon propre serveur RTSP de base (à des fins d'apprentissage). Je suis en train de rédiger la logique du serveur pour effectuer la poignée de main avec le client lors de la négociation des ports multimédia sur une demande décrite.

L'application client n'a pas été écrite par moi et je n'ai aucun accès pour mettre à jour le logiciel, C'est un simple client RTSP qui négocie des ports multimédias sur un routeur Cisco, puis des tuyaux audio aux clients qui y sont liés.

La charge utile que je souhaite renvoyer est 1024 octets et un en-tête 64 octets, et de ce que je peux voir d'inspecter mon application client, seuls 400 octets sont transmis au client. < p> La charge utile de réponse est définie en C # comme suit: xxx

la méthode de réponse répondable est implémentée comme suit: xxx < / pré>

avec un sendcallback Pour déterminer lorsque le paquet a été envoyé au client: xxx

Pourquoi mon application client reçoit-elle seulement 400 octets, et si oui, comment puis-je m'assurer que tout mon paquet est envoyé (j'utilise TCP)? Est-ce une limite dure définie par c #? J'ai consulté MSDN et n'a pas pu trouver d'informations pour soutenir cette théorie.

S'il y a plus de détails requis concernant la mise en œuvre de mon serveur, veuillez demander.

edit Voici quelques aliments pour la pensée, et je ne sais pas pourquoi cela se produirait, donc si quelqu'un pouvait éclairer que ce serait génial ... @ Gregory A Beamer suggéré dans les commentaires que se révèle pourrait tirer prématurément, est-ce une possibilité? De ma compréhension, je pensais que le rappel Async ne ferait que tirer une seule fois, et une fois que tous les octets avaient été envoyés du serveur à la prise cliente d'écoute.

Pour que je dise que le paquet n'était pas Entièrement reçu par le client, les informations suivantes indique que seulement 400 octets sont reçues par l'application client:

Entrez la description de l'image ici

prise en charge par une trace de fil de fil de S-> C

 Entrez la description de l'image ici

update Après avoir parlé plus tôt avec @usr, j'ai fait des tests supplémentaires et peut maintenant confirmer que l'application client ne recevra jamais une réponse de 400 octets de retour du serveur. I H xxx

^ Il s'agit de la trace du journal larguée par l'application client lorsque je connais ici le serveur, nous pouvons voir ici qu'il accepte 1384 octets de retour du client, Mais son tampon de traitement n'est capable que de stocker 400 octets. J'ai examiné un journal pour une application existante qui gère la diffusion en continu vers le même périphérique, et dans la trace Wireshark, au lieu d'envoyer l'en-tête dans un bloc, il envoie plusieurs morceaux avec l'info [segment TCP d'un PDU réassemblé ] Je ne suis pas sûr de ce que cela signifie (Nouveauté de Stuff Network), mais je suppose que cela décompose la charge utile du serveur et que je l'envoie dans plusieurs morceaux puis remontant sur le client pour gérer la demande. < p> Comment puis-je reproduire ce comportement sur mon application Server? J'ai essayé ce qui suit dans ma méthode de réponse, les espoirs que cela tuyerait le paquet et remontent sur le client, mais je viens de continuer à obtenir la même erreur décrite ci-dessus: xxx


13 commentaires

La limite de méthode d'envoi est System.int32


Je vois, comment puis-je vous assurer que l'ensemble du paquet est envoyé?


Obtenez-vous une exception? Je vois aussi que votre a = fmtp: 8 la ligne n'a pas de nouvelle ligne à la fin de celui-ci


À quoi ressemble la mise en œuvre du client? Cela pourrait provoquer le déclenchement des restes trop tôt. Juste une idée.


Obtenir des exceptions, je vais essayer d'ajouter la nouvelle ligne Nice Spot. Toutefois, sur le client, il n'imprime que v = 0


@Gommoryabeamer je n'ai pas accès à l'application client, son routeur Cisco avec un petit script sur celui-ci pour négocier la poignée de main de la RTSP, pensée intéressante que l'envoi final tire tôt, ce qui pourrait certainement être ce qui se passe


Notion de champ de gauche ... Toutes les chances d'une inadéquation duplex entre le client et le serveur?


@DAVIDW Merci pour vos commentaires - qu'est-ce qu'une inadéquation duplex? Comme indiqué ci-dessus, le réseau de réseau est nouveau pour moi!


Une inadéquation duplex est l'endroit où un côté d'une conversation peut envoyer simultanément du trafic dans les deux sens, mais l'autre extrémité ne peut aller qu'un seul moyen à la fois. Un symptôme normal de cela pourrait être une connexion autrement inexplicablement lente, mais je spéculerais sauvagement, peut-être que la défaillance de capturer plus que ces 400 octets n'aurait peut-être pas indiqué qu'elle ne résiste pas correctement avec l'autre côté, par exemple une inadéquation duplex. Probablement une idée folle, une mauvaise idée, jetant simplement sortir des notions de la boîte pour vous. Problème intéressant!


Merci pour l'idée David, je vais regarder davantage là car il peut briller de la lumière sur le problème! Cependant, il semble étrange que l'exécution du même test à plusieurs reprises avec plusieurs ou plusieurs clients connectés entraînerait des résultats constants de 400 octets collectés sur le client. Merci pour votre contribution :)


"a = mr: intGner; 0 \ n" + - Entier est orthographié


Merci @joephilllips, a fait le changement, malheureusement n'était pas le bogue;)


Pouvez-vous enregistrer avec WireShark la connexion de travail puis rejouer les données sur le paquet de périphérique par paquet? Il existe des wrappers .NET autour du format .PCAP où vous pouvez obtenir la charge utile de paquets TCP et la lecture sur l'appareil les données brutes. Si l'appareil est si simple, il pourrait être que sa mise en œuvre de la pile TCP est simplement défectueuse et impose des limites supplémentaires non écrites dans une norme.


3 Réponses :


2
votes

TCP est un flux intégré d'octets. Il n'y a pas de paquets perceptables aux applications. Lire / recevoir des appels renvoiez un certain nombre d'octets de manière non déterministe (au moins un). Dans le récepteur, vous devez traiter du fait que les lectures peuvent être partielles. Utilisez la valeur de retour de la réception pour déterminer le nombre d'octets reçus.

Ceci est tout plus facile si vous lisez de manière synchrone et utilisez binarinreader car il fait cette logique en boucle pour vous.

Beginson pourrait tirer prématurément, est-ce une possibilité

Non.


12 commentaires

Désolé, je voulais dire révèle mais je suppose que la réponse est toujours non (comme je la pensais). Le seul problème que j'ai avec cette application est que je n'ai aucun contrôle sur le client, son périphérique SIP et le logiciel client ne peuvent pas être modifiés (rend mon travail un peu plus fort). Est-ce que vous pouvez vous assurer de l'application serveur que tous les octets sont transmis à la prise d'écoute?


D'ACCORD. Notons d'abord que le client est cassé. Vous devriez être capable de faire un seul paquet TCP sortir en désactivant la nagage et effectuer exactement un appel de début. Utilisez WireShark pour confirmer que le paquet TCP laisse avec les données attendues 1024 + 64 octets de données. Ceci est un esprit de hack vous.; BTW, comment avez-vous déterminé que le client ne reçoit qu'une partie des données?


J'ai mis à jour ma question avec une trace Wireshark et un journal de l'application client


Je ne sais pas comment déboguer cela plus loin. La trace Wireshark ne montre rien comme un paquet avec 400 octets.


Je vois le paquet d'octet 1461 comme le gênant, le client répond avec un accusé de réception, mais il semble que cela n'accepte que 400 octets sur le client - peut-être que je devrais peut-être faire une boucle dans l'envoi Méthode et tuyau de 400 octets à une époque ou quelque chose, voir si cela fonctionne ... Cela semble tout simplement très bizarre (je suppose que le client pourrait avoir un tampon maximum de 400Byte à sa fin, cela aurait un sens ... mauvaise architecture ?! )


Quel logiciel client est-ce?


Il est utilisé pour une application de téléphonie, son routeur Cisco qui établit les ports multimédias via RTSP puis craignent l'audio à ses clients connectés. Je suppose que d'avoir un petit tampon de réception pourrait avoir un sens dans ce scénario? C'est tout les détails de la mise en œuvre que j'ai été donnés si


Étant donné que les messages semblent fréquemment plus gros que 400 octets, je doute que le client ne peut pas gérer cela. Je pense toujours que le bogue est à vous, mais je ne peux pas taper aucun problème. Peut-être qu'il y a un bogue dans un code qui n'est pas visible ici et vous envoyez simplement les mauvaises choses. Recherchez dans les paquets Wireshark ("Suivez le flux TCP") et assurez-vous que le contenu est correct.


Dans le flux TCP, tout le paquet est là, je viens de mettre à jour ma question


Nous progressons de ses progrès. Je ne suis pas envie de réfléchir à la logique de chunking compliquée là-bas ... utilisez Wireshark pour vous assurer que cela fonctionne. Assurez-vous de désactiver la nagage. Sinon, la pile TCP fusionnera ceux qui écrit ensemble.


Je pense aussi que la logique de chunking semble un peu gonflée pour ce que j'essaie d'atteindre. Je continuerai à creuser des paquets!


Des détails sur le routeur Cisco disponible? Le routeur pourrait-il faire une sorte de filtrage ou d'inspection qui s'arrête à une limite de 400 octets?



2
votes

Une réponse possible peut être que le client a défini une taille de bloc spécifique à votre serveur (voir 12.7 - https://www.ietf.org/rfc/rfc2326.txt ). Cela peut être applicable ou non, mais si vous pouviez décharger la demande que le client vous envoie et examine à travers cela, vous pouvez voir un blocsize indiqué quelque part autour de la marque 400.

edit: Vérifiez la réponse Alex 'Réponse ci-dessous pour la réponse finale.


1 commentaires

Malheureusement, j'ai passé beaucoup de temps à récurer la documentation RFC, mais je suis d'accord pour dire qu'il doit y avoir une sorte de capuchon souple sur le client. C'est juste ennuyeux comment l'application client est une boîte noire avec 0 documentation!



2
votes

Cela peut sembler controversé, mais le bogue dans le code était extrêmement idiot et je dois attribuer le succès de cette question à @ KeyZ182 dans les réponses. Après avoir discuté en privé, il remarqua que j'avais l'aide \ n pour ajouter de nouveaux éléments de ligne.

Le problème était que je devais modifier ces retours à \ r \ n et ajouter un entre l'en-tête et le corps pour dicter au client où l'en-tête s'est terminé et que les informations corporelles de la charge utile ont commencé. (frappe la tête contre le mur de briques).

Il s'avère qu'il n'y avait pas de tampon de 400 octets sur le client (alors je suis toujours amusé sur la raison pour laquelle il a parlé d'un tampon de traitement de 400 octets). Merci à tous pour votre aide!


2 commentaires

Cela peut avoir été la taille du tampon alloué à lire une seule ligne. Comme il ne voyait pas le CRLF, cela s'attendait, il a juste continué à lire jusqu'à ce que le tampon soit plein, avant de se rendre compte qu'il s'agissait d'une ligne invalide, à laquelle cela vient de fermer brusquement la connexion.


@ KeyZ182 qui fait le sens total maintenant que vous le dites - je manque toujours les petits détails ... merci encore pour votre aide