begin process at 2010 07 29 16:08:55
  Trouver un code source :
 
dans
 
Accueil > 

Code

 > 

Réseau & internet

 > [HTTP-CLIENT] - RÉCUPÉRER UNE REQUETE COMPLÈTE SANS PASSER PAR LES SOCKETS ASYNCHRONES

[HTTP-CLIENT] - RÉCUPÉRER UNE REQUETE COMPLÈTE SANS PASSER PAR LES SOCKETS ASYNCHRONES


 Description

Hello !
Etant tout nouveau dans ce merveilleux monde qu'est python, je suis content de mettre en ligne ma première source python ;-)
Je travail beaucoup sur le protocole HTTP et je n'arrête pas d'avoir des problèmes avec la fonction recv() du module socket.
Pour recevoir une entête et tout le contenu envoyé par le serveur (dans le cadre d'un client HTTP), j'ai du user de ruses pour arriver a récupérer l'intégralité des paquets dans un buffer et arrêter la fonction recv() sans passer par le mode asynchrone ni les threads.
Il s'agit d'une (toute) petite astuce, je m'excuse d'avance si quelqu'un d'autre l'a postée avant moi.

Source

  • def HTTPRecv(Socket):
  • sResult = ''
  • while 1:
  • sResult += Socket.recv(1024)
  • if ( ord(sResult[-1:]) == 10 ):
  • break
  • return sResult
def HTTPRecv(Socket):
	sResult = ''
	while 1:
		sResult += Socket.recv(1024)
		if ( ord(sResult[-1:]) == 10 ):
			break
		
	return sResult

 Conclusion

En fait, le fonctionnement est très simple : je reçois les paquets dans un buffer de 1024 bytes. Je concatène au résultat final et je teste le dernier caractère : si il s'agit du caractère <LF>, je stop l'exécution de la boucle et je renvoi le résultat final.


 Sources de la même categorie

Source avec une capture HTTP FORWARDER par matad0r
Source avec Zip GÉNÉRATEUR HTML POUR L'UTILISATION DE PYTHON EN CGI par Just_1
SIMPLE COMPARATEUR IPV4 EN PYTHON par erebos
TÉLCHARGEUR YOUTUBE par rezuz
Source avec Zip LIRE DES FICHIERS PCAP par KimbleMandel

 Sources en rapport avec celle ci

Source avec une capture HTTP FORWARDER par matad0r
Source avec une capture [PYGTK] LECTEUR MULTI-VIDÉO EMBARQUANT MPLAYER GRÂCE À L'ID ... par loupmagic
SOCKET CLIENT/SERVER TRÈS SIMPLE! par mast
Source avec Zip SOCKET : CLIENT ET SERVEUR SINGLE ET MULTI-THREAD par Ulala2
SOCKET CLIENT/SERVEUR par Shinji

Commentaires et avis

Commentaire de Dobel le 30/06/2007 00:04:37

Pour info, les objets sockets en python contiennent déjà de quoi faire ce genre de lecture.
tu as une méthode makefile pour créer des objets type fichier, qui travaille sur des buffers.

s.bind((HOST, PORT))
s.listen(1)
conn, addr = s.accept()

# pseudo fichier en lecture, binaire, buffer taille par défaut du système
rfile = conn.makefile('rb', -1)

while 1:
    data = rfile.readline()
    if not data: break
    print data

readline retourne bien la chaîne jusqu'au premier \n rencontré, et non pas juste à la fin de ce que te retourne recv

Commentaire de jean84 le 30/06/2007 02:15:06

Salut

Je pense que tu m'as mal compris. Le code que tu présentes est celui d'un serveur (fonction bind()) qui ne doit recevoir effectivement que des requêtes, d'où l'intérêt de n'arriver qu'à \r\n (HTTP 1.1).
Mon problème ce positionne côté client : dans le cas d'un forward en HTPP, il est beaucoup plus pratique de recevoir toutes les données (réponse serveur + contenu de la page demandée) pour les renvoyer en intégralité au proxy suivant (que j'ai développé). Je laisse le soin à python (et à TCP) de fragmenter les trames pour ses besoins, je n'ai besoin de travaillé pour ma part qu'avec les données complètes, fragmenter les paquets HTTP devient ensuite un casse tête à gérer(encore une fois, pour mon projet).

