Accueil CanalOpenSource
SourceServer
Langage xShell
BasicBrick
tcp OpenClient
tcp_OpenServer

DesignServer

openSource Shop Gallery
Main Street
freeway Avenue

Liens :

ifs_GettingStarted
OffreFormationxShell
OpenSyncPresentation
ssf_Mail-13122002
tcp_GettingStarted
tcp_Samples
tcp_ServerGettingStarted
xShell2003Novembre2003

 

Mot entier Recherche dans la sélection


| Retour

tcp OpenServer - Prise en main
A propos de tcp OpenServer
  
Cette librairie permet de recevoir et de traiter les requêtes envoyées par une base 4D qui utilise la librairie tcp OpenClient.
tcp OpenServer est en mesure de manipuler les données de votre base, de faire des recherches et des sélections, de maintenir un contexte client, d'envoyer des données au client et d'executer du code à la demande de la base connectée. tcp OpenServer offre des points d'entrées pour que vous puissiez inserer votre propre code et répondre à des requêtes spécifiques.
  
Description de la librairie
  
La base tcp_OpenServer contient 3 groupes Insider qui constituent la librairie à intégrer à une application 4D pour profiter des fonctions de communication.
  
Le groupe tcpOpenServer regroupe toutes les méthodes propres à la partie serveur de ce module.
  
Le groupe tcpOpenShared contient toutes les méthodes partagées par tcp OpenServer et tcp OpenClient.
Ce groupe contient aussi deux formulaires d'interface, tcp_log qui permet d'afficher le log de communication et de l'enregistrer sur disque si on le désire, et tcp_Ping qui affiche une fenêtre avec une fonction pour tester si la base serveur distante répond.
  
Le groupe Include apporte les méthodes nécessaires et complémentaires issues d'autres librairies de xShell.
  
Parmétrages
  
La base est fournie avec un dossier properties qui contient le fichier tcpPrp.txt. Ce fichier renferme plusieurs paramètres. Ce fichier est commun au serveur et au client tcp Open. Voici les paramètres qui concerne le serveur :
  
Dans la section [SrvManager]
  
nbMaxSrvTempoRequest=10
RefreshLogWindow=60
  
La propriété nbMaxSrvTempoRequest indique le nombre maximum de process de requêtes temporaires qui seront conservés après l'execution du traitement.
  
RefreshLogWindow indique le délais en tick du rafraichissement de la fenêtre de log.
  
Dans la section [Server1]
  
ServerName=Standard
MethodeName=tcp_SrvRequest
ProcessName=tcp_SrvRequest
LaunchAtStartup=no
nbPrcSrvConnect=2
nbPrcSrvRequest=2
killExtraAfterOneRequest=no
logName=Server1Log.txt
listen=15000
Call=15000
IP=127.0.0.1
DelayOnListen=1
tcpTimeOut=1200
tcpTimeOutITK=30
tcpTimeOutServer=7200
tcpTimeOutSrvOnBind=7200
  
  
Le principe mis en place est celui du listener qui est à l'écoute et attend des requêtes en provenance de l'extérieur. Le listener ne traite pas la requête qu'il reçoit. Il délègue le traitement à des process de requêtes.
  
Description des propriétés de la section [Server1]
  
La méthode qui contient le code du listener est tcp_Srv. MethodeName indique à tcp_Srv quel est la méthode du process qui doit executer les requêtes qu'il reçoit. Dans notre cas, il s'agit de la méthode tcp_SrvRequest. Elle contient tout le code du serveur tcp OpenServer. La même méthode tcp_Srv est capable de gérer d'autres process de requêtes, comme par exemple IncludeFtpServer.
  
ProcessName est le libellé du nom du process dans la liste des process qu'affiche 4D. Idem pour ServerName, la première propriété de cette liste.
  
LaunchAtStartup détermine si le serveur doit être lancé ou non. Deux valeurs sont possibles : "yes" - "no". Pour pouvoir utiliser le serveur il faut donc passer LaunchAtStartup à "yes". Ce paramètre est prise en compte au lancement de la base lors de l'appel de la méthode tcp_OnStartupBase.
  
La propriété nbPrcSrvConnect indique le nombre de listener qui sont à l'écoute des connexions entrantes. Un seul listener suffit si on a peu de connexions. Avec deux listeners on peut déjà assurer une bonne montée en charge. Avec quatre listeners, votre base répondra aux connexions entrantes même si elles sont nombreuses à arriver simultanément. A ce jour, il n'y a qu'un seul cas où ce nombre de 4 listeners est nécessaire, c'est avec IncludeFtpServer et le client ftp de Internet Explorer Mac. Ce dernier lorsque vous voulez télécharger un dossier envoie un très grand nombre de requêtes. Si le nombre de listener n'est pas suffisant, on arrive à un blocage.
  
