2010-11-09 5 views
1

Je fais mon propre serveur web simple et j'ai des fichiers texte et html à envoyer parfaitement, mais quand j'essaie d'envoyer des images, j'ai des problèmes, et je peux t le comprendre.Serveur Web en C++, comment envoyer une image

Voici ce que j'ai. Je sais que l'envoi d'un octet à la fois est inefficace, mais c'était pour les tests.

char buffer[1]; 
send_header(new_fd, get_file_type(file_location)); 
ifstream file; 
file.open(temp.c_str(), ios::out | ios::binary); 
while (file.good()) 
{ 
    file.read(buffer, sizeof(buffer)); 
send(new_fd, buffer, strlen(buffer), 0); 
} 

Des idées? Ai-je besoin de le convertir en ordre de byte réseau avant de l'envoyer?

Merci!

+1

En outre, si vous allez suivre cette approche, vous devez définir le tampon à quelque chose comme 4096 octets. L'utilisation d'un tampon de 1 octet entraînera des tonnes d'appels système supplémentaires, ce qui ralentira considérablement le serveur. – cdhowie

+0

Si vous voulez vraiment être hard-core, vous pouvez mmap() le fichier manuellement, puis writev() à la fois l'en-tête et le fichier en même temps. Le sendfile() de BSD le fait pour vous; Linux est plutôt limité, donc vous devrez appeler mmap()/writev() vous-même. – chrisaycock

+0

@cdhowie, lol Je sais que je l'utilisais pour tester certaines choses, je l'ai passé à 1024, parce que cela ne fonctionnait même pas correctement avec votre solution avec le réglage à 1. – Pieces

Répondre

6

strlen(buffer) va compter jusqu'au premier caractère nul ('\0'), qui est un octet très commun dans les données d'image. Vous devez, à la place, déterminer combien d'octets ont réellement été lus (ifstream.read() ne fournit pas cette information) et l'utiliser à la place de votre appel strlen.

EDIT: Vous pouvez obtenir cela avec ifstream.gcount() - donc il suffit de remplacer votre strlen appel avec file.gcount() et tout devrait fonctionner comme par magie.

+0

Génial, merci beaucoup! – Pieces

6

@cdhowie a raison sur strlen() comme le coupable. Cependant, si vous voulez vraiment être "moderne" envisager d'utiliser sendfile(). Il va mmap() le fichier que vous souhaitez envoyer pour vous. L'utilisation de sendfile() vous empêchera de lire le fichier dans la mémoire temporaire uniquement pour l'envoyer à un autre destinataire. Il enregistre non seulement les étapes, mais provoque également moins de défauts de page pour les fichiers vraiment gros (tels que les images).

+0

Cool, je suis toujours prêt à être moderne, je vais vérifier. – Pieces

+0

Je considérerais certainement cette route aussi bien. Les mécanismes d'envoi en lecture/écriture ne doivent être utilisés que lorsque vous devez traiter le flux (par exemple, compression/chiffrement). – cdhowie

+0

Ou dans le cas où quelqu'un d'autre pour faire quelque chose de similaire dans Windows l'équivalent est appelé TransmitFile. – Matt