Des expériences que j'ai réalisé, beaucoup de serveur envoi leurs entêtes dans un paquet différent de celui du contenu des pages. On peut palier ce problème en réservant un buffer plus important mais on fini par se retrouver avec des entêtes et une partie de la page HTML dans un buffer. Suivant le site, on peut essayer de 'prévoir' la taille du buffer en réception mais je ne trouve pas cela très propre et il existera toujours des exceptions (on ne peut pas connaitre à l'avance la taille que fera un site).
Je me suis basé ensuite sur le champ content-lenght mais la encore, chaque serveur fait sa sauce (suivant sa configuration essentiellement et sa façon d'implémenter le protocole HTTP) et n'envoi pas toujours ce param (ça faciliterai beaucoup de choses pourtant :^) )
J'ai trouvé ensuite plusieurs astuces ici et là mais aucune d'entre elles n'a fonctionné (je m'y suis peut être pris comme un manche, c'est possible aussi) :
- le site du zéro indique de tester le retour de recv() avec not (un peu comme tu l'as fait). Sur de nombreux forum, j'ai pu lire que cela ne fonctionne pas et ce pour une simple raison, c'est qu'on teste le buffer de sortie après l'appel a recv(), donc inutile car on veut éviter de faire appel à cette fonction si on n'a plus rien à recevoir (et donc éviter qu'elle attende dans le vide)
- progx.org donne une solution à ce problème grâce à la fonction socket.setblocking(0). Pour mon utilisation, cela n'a pas fonctionné car apparemment il faut que les communications soient absolument synchrone (au centième de seconde près). Il faut que le paquet à recevoir arrive au moment ou python exécute la fonction sinon elle passe par le try: except: et le paquet est rejeté (ou du moins, il n'est pas pris en compte)
- une dernière solution concerne les threads. Pas utile dans mon cas car je veux garder la synchronisation du serveur et du client : l'un envoi, l'autre reçoit puis envoi à son tour etc...
Même si le protocole HTTP 1.1 gère les envois multiples d'entêtes sans attendre le retour, ce ne faisait pas parti de mon cahier des charges. Je n'ai pas besoin d'envoyer et recevoir en même temps donc j'ai préféré zappé (bien que l'implémentation des threads en python soit excessivement simple, c'est indéniable)

C'est donc après mes petites recherches que j'en suis arrivé à ce code. Je le dis je le répète, je suis nouveau en python. Il est évident que j'ai du passer à coté de quelque chose mais n'ayant pas trouvé de solution probante, j'ai du me résoudre à l'obtenir par mes propres moyens.

Merci de m'avoir lu jusque là et si j'ai dit une bêtise, merci de me le signaler ;-)

++

Commentaire de Dobel le 30/06/2007 09:59:00

ok.
j'espère que ce que je vais dire est juste, j'ai jamais testé et  :)


autant que je sache, la méthode readline qu'ils ont fait utilise son buffer pour faire abstraction des trames TCP.
ça doit être un truc du genre :
recv, regarde si il y a un \n (LF) dedans, si oui, coupe au \n, retourne la 1ère partie, conserve la 2nde
sinon, recv à nouveau.

donc 1er readline : commande HTTP, chemin, version
readlines suivant : tous les entêtes, jusqu'à rencontrer une ligne vide

puis lecture du corps de la requête (là, ça va dépendre de la version d'HTTP)


pour le test if not data: break,
il semble que quand le client ferme sa socket, recv retourne "", un paquet vide.
si tu ne gères pas les connexions persistantes, ça doit être bon.

ça doit fonctionner quelque soit le nombre de trames utilisées par le client :)