nbPrcSrvRequest détermine le nombre de process de requêtes qui sont lancés au démarrage de l'application. Il n'a pas besoin d'être élevé car le listener est capable d'en lancer un supplémentaire si tous ceux existants sont occupés.
  
killExtraAfterOneRequest indique par "yes" ou "no" si les process de requêtes supplémentaires doivent être conservés après l'execution de leur traitement.
  
Cas pratiques :
  
1 - vous avez une base serveur avec 10 postes tcp OpenClient qui vont ouvrir chacun deux à trois binds simultanément. Vous savez donc que de manière générale vous avez besoin d'une trentaine de process de requêtes et vous pouvez augmenter le nombre de listener à 6. Par contre, il n'est pas nécessaire de conserver les process de requêtes qui sont créés de manière execptionnelle.
On a donc les paramètes suivants :
nbPrcSrvConnect=6
nbPrcSrvRequest=30
killExtraAfterOneRequest=yes
  
2 - vous avez une base serveur avec 3 postes tcp OpenClient, dont un qui ne se connecte qu'occasionnellement. Vous pouvez adopter les paramètres suivants :
  
nbPrcSrvConnect=1
nbPrcSrvRequest=2
killExtraAfterOneRequest=yes
  
Ces mêmes paramètres sont bons si votre serveur est un serveur web et que vous vous connectez dessus avec un client tcp OpenClient pour des opérations d'administration.
  
3 - vous ne savez pas trop quel va être le nombre de connexions et vous voulez que votre serveur ne connsomme pas trop de temps cpu mais puisse répondre à toutes les requêtes et s'adapte aux montées en charge :
  
nbPrcSrvConnect=2
nbPrcSrvRequest=4
killExtraAfterOneRequest=no
  
Complétez ce paramétrage avec la propriété nbMaxSrvTempoRequest de la section [SrvManager] qui précise le nombre maximum de process de requêtes temporaires qui sont conservés après leur traitement.
  
La propriété logName est le nom du fichier de log. Le fichier de log est enregistré dans le dossier Logs Folder qui se trouve à coté du fichier de données. Pour activer le log, il faut lancer la méthode tcp_ScreenLog qui ouvre la fenêtre de log. Dans cette fenêtre va s'afficher toutes les requêtes. Une boite à cocher indique d'enregistrer les requêtes dans le fichier Server1Log.txt, valeur par défaut de la propriété logName. Ce log est très verbeux. Il est interressant à utiliser lorsque vous testez vos communications entre base. Il est aussi disponible sur le client.
  
listen indique le port sur lequel le listener est à l'écoute.
Call indique le port sur lequel les appels se font.
Dans la majorité des cas listen et Call sont identiques. Vous pouvez avoir besoin d'avoir un port d'appel différent du port de réception si vous voulez faire communiquer des bases qui sont sur la même machine et que chacune est serveur et client à la fois. Si tel est le cas, l'adresse Ip étant identique, si la base A (serveur) appelle la base B, si les ports sont égaux, c'est le listener de la base A qui va réceptionner l'appel. Contrairement au cas du 4DServer et 4DClient sur la même machine, la communication avec tcp Open est très performante.
  
IP indique l'adresse IP du serveur. Un nom de domaine (www.acme.com) peut être utilisé.
  
DelayOnListen est exprimée en tick. Le listener est une boucle dont on ne sort que lorsqu'une requête arrive. DelayOnListen indique la temporisation entre chaque écoute. A un tick, valeur par défaut, la requête est reçu immédiatement. Plus la valeur est élevée moins le listener réagit à la reception d'une requête. Voici le code de la boucle d'attente :
  
Repeter
  tcp_vlStatutConnection:=ITK_TCPStatus (tcp_vlStreamRef)
  Si (tcp_vlStatutConnection#8)
     ENDORMIR PROCESS(numProcess;tcp_vlDelayOnListen)
  Fin de si
Jusque ((tcp_vlStatutConnection>=8) | (tcp_vlStatutConnection<0) | <>tcp_flgOnQuit | (prp_Get ("Quit";"header")="yes"))
  
Dans ce code, la variable tcp_vlDelayOnListen est valorisée avec la propriété DelayOnListen et est passée en paramètre à la commande ENDORMIR PROCESS.
  
tcpTimeOut est exprimé en tick. Il est utilisé comme valeur de time out à chaque attente de réponse. La valeur de 1200 indique donc un time out de 20 secondes. Chaque fois que tcp OpenClient envoie une requête au serveur, il attend un accusé de réception et passé ces vingt secondes, il considère que le serveur ne répond plus.
  
tcpTimeOutITK est exprimé en seconde. C'est la valeur passée à la fonction ITK_TCPWaitConn qui est appelée lors de l'établissement de la connexion. Par défaut elle est de 30 secondes.
  
tcpTimeOutServer est exprimé en tick. Lorsque vous envoyez une requête sur le serveur, le listener reçoit la demande de connexion et passe la main à un process qui va traiter la requête. Le temps indiqué par tcpTimeOutServer est le temps pendant lequel le process va attendre la requête. Le temps par défaut est de 7200 ticks soit 2 minutes.
  
tcpTimeOutSrvOnBind est exprimé en tick. Ce time out est identique au précédent mais il est utilisé lorsque le client établie une communication au sein d'un bind, c'est à dire que c'est le même process de requête qui gère les demandes du client. La communication reste ouverte entre les deux postes. On créé ainsi un mécanisme similaire à celui de 4DServeur et 4DClient. Le serveur donc, va attendre 2 minutes (valeur par défaut) entre chaque requête avant de considérer que le client a coupé sa communication. Si vous voulez maintenir le contexte du client sur le serveur, il n'est pas nécessaire d'envoyer une requête à interval régulié. Il suffit pour le client d'appeler tcp_SleepOnBind pour le serveur se mette en boucle d'attente sans time out. Le serveur attend l'ordre de réveil qui est envoyé par le client avec la méthode tcp_WakeUpBind. Reportez vous à la documentation de tcp OpenClient pour plus d'information sur le sujet.
  
  
Initialisation
  
Pour initialiser le serveur tcp Open il suffit d'appeler la méthode tcp_OnStartupBase. Elle va se charger de lancer les listener et les process de requêtes en observant les paramètres du fichier tcpPrp.txt.
  
  
Les points d'entrées du serveur
  
Où est traitée votre requête client? Où compléter le code du serveur pour implémenter vos propres requêtes?
  
tcp_SrvRequest est la méthode qui va traiter vos requêtes. On la retrouve dans le tcpPrp.txt. Après le code d'initialisation, le code de reception de la requête, vient un au cas ou. Pour construire une requête coté client, vous pouvez regarder des méthodes comme tcp_SendText :
  
Si (tcp Send (tcp_Request ("tcp_SendText";$1))=0)
   $0:=tcp_WaitOK
Fin de si
  
En dehors du code qui gère la connexion et qui n'est pas montré ici, la construction d'une requête est toujours la même :
tcp_Request reçoit n paramètres et le premier indique quel est le type de requête. Ici, il s'agit de la requête tcp_SendText et dans la méthode tcp_SrvRequest, dans le au cas ou, on a :
: ($request="tcp_SendText@")
   $err:=tcp_SrvTools ($request)
  
tcp_Request retourne la requête formatée. Dans la syntaxe donnée au dessus, ce résultat est passé à la méthode tcp Send qui va se charger de l'envoie sur le serveur et retourne 0 si la communication s'est bien passée. Dans ce cas, juste après, on appel la méthode tcp_WaitOk qui attend l'accusé de reception retourné par le serveur à l'issue du traitement de sa requête.
  
Dans la méthode tcp_SrvTools qui est appelée pour traiter le tcp_SendText, on trouve un autre au cas ou. Dans cette méthode, la requête est extraite de son enveloppe et traitée :
  
: ($request="tcp_SendText@")
   tcp_vtRequest:=tcp_Extraction ("tcp_SendText";$request)  
   $request:=txt_CutOut (->tcp_vtRequest)  
   $0:=tcp_SrvTreatSendText ($request)
   $0:=tcp_SendOK ($0)
  
$request est débarrassé de son en tête "tcp_SendText" avec la méthode tcp_Extraction. On valorise une variable process avec ce résultat car on la passe en pointeur à la méthode txt_CutOut. Cette méthode retourne le texte contenu dans la chaine jusqu'au premier séparateur rencontré. Par défaut txt_CutOut utilise le séparateur retourné par txt_Sep. Chaque paramètre passé à tcp_SendText est séparé par le séparateur retourné par txt_Sep. Il faut donc éliminer ces séparteurs de la requête. $request contient maintenant le texte qu'on voulait envoyer sur le serveur. $request est passé en paramètre à  tcp_SrvTreatSendText .
  
tcp_SrvTreatSendText  est un point d'entrée dans le serveur, c'est un au cas ou vide.
  
Vous pouvez écrire sur le client :
tcp_SendText ("ExportBase")
  
et dans tcp_SrvTreatSendText écrire :
Au cas ou
  : ($1="ExportBase")
     Methode_ExportBase
  
Créer une nouvelle requête cliente et l'implémenter sur le serveur revient à écrire sur le client :
  
Si (tcp Send (tcp_Request ("MyNewRequest";"parametre1";"parametre2"))=0)
   $0:=tcp_WaitOK
Fin de si
  
et à ajouter dans le au cas ou de tcp_SrvRequest
: ($request="MyNewRequest@")
   tcp_vtRequest:=tcp_Extraction ("MyNewRequest";$request)  
   $param1:=txt_CutOut (->tcp_vtRequest)  
   $param2:=txt_CutOut (->tcp_vtRequest)  
   ... traitement de la requête spécifique en fonction de $param1 et $param2
   $err:=0 `tout va bien sinon $err:=-1
   $0:=tcp_SendOK ($err)
  
Ici, $param1 contient "parametre1" et $param2 contient "parametre2". Vous pouvez traiter cette information selon vos besoins. Ensuite, il faut envoyer au client un accusé de reception. Utilisez tcp_SendOk en lui passant 0 si tout va bien ou -1 si le traitement n'abouti pas. N'oubliez pas que le client attend cet accusé de reception avec un time out de 20 secondes par défaut. Rappelez que ce temps est fixé dans tcpPrp.txt avec la propriété tcpTimeOut. Vous pouvez modifier la durée de ce time out sur le client à la volée avec tcp_SetTimeOut.
  
Deux points importants sont à souligner dans ce que nous venons de voir :
1 - vous avez envoyé une requête sur le serveur, ce qui vous est retourné est seulement un code d'erreur
2 - vous n'êtes pas sur un bind, après l'éxecution de la requête vous perdez le contexte du process qui a fait le travail. A la prochaine connexion, le listener ne vous proposera pas forcement le même process de requête.
  
Pour que le client soit en relation avec le même process sur le serveur, il faut créer un bind avec la méthode tcp_CreateBind. Maintenant c'est la méthode tcp_SrvOnBind qui va recevoir et traiter la requête. Comme pour tcp_SrvRequest, il s'agit d'un au cas ou. Vous pouvez opérer de la même manière pour inserer du code spécifique sur le serveur.
  
Pour obtenir une valeur particulière issue du traitement de la requête et pas simplement un code d'erreur, vous pouvez utiliser sur le client la méthode tcp_SendRequest. Votre requête est alors traitée par sur le serveur par la méthode tcp_SrvTreatSendRequest. Cette dernière est à l'identique de tcp_SrvTreatSendText, c'est un au cas ou prêt à accueilir du code spécifique. Cette méthode se termine par l'appel à tcp_Answer. Vous lui passez une chaine contenant la réponse à votre requête. Sur xShell tcp_SrvTreatSendRequest a un appel spécifique à rcd_TcpSrv. Cette méthode contient tout le code de traitement des requêtes du module rcd_ c'est à dire la librairie qui traite la gestion des enregistrements.
  
Voici un extrait de ce code qui retourne le time stamp serveur pour la synchronisation.
  
: ($1="GetRemoteSyn@")
`________________________________________________________________________________
`login pour la synchro de données
   rcd_OnStartupProcess
   $request:=txt_CutOut (->tcp_vtRequest)
   usr_Language:=$request `affecte le langage de l'utilisateur connecté
   rcd_vtSynTimeStamp:=hdl_GetNewHandle `envois au client un handle de synchro
   $Answer:=rcd_vtSynTimeStamp
  
Conclusion
  
tcp OpenServer vous permet de mettre en place un système de communication entre plusieurs bases 4D avec la possibilité d'implémenter facilement vos propres besoins de traitements au sein de mécanismes qui preservent le contexte du client. Consultez la partie tcp OpenClient pour voir toutes les requêtes déjà créées pour la gestion des données et l'échange d'information.
  
  
  
  
  
  
  
  
  
  
  




 | Haut de page | Retour