2010-12-05 4 views
5

J'ai expérimenté un peu avec des messages de socket TCP asynchrone entre deux programmes, pour transmettre des données, des nombres et/ou du texte. Ce que j'ai fait est d'utiliser un mot-clé au début de chaque message, puis séparer les valeurs avec le "|" personnage. Ainsi, un message peut ressembler à ceci:Comment séparer les messages de socket TCP

"DATA | 490 | 40517,9328222222 | 1 | 6 | 11345 | 11347 | 11344 | 11345 | 106 | 40517,8494212963"

I définir la taille de la mémoire tampon de lecture à 1024, comme la plupart des messages seront dans cette longueur. Cependant parfois je peux envoyer rapidement de nombreux messages courts où plusieurs ensemble sont moins de 1024 caractères, et il semble alors qu'il sera lu en une seule fois. Et si j'envoie un message de plus de 1024 caractères, il sera divisé. Donc, je cherche des conseils sur la façon de gérer cela. Dois-je utiliser des caractères spéciaux pour démarrer et/ou terminer chaque message? J'apprécierais quelques conseils sur la façon dont vous faites ceci ..

Répondre

5

Le moyen le plus simple serait d'envoyer la longueur du message au début de chaque message, sérialisé de telle sorte qu'il fonctionnera sur le matériel little-endian et big-endian .

Cela pourrait aider votre récepteur à préallouer son tampon de réception de manière efficace.

+0

Merci! Qu'est-ce que vous voulez dire par sérialisation? Cela s'applique-t-il aux ordinateurs fonctionnant sous Windows standard? Avec votre dernier commentaire, cela signifie-t-il que je devrais changer la taille de la mémoire tampon en fonction du message reçu? Comment cela fonctionnera-t-il? Puisque la longueur du message n'est pas connue tant que le message n'a pas déjà été lu, je ne comprends pas exactement ce que vous voulez dire. Btw; Est-ce utile de diviser un message du côté de l'expéditeur ou cela n'aura-t-il aucun impact sur les performances? La taille sera un message de 50 caractères toutes les 200 ms, et rarement un message de 50 000 à 400 000 caractères. – bretddog

+0

La sérialisation signifie simplement "sortie en tant que chaîne". La suggestion de @terminus serait un moyen raisonnable de le faire - convertir la longueur du message en une chaîne de longueur fixe afin qu'elle soit facilement reconvertie en un '' non signé '' du côté réception. Vous pouvez demander à lire ces nombreux octets d'abord dans un tampon de taille fixe, puis allouer un tampon pour recevoir le reste du message. Ne vous embêtez pas à diviser le message du côté émission: la pile TCP/IP effectuera la mise en paquets requise. –

+0

bravo! Je pense que je l'ai compris maintenant :) – bretddog

3

Le moyen le plus simple serait d'envoyer la taille du message au début du paquet. De cette façon, vous savez combien de données lire. Donc, cela ressemblerait à:

00015MESSAGE|1|2 ... 

Il est important que le champ de taille ait une taille fixe.

Vous pouvez également faire en sorte que ce champ de taille soit binaire, mais il semble que vous envoyez du texte brut afin que vous disposiez d'un champ de taille lisible par l'utilisateur.

0

Vous pouvez résoudre ce problème en remplissant vos messages avec des octets uniques (comme 255 qui n'apparaissent pas en ASCII) à la taille de la mémoire tampon et en les décompressant du côté réception. Pour moi ce n'est pas une solution très agréable et intelligente, mais cela fonctionne réellement. Vous pouvez également essayer d'envoyer la longueur totale du paquet au début de chaque paquet, ce qui est un peu plus difficile et fonctionne plus efficacement comme la technique de remplissage lorsqu'il est bien fait. paquets seraient alors fusionnés ressembler à quelque chose comme ça (schéma):

05|.....02|..03|... 
0

La RAT façon le fait, est d'utiliser des blocs de taille fixe. Chaque bloc dans TAR est de 512 octets, et le fichier (message) peut être entièrement contenu dans ce bloc. Si ce n'est pas le cas, les 512 premiers octets incluent un en-tête qui spécifie combien de blocs supplémentaires doivent être lus pour ce fichier (message).

Tar n'est évidemment pas une application TCP, mais elle a des exigences d'analyse ou de traitement des données similaires.

Votre taille est également inférieure à 512 octets, mais il est peut-être judicieux d'inclure un bloc de 64 octets, 128 ou autre, et d'envoyer toutes vos données dans des packages de cette taille. vous perdez de l'efficacité avec la surcharge de la "taille de la boîte", mais vous pouvez gagner en efficacité et en simplicité de l'algorithme de traitement des données.

1

Il existe plusieurs approches.

  1. Un mot de longueur préfixé à chaque message.

  2. Un habillage de style STX/ETX de chaque message afin que vous puissiez voir où il commence et se termine. Cela nécessite l'échappement des octets ETX qui se produisent dans les données, ce qui nécessite également l'échappement des octets ESC.

  3. Un protocole autodescriptif, par exemple XML, ou un protocole basé sur les valeurs de type.

+0

L'OP doit déjà échapper les caractères '|' qui apparaissent dans les données, ce qui peut ne pas être un fardeau. – caf

1

Le protocole est tout. Pour ma application de chat J'utilise le protocole argument comme lorsque vous exécutez

shutdown.exe -s -f -t 30 

Mais pour les sockets J'utilise cette

join John%20Doe   ' %20 for space 
msg This%20Is%20a%20test ' again %20 for space 

De cette façon, peu importe si vos données envoyer ASYNC: D Hope this aide

Questions connexes