"car on veut éviter de faire appel à cette fonction si on n'a plus rien à recevoir (et donc éviter qu'elle attende dans le vide)"
=> d'où l'intérêt d'utiliser des threads, pour ne plus avoir cette limitation :)
t'attends que ton client ferme tranquillement sa socket, et hop. ton thread gérant la requête se termine.

Commentaire de Dobel le 30/06/2007 10:41:41

oups, oui, tu bosses côté client.
(c'est ça de poster aussi "tôt" un weekend :))

Enfin, c'est la même chose.

tu peux aussi créer des pseudos fichiers avec makefile,
en lecture et/ou en écriture suivant les arguments
(wfile = sock.makefile("wb", 0) par exemple pour un pseudo fichier en écriture)

pour HTTP 0.9 :
tu lis tant que tu peux, cad juste la méthode read du pseudo fichier, sans donner d'argument size, qui lira jusqu'à EOF

pour les autres,
tu lis ligne par ligne la version, code réponse, etc., puis les entêtes jusqu'à trouver une ligne blanche
et tu peux utiliser le champ content-length si il est là, ou sinon, tu lis aussi jusqu'au bout.

bonne prog.

Commentaire de jean84 le 30/06/2007 11:14:45

Hello ;-)

Ok je viens de saisir pour le pseudo fichier. Je vais tester et je te tiens au courant.

Merci :-p

 Ajouter un commentaire


Discussions en rapport avec ce code source dans le forum

Socket et Threading [ par dabcorp ] Bonjour , J'ai fait un client/serveur socket , mais je me comprend pas les threads ... Je suis oblig&#233; de faire une boucle pour relance le progra TWISTED : Transfert de fichier [ par chmod666 ] Bonjour,je viens enfin de trouver ce qu'il me faut aprés bcps bcps de recherche il faut le dire ... Situation:J'ai un client qui envoie un fichierJ' Perl to Python [ par mike1310 ] Bonjour,je ne savais pas trop ou poster mon message étant donné qu'il n'y a pas de codes sources pour Perl.J'ai en fait un code en Perl que je dois re msn client/serveur python [ par tsic ] Bonjour, je suis bloqué ilya preque 2 semaines dans le code suivant. je veut que le client et le serveur envoyent leurs message d'une maniere comme ms Client Serveur Netstat [ par power211 ] Bonjour &#224; tous, je suis un ptit nouveau ds le monde du python, projet d ecole oblige mais c vrai que&nbsp; le python c rapide comme langage.Bon t Socket+timeout [ par power211 ] Re Bonjour tout lemonde,bon voila j aurai une ptite question sur les sockets plus les timeout.Donc je vais directement aller au but avec un exemple co Bittorent Source [ par 0mega ] Bonjour a tous ! J'essaie en vain de compiler la source du dernier client bittorent (python 2.4) mais sans succ&#233;s. Voici le read-me inclus av [Python] Trouver l'IP d'un PC à partir d'un Pocket PC [ par sacrechipou ] Salut!Je suis en stage d'informatique et on m'a demandé à partir d'un pocket pc de récupérer l'adresse ip du PC auquel il est connecté.Ayant débuté le Probleme recv bloquant [ par mike1310 ] Bonjour à tous,je débute un peu dans le python et je suis sur un projet de socket. Je dois pouvoir communiquer avec un postfix pour, par la suite lui Réouvrir une socket precedemment fermée [ par mike1310 ] Bonjour à tous,J'aurais une petite question concernant les sockets. Dans le soft que je suis en train de créer, à un moment donner je suis obligé de f


Nos sponsors


Sondage...

Comparez les prix

CalendriCode

Juillet 2010
LMMJVSD
   1234
567891011
12131415161718
19202122232425
262728293031 

Consulter la suite du CalendriCode

 
Développement réalisé par Nicolas SOREL (Nix) avec l'aide de : Cyril DURAND et Emmanuel (EBArtSoft), 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

Google Coop CodeS-SourceS Google Coop CodeS-SourceS
Temps d'éxécution de la page : 0,608 sec (3)

Nous contacter | Annoncer sur CodeS-SourceS | Mentions légales