15 mars 2009

Problème de connexion client jabber en scheme

J'avais un petit soucis quand a l'établissement de connexion en PLT Scheme pour mon client Jabber. J'avais en parti raison quand à la source du problème, c'était bien la réception de données qui déconnait !

En effet, il faut savoir que a réception avec le listener de Scheme se fait en blocks, ca veut dire que lorsque le serveur me répond quelque chose, et il peut me répondre en plusieurs messages (ou blocks), mon listener ne capture que le premier block, et me le retourne. C'est pourquoi je n'avais que le début du message.

Dans le code suivant, et surtout la fonction la plus en bas, vous verrez comment je contourne le problème. En fait je vais donner une taille en bytes au block, et je vais aller piocher dedans sans modifier ce qu'il y a, jusqu'à avoir un block qui n'est pas rempli de 0 (ou de la quelconque valeur que le listener met en attendant de recevoir quelque chose). Notez que j'utilise la librairie port qui me sert a utiliser peek-string, peek-string va jeter un oeil dans le port-input et me dire ce qu'il y a dedans, sans y modifier le contenu, càd qu'a la différence de read-string par exemple, il ne va pas effacer ce qu'il y a dans le input-port, ce qui est tout bon !

#lang scheme
(require scheme/port)
(require scheme/tcp)
(require xml)

;-------------------------------------
;
; Client Jabber: reseau
;
;-------------------------------------

; c'est bon je parse mieux les données
; il est preferable d'utiliser display que write, car display affiche les données raw sans les parser !
;
;


; serveur jabber au hasard
(define URL "jabber.org")
(define PORT 5222)
(define TAILLEBLOCK 2048) ; taille d'un block en byte



(define (client-test)
(let-values ([(server->me me->server)
(tcp-connect URL PORT)])
;(write "" me->server)
(display "" me->server)
(close-output-port me->server)
(sleep 1) ; optionnel ? car recupServer->me

;reponse du serveur
(let ((reponse (recupServer->me server->me)))
(display reponse)

(close-input-port server->me))))



; recupServer: int -> string
; je récupere les données de [server->me] directement en raw
(define (recupServer->me port)
(let loop ()
(let ([available (peek-string TAILLEBLOCK 0 port)])
(if (null? available) ; on boucle tant que le serveur ne m'as rien renvoyé !
(loop)
(read-string TAILLEBLOCK port)))))


Ainsi, je récupère bien tout ce donc j'ai besoin, et je peux continuer à recevoir de cette manière.

Aucun commentaire: