7
votes

Envoyer un fichier volumineux sur la connexion TCP

Je dois envoyer quelques fichiers volumineux à un ordinateur sur Internet. En conséquence, j'ai ouvert les ports que je prévois d'utiliser sur le routeur et transmettez les adresses IP correspondantes. Quoi qu'il en soit, laissez-moi vous montrer les classes que je travaille pour y parvenir. Ces cours fonctionnent bien avec de petits fichiers mais parfois ils échouent avec de grands fichiers.

Voici le code du serveur: (c'est une application de console) xxx

et le code de mon client est le suivant: xxx < / pré>

La manière dont j'instécie la classe client consiste à fournir l'adresse IP du serveur comme suit: xxx

Le serveur doit être exécuté d'abord avant d'exécuter ce code .

Je ne sais pas pourquoi est si compliqué pour envoyer un fichier sur Internet en utilisant des sockets. Je n'ai pas Konw WCF C'est pourquoi j'ai perdu beaucoup de temps à la création de ces classes. Il y a peut-être déjà des classes intégrées qui me permettront d'envoyer des fichiers sur Internet à un ordinateur différent. Je sais juste les bases de la mise en réseau de sa mise en réseau, ce sera bien si je pouvais le faire avec une classe simple. Je ne soussets pas pourquoi mes cours ne fonctionnent pas tout le temps? Si j'augmente la taille du tampon, mes cours seront-ils plus efficaces? Dois-je attendre ou mettre en pause mon programme un peu avant d'envoyer plus d'octets? Ce sera bien si quelqu'un peut me dire ce qui ne va pas avec ces classes. Ils fonctionnent bien avec de petits fichiers mais avec de gros fichiers parfois, il ne fonctionne pas ...


1 commentaires

Pensez à utiliser PacketProtocol blog.stephancleary.com/2009/04 / ...


4 Réponses :


5
votes

Envoi de fichiers / répertoires sur les sockets n'est pas trivial. Je recommanderais d'utiliser une bibliothèque de transferts de fichiers (sur des prises sur des sockets ou peut-être un protocole de niveau supérieur, c'est-à-dire FTP, HTTP, etc.), plutôt que d'essayer de coder la chose à partir de zéro.

Après avoir écrémé sur le code - essayez d'envoyer un fichier volumineux contenant une teneur uniforme (remplie de '0 ou quelque chose). Si cela réussirait - votre chose XML ne fonctionne pas.


1 commentaires

Ouais tu as raison, je vais commencer à chercher des bibliothèques. La série XML me sauvegarde du temps. Au lieu de passer plusieurs cordes, cela me permet de passer un objet.



10
votes

Il y a quelques problèmes que je peux voir immédiatement. Celui qui peut causer que votre programme ne fonctionne que peu de temps est le fait que l'envoi via TCP ne garantira pas que chaque envoi entraînera un de taille identique de l'autre côté.

Votre protocole semble supposer que ce sera, car vous attendez une lecture exacte de 11 octets pour le , alors qu'il pourrait être reçu dans plusieurs lectures distinctes. E.g.: "[Données de fichier ...]". Si cela se produit, votre code ne finira pas correctement.

Il convient également de noter que le codage ASCII est de 7 bits, et de manière incorrecte des fichiers binaires (tels que le MP4) (même si vous fixez ce qui précède). Si ce sont des données binaires, vous ne devriez pas tenter de le convertir en chaîne, mais écrivez-le directement à partir du fichier octet [] .

Si vous souhaitez contenir cette route (plutôt que d'utiliser les nombreux systèmes de transfert de fichiers existants déjà disponibles, comme indiqué dans une autre réponse), vous pouvez également vouloir modifier votre protocole afin que, au lieu de délimiter le fichier avec < sendfile> ... , vous envoyez la longueur du fichier initialement, ce qui vous permettra d'envoyer des fichiers pouvant contenir l'une de ces balises spéciales.


3 commentaires

Merci beaucoup. Votre deuxième paragraphe est où mon problème réside. J'ai besoin de trouver un moyen de laisser le serveur savoir que le transfert est effectué afin qu'il puisse commencer à écouter pour d'autres commandes. De plus, j'ai divisé chaque fichier sur des morceaux car je reçois une erreur de mémoire lors de la mise en place d'un fichier important sur un tableau d'octets.


Et mon code n'est pas bien organisé ... Je n'écris pas des caractères ASCII dans le fichier que je transporte :)


Iridum maintenant ça marche. J'attends quelques secondes avant d'envoyer "" et j'ai également augmenté la taille du morceau et cela fonctionne bien. Comment puis-je savoir si le flux est utilisé ou si le client envoie des octets? Ce sera bien si je peux savoir que pour que je n'ai pas besoin d'attendre quelques secondes avant d'envoyer "" et attendez plutôt que le flux soit "inactif" afin d'envoyer "" et rendre mon code plus efficace ...



2
votes

Fondamentalement, ce que vous faites est correct. Le point principal que je pourrais suggérer d'améliorer est la définition du maxchunksize à une valeur plus grande, jusqu'à 65000. Cela permettra au code de la prise de gérer toute fragmentation, ce qui sera beaucoup plus efficace que tout se divisant. fera par vous-même.

En outre, vous savez que l'envoi d'un fichier important devrait prendre un certain temps. Sur un réseau local de 100 Mbit, la bande passante serait (théoriquement) 12,5 Mo par seconde. L'envoi d'un fichier de 700 Mo de 700 Mo prendra toujours 56 secondes. Bien entendu que le débit réel dépend et de nombreux facteurs du réseau et des ordinateurs et du matériel de réseau impliquent, il serait donc censé plus lent.

Enfin, Wireshark (ou tout autre programme de renifleur) est l'outil le plus élémentaire et le plus précieux dans le programmateur de réseautage. boîte à outils. Utilisez-le sur le serveur et le client pour voir comment les paquets TCP sont transmis, de voir si vous pouvez identifier toutes les causes de la traînée lente.


0 commentaires

11
votes

Voici mon code pour envoyer un fichier volumineux. Quelques conseils:

  • Vérifiez votre taille de tampon. Si c'est trop gros, ça échouera.
  • Drapeaux de prise. Le drapeau partiel fonctionne le meilleur.
  • Le délai d'attente de socket est nécessaire en raison du temps de transfert.

    client: xxx

    serveur: xxx

    espère que cela aidera quelqu'un.


4 commentaires

+1 Merci C'était très utile. Notez que vous devez supprimer Trailing "\ 0" des en-têtes avant de les utiliser sur le serveur lorsque vous les recevez .... J'ai utilisé (Header.replace ("\ 0". Vide))


Pourquoi cela échouerait si la taille de la mémoire tampon trop grande?


Votre exemple est-il valide si je souhaite qu'un client télécharge un fichier sur le serveur? Je suis un petit noob, j'essaie de modifier votre exemple pour obtenir ce comportement (synchroniser des fichiers du serveur aux clients). Merci!


Ce code n'est pas bon. Cela peut échouer car si la connexion est lente, le serveur peut recevoir une partie du fichier sur l'en-tête et perd ainsi cela lors de l'écriture dans le fichier actuel!