Vous ne trouvez pas de réponse à votre problème ? Alors posez la question dans le forum. Souvenez-vous qu'il n'y a jamais de question bête, mais rester dans l'ignorance parce que l'on n'ose pas poser une question, ça c'est une erreur !

Sujet : miniserveur HTML multithread : faire un SEND bloquant ? [ Windows / Réseau & Internet ] (steph12358)

mercredi 17 octobre 2007 à 11:36:07 | miniserveur HTML multithread : faire un SEND bloquant ?

steph12358

Bonjour

J'essaye de réaliser un serveur HTML multithread dans le cadre d'un projet :
j'utilise des sockets de type SOCK_STREAM.

Afin de ne pas fermer la connexion avec le client avant d'avoir effectué la totalité de l'envoi de la page demandée (ou du fichier binaire : image, activex etc...) j'ai écrit une routine qui saucissone le buffer en blocs de 1024 octets maxi...

En local sur ma machine ça fonctionne assez bien.
Mais pour l'accès à partir d'une autre machine (réseau local) j'ai du introduire un délai de 15 ms entre chaque envoi de bloc sinon la connexion est coupée avant la fin de l'envoi.

En accès distant je crains de devoir indiquer une valeur encore plus grande.
Tout ça ne me semble pas trés propre.

Problèmes rencontrés :
-Si le délai entre deux envois de blocs est trop court les fichiers envoyés sont tronqués (image incomplètes, etc.)
-Si le client fait un refresh trop tôt (trop grand nombre de requetes) le serveur renvoit n'importe quoi et le navigateur affiche des caractères incompréhensibles.

A l'évidence dans un cas comme dans l'autre il y a bien perte d'intégrité des données transmises...

Bien sûr je pourrais mettre un Sleep de folie mais ça me paraît innacceptable comme solution !

Quelqu'un connait un moyen de savoir, lors d'un SEND si le client a reçu la totalité des données envoyées avant de fermer la connexion ?

Merci

"(...)
    lgenvoi = 10;
    erreurs = 0;
    do
        {
            Sleep (15);                        //ajustement "empirique"    15ms
                lg = 1024; //SO_MAX_MSG_SIZE;      //ajustement "empirique"    1024
                lg = min (lg, lgtotal-lgenvoi);
                cr = send(laSocket[NoThread], &buffer[lgenvoi], lg, 0);
                if (cr<0)
                {
                       Sleep (0);
                       erreurs++;
                       if erreurs> 5)
                       {
                          cr=WSAGetLastError ();
                          break;
                }
                       else
                         continue;
            }
            lgdata += cr;
                Sleep (0);
         } while (lgenvoi < lgtotal);

(...)

    closesocket (laSocket[NoThread]);
       SocketsEntrant[NoThread] = INVALID_SOCKET;
    AdresseIpClient[NoThread] = "";

(...)
"

mercredi 17 octobre 2007 à 12:15:33 | Re : miniserveur HTML multithread : faire un SEND bloquant ?

The_Guardian

Bonjour,

Ton problème est étonnant
_  tu ne dois surtout pas faire de sleep pour garantir l'intégrité des données. TCP se charge de ça pour toi. Commence donc par enlever tes sleep alors.
- réflechissons ensemble
1) pourquoi ton client reçoit n'importe quoi quand les envois sont trop proches ?
- deux possibilités
(a) ton client est mauvais (ce dont je doute, vu que tu dois utiliser je suppose un browser habituel)
(b) c'est ton émission qui est mauvaise
- quand tu fais ton send( ), le buffer est copié dans un endroit propre,  donc tu as pas de risque d'écrasement du buffer
- à moins que... à moins que tu fasses de la lecture dans un thread d'émission et de l'écriture dans le buffer, à partir d'un thread différent. Et ça ça pourrait te poser des problèmes
Et il y a un autre problème aussi, celui des refreshs
- quand tu fais un refresh, le client coupe la connexion et en ouvre une autre , ton serveur peut détecter la coupure de la connexion parce que le send va renvoyer des valeurs d'erreur notamment, et dans ce cas là, il peut fermer la connexion

Bon maintenant que tu aies trop de requêtes c'est étrange..

Question : pourrais-tu donner un exemple plus concret de ce qui se passe quand tu rafraichis ?

Et pour ta dernière question:
_ pour savoir si un client a bien reçu toutes les données
- soit tu ne t'en préoccupes pas (TCP gère ça pour toi)
- soit tu demandes au client d'acquitter,  mais là tu sors du protocole HTTP..

Bon courage et pour tes prochaines questions, pense à expliquer davantage ton architecture avec les threads écrivains et les threads lecteurs. :p

===

 


Une autruche ne se cuit pas aux petits lardons


mercredi 17 octobre 2007 à 12:17:16 | Re : miniserveur HTML multithread : faire un SEND bloquant ?

The_Guardian


Re,

Et en y réflèchissant, à mon avis c'est ça ton problème: des threads partout et du coup tu contrôles  mal ce qui se passe...

===

Une autruche ne se cuit pas aux petits lardons

mercredi 17 octobre 2007 à 14:49:22 | Re : miniserveur HTML multithread : faire un SEND bloquant ?

steph12358

Salut The_guardian

Sans les Sleep ça marche parfaitement si le serveur et le client sont sur la même machine. Pas besoin de Sleep ou autre magouilles. Mais intérêt trés limité
Dès que je teste depuis un autre poste, en réseau local, ça part en live et les envois sont corrompus ou incomplets...Mes clients: les 2 navigateurs les plus utilisés bien sûr, IE et Firefox (pas de soucis de ce côté là, le bug est de mon côté là c'est sùr )

Il me semble que le fait de fermer la connexion immédiatement après avoir fait le dernier Send arrête l'envoi des données : si le buffer (tampon de données en attente) n'a pas eu le temps de se vider, oups ! Le close Socket fait un massacre !
Est-ce que TCP/IP "empile" l'appel au close Socket et l'exécute après seulement que le buffer soit complétement envoyé ? Il me semble que non. En plus comme tu le souligne les navigateurs n'envoyent pas d'accusé de réception (ça serait trop simple).

Quand je consulte une page html qui contient par exemple 4 images grand format, le navigateur ouvre plusieurs threads (1 pour la page et autant que nécessaire pour les liens vers des images contenus dans la page ). Si on fait un refresh mon serveur peut ne pas avoir fini d'envoyer tous ces éléments...

Si une des images demandées a été envoyée son thread est utilisable pour un nouvel envoi.

Pour les refresh : puisque le client à qui je suis, le cas échéant, en train d'envoyer des données s'est déconnecté est-ce que je ne devrais pas sortir de ma boucle d'envoi dès la première erreur constatée.

Et pour répondre à ta question sur les threads utilisés j'ai un thread d'écoute et un d'écriture effectivement, et un tableau de buffers et de flag d'envois, mais j'utilise des sémaphores pour éviter les conflits d'accès et que ça parte en sucette.


mercredi 17 octobre 2007 à 15:18:59 | Re : miniserveur HTML multithread : faire un SEND bloquant ?

The_Guardian

Re,

Ok quand tu fais ton close, les données en attente vont être envoyées, c'est pas un arrêt brutal.

_ pour les refresh, oui, tu devrais sortir de ta boucle d'envoi dès la première erreur rencontrée
_ en gros, c'est pas normal que tu aies une erreur de ce type, vérifie bien tes sémaphores, fais le contrôle d'erreur qui sort de la boucle dès qu'un client se déconnecte, puis reposte du code pour qu'on voit ça plus en détail si ça marche toujours pas.
Car c'est sencé marcher ton truc, si tu fais pleins de send et un close ben tout sera envoyé.
 erf souci mais ou?
===
Une autruche ne se cuit pas aux petits lardons

mercredi 17 octobre 2007 à 15:55:24 | Re : miniserveur HTML multithread : faire un SEND bloquant ?

steph12358

Ok ! Je vais tout remettre à plat suivre tes conseils, puis faire de nouveaux tests

Merci encore

A+

vendredi 19 octobre 2007 à 10:36:26 | Re : miniserveur HTML multithread : faire un SEND bloquant ?

steph12358

Réponse acceptée !
Salut The_Guardian

Comme tu le présentais j'avais qques soucis avec mes sémaphores .

J'avais aussi des erreurs WSAWOULDBLOCK dans ma boucle alors que ma socket était non bloquante

Je suis tombé sur un site qui m'a bien aidé sur le coup.

http://tangentsoft.net/wskfaq/

J'y ai appris beaoucoup de choses, entre autres comment fermer plus proprement une socket en utilisant
shutdown et en attendant le compte-rendu 0 avant de faire le closesocket...

En fait j'y ai appris que l'erreur WSAWOULDBLOCK était une occurence normale quand on travaillait avec des sockets non bloquants. Elle veut simplement dire que le système ne peut plus "bufferiser" de nouvelles données à envoyer. Il suffit d'attendre...

Dans ma boucle je compte donc toutes les erreurs avec un sous-total pour l'erreur WSAWOULDBLOCK et pour sortir de la boucle je teste

"if (nberr-nberrWouldBlock > 5 || cr==INVALIDE_SOCKET)"

et ça marche pas trop mal.

Merci pour ton aide



vendredi 19 octobre 2007 à 10:42:06 | Re : miniserveur HTML multithread : faire un SEND bloquant ?

The_Guardian


Ah c'est interressant ça de savoir, merci aussi alors :p

===
 

Une autruche ne se cuit pas aux petits lardons :p



Cette discussion est classé dans : send, lg, sleep, cr, lgenvoi


Répondre à ce message

Sujets en rapport avec ce message

fonction Sleep ou Delay sous VC++ 6HELP !!! [ par TricK ] salut ou sont donc passer ces focntions dans la version 6 de visual c++ j'en ai granve besoin dans un programme ...au secourssi quelqu'un a une librai Aide sleep [ par ManDeq59 ] Salut, Je programme sur Borland C++ 4.0 et je n'arive pas à utiliser les fonction sleep(..), il me marque une erreur.Comment pus-je faire pour pouvoir creer une tempo et bibliotheque [ par jimtruand ] je crois qu'on peut creer une tempo avec sleep mais quel fichier d'include mettre dans le code mon code a pour but d'afficher toutes les 3 s le carre creer une tempo [ par jimtruand ] salut!je voudrais savoir quel fichiers include on doit utiliser pour sleep que la compilation ne reconnait pasmon code est le suivant#include #include petit probleme en c++ [ par chris5874 ] bonjour!je développe actuellement un logiciel en c++ pour piloter un moteur pas à pas.j'aimerais piloter le moteur par demi pas,en ayant une vitesse r fonction sleep ? [ par kilian ] bonjour la teamje souhaiterai savoir si qql1 connais une fonction equivalente a la fonction sleep... car pdt que la fonction sleep est activer, je ne Fonction sleep [ par ToToL ] Je cherche la fonction sleep sur visual c++. si quelqu'un pouvai m'aider :) se serai super.----------------------------------------------Programmeur e Send qui n'envoi pas [ par CyberP ] J'utilise la commande send dans un programme. Apparemment, aucune erreur ne se déclanche et l'envoi est correct mais le serveur auquel je me suis conn Envoi de classe avec send [ par piemur2000 ] Bonjour,Je voudrai envoyer une classe grace à un send.Par exemple cette classe :class Donnees{ int Type; int Taille; d utiliser un Timer [ par melkiorlenecrarque ] hello! jutilise VC++ 6 et et j'essai de transcrire mon programme "combat warhammer" pour windowsvoila mon pb:mon prog en appuyant sur un boutton execu


Nos sponsors

Sondage...

CalendriCode

Décembre 2008
LMMJVSD
1234567
891011121314
15161718192021
22232425262728
293031    

Consulter la suite du CalendriCode

Téléchargements

Logiciels à télécharger sur le même thème :



Développement réalisé par Nicolas SOREL (Nix) avec l'aide de : Cyril DURAND et Emmanuel BAÏSE, Merci à Vincent pour ses précieux conseils
CodeS-SourceS.com© Toute reproduction même partielle est interdite sauf accord écrit du Webmaster
CodeS-SourceS.com© est une marque déposée tous droits réservés
Temps d'éxécution de la page : 0,234 sec

Google Coop CodeS-SourceS Google Coop CodeS-SourceS


Certaines images présentes sur le site (notament certains avatars) sont issues des collections IconShock, donc si vous souhaitez utiliser ces icons vous devez les acheter, ne les copiez pas et ne utilisez pas dans vos sites et applications sans les avoir commandé.