Tivoli Service Desk 6.0 Developer's Toolkit - Guide de programmation TSD Script
Retour à la table des matières
Ce chapitre introduit les concepts fondamentaux que vous devez comprendre pour pouvoir utiliser les
instructions des extensions de réseau TSD Script pour communiquer via votre réseau. Il décrit également des
concepts particuliers relatifs aux réseaux ainsi que les instructions et constantes TSD Script propres à ces
derniers.
Vous pouvez utiliser ces instructions TSD Script pour personnaliser le code source des applications
installées ou pour créer votre propre application TSD Script répartie.
Bien que ce chapitre traite brièvement de certains aspects fondamentaux du langage et des principes des réseaux TSD Script, on suppose que ces deux domaines vous sont familiers. Si vous devez modifier une application, nous vous conseillons de le faire avec l'aide d'une personne ayant déjà personnalisé des applications ou utilisé TSD Script et la boîte à outils du développeur (Developer's Toolkit).
Les instructions du langage TSD Script permettent l'utilisation des deux architectures de réseau suivantes :
Dans ce chapitre, la description des services réseau de TSD Script est généralement valable pour les deux architectures. Lorsque des différences existent, elles sont signalées.
De nombreux termes sont utilisés pour décrire les interactions entre les ordinateurs d'un réseau. Bien que vous en connaissiez déjà peut-être certains ou la totalité, le glossaire qui suit peut vous être utile car ces termes y sont définis spécifiquement dans le contexte des extensions de réseau de TSD Script.
Une communication bidirectionnelle se produit quand deux machines peuvent chacune jouer les rôles de client et de serveur. Autrement dit, si la machine A (client) peut demander à la machine B (serveur) de lui fournir un service, la machine B peut inverser les rôles, devenir le client et demander à la machine A de lui fournir un service. Voir aussi "Connexion inversée". Voir "Environnement d'égal à égal".
Un client est une application qui demande un service à un serveur. Un poste de travail qui se connecte à un serveur de fichiers via un réseau est un exemple de client. La connexion est établie à l'initiative du client.
Une connexion est une liaison logique entre un client et un serveur.
Un gestionnaire d'événements est une fonction TSD Script spéciale conçue pour traiter les événements asynchrones. Les gestionnaires d'événements s'exécutent sur le serveur et traitent les demandes de services qui leur sont transmises via le réseau.
Chaque connexion possède un descripteur. Ce dernier contient des informations concernant le poste de travail client et le service que le serveur doit lui fournir.
Un serveur TSD Script est un processus TSD Script qui s'exécute sur un ordinateur en réseau et fournit un service.
Le gestionnaire d'événements local est le gestionnaire d'événements qui fonctionne sur la machine locale. S'il traite des demandes émanant d'une autre machine, la machine locale est un serveur.
Les instructions NETx, ou extensions, sont les instructions TSD Script qui commencent par le préfixe NET. Elles ont été créées pour permettre aux applications TSD Script de communiquer via un réseau.
Un environnement d'égal à égal est un environnement dans lequel une même machine peut jouer à la fois le rôle de client et celui de serveur.
Enregistrer un gestionnaire d'événements signifie l'associer à une source d'événements.
Dans un environnement d'égal à égal, une connexion inversée est établie lorsqu'un serveur demande à un client de lui fournir un service, renversant ainsi les rôles de client et de serveur. La connexion inversée est établie pour gérer cette communication spécifique entre le serveur local et le serveur éloigné.
Un serveur est une machine qui fournit un service à un client. Une imprimante réseau est un exemple de serveur.
Un service est une fonction exécutée par un serveur. Par exemple, si le serveur est une imprimante, le service fourni est l'impression de documents.
Les gestionnaires d'événements sont utilisés dans TSD Script et dans la boîte à outils du développeur
(Developer's Toolkit) pour prendre en charge un environnement commandé par des événements. Dans un tel
environnement, un événement (tel que l'utilisation d'une touche, un clic de la souris ou un message réseau)
déclenche une réponse de l'application (telle que l'ouverture d'une boîte de dialogue ou la sélection d'une
entrée dans une zone). Pour traiter les événements, chaque application utilise des gestionnaires d'événements
spécifiques.
Les applications qui utilisent des gestionnaires d'événements n'ont pas besoin de demander ou de procéder à
des "sondages" pour savoir si des événements réseau se sont produits. Généralement, les
gestionnaires d'événements sont "en sommeil" (inactifs) jusqu'à ce qu'un événement se produise,
auquel cas ils traitent alors la demande de service correspondante.
Un serveur peut posséder plusieurs gestionnaires d'événements. Chacun d'eux est alors conçu pour fournir un
service spécifique ou un ensemble de services connexes, comme expliqué plus loin dans ce chapitre.
Les gestionnaires d'événements sont définis dans la section ROUTINES d'un programme TSD Script. Les
gestionnaires d'événements réseau doivent être déclarés avec le type NETCONNECTION.
Ce type est différent du type par défaut WINDOW. Le type déterminant le descripteur $Handle
utilisé, seuls les descripteurs d'événements de type NETCONNECTION peuvent être utilisés
avec les instructions NETx.
NETCONNECTION EVENT TalkConnectEvent(REF whdl: WINDOW )IS
Lorsque vous définissez un gestionnaire d'événements, vous devez également enregistrer son service, comme
expliqué dans les sections suivantes. Enregistrer un gestionnaire d'événements permet de l'associer à une
source d'événements.
Pour enregistrer un gestionnaire d'événements, vous pouvez utiliser deux instructions :
Les gestionnaires enregistrés à l'aide de la commande NetRegister sont appelés gestionnaires NetRegister. Ceux enregistrés à l'aide de la commande NetListen sont appelés gestionnaires NetListen.
Ce chapitre décrit comment enregistrer un gestionnaire à l'aide de la commande NetRegister, fréquemment utilisée pour les gestionnaires d'événements "standard". Pour savoir comment personnaliser les gestionnaires d'événements, reportez-vous à la section "Instructions avancées", plus loin dans ce chapitre.
Pour qu'un gestionnaire d'événements puisse recevoir et traiter des demandes de services, vous devez l'enregistrer auprès du serveur. Pour enregistrer un gestionnaire à l'aide de la commande NetRegister, utilisez la syntaxe suivante :
NetRegister( TalkConnectEvent, 'Talk' );
Lorsque vous enregistrez un gestionnaire d'événements, vous devez indiquer le nom du service qu'il fournit. Un service est une catégorie d'actions effectuées par un gestionnaire.
Dans l'exemple suivant, le nom du service défini pour le gestionnaire d'événements réseau TalkConnectEvent est Dialogue.
NETCONNECTION EVENT TalkConnectEvent(REF whdl: WINDOW )IS ACTIONS . .. END; NetRegister( TalkConnectEvent, 'Talk');
Outre les services mentionnés précédemment, une extension de numéro de port est prise en charge, qui permet d'indiquer un port IP. Le numéro de port contrôle :
La numéro de port par défaut est 5001, et le service par défaut, asenet/tcp. Si le service figure dans le fichier des services, asenet/tcp est utilisé à la place du numéro par défaut.
Pour indiquer un numéro de port dans la commande, utilisez la syntaxe suivante :
/p=nnn
Un numéro de port spécifié à partir de la ligne de commande remplace le port et le service par défaut.
Remarque : Les numéros de ports doivent être identiques sur le client et le serveur.
Vous pouvez créer un gestionnaire d'événements associé à un service dont le nom est une chaîne de longueur
nulle ('') ou $Unknown. Ce type de service est appelé service générique.
Lorsqu'un service générique est défini sur un serveur, il traite toutes les demandes du client pour
lesquelles le serveur ne trouve pas de nom de service correspondant.
Vous pouvez également définir un service générique sur le client. Dans ce cas, le serveur doit comporter
un service appelé '' ou $Unknown.
Remarque : Vous ne pouvez définir un service générique que lorsque vous enregistrez le
gestionnaire d'événements à l'aide de l'instruction NetRegister. (NetListen
utilise toujours un service générique.)
Lorsque vous enregistrez un gestionnaire d'événements, un modèle du service correspondant est défini sur le serveur. Ce modèle contient des informations provenant de la définition du gestionnaire dans la section ROUTINES du code, ainsi que des informations indiquées lors de l'enregistrement du gestionnaire.
Le modèle est conservé en mémoire jusqu'à ce qu'une connexion soit demandée. Les informations qu'il
contient sont alors utilisées pour instancier le service pour la connexion.
Vous pouvez apporter les deux modifications suivantes à un modèle :
Chaque fois que vous voulez modifier un modèle, vous pouvez soit réenregistrer le gestionnaire d'événements, soit enregistrer son service. Lorsque vous réenregistrez un gestionnaire, les nouvelles valeurs de paramètres prennent effet immédiatement et les nouvelles connexions établies pour le modèle les utilisent. Les connexions ne sont pas affectées par les modifications apportées au modèle.
Attention : Vous devez indiquer le même nom de service que dans le modèle original. Sinon, l'instruction NetRegister crée un autre modèle pour le gestionnaire et le modèle existant n'est pas modifié.
Une fois un modèle créé, il devient immédiatement et de façon permanente capable de recevoir et de traiter des demandes de service. Il est toutefois possible à tout moment de l'empêcher de répondre à ces demandes. Pour ce faire, vous devez réenregistrer le service avec le gestionnaire d'événements spécial $NullHandler, de la manière suivante :
NetRegister ($Nullhandler, 'service');
où "service" est le nom du service associé au gestionnaire à désactiver.
Une fois le service réenregistré avec $NullHandler, les demandes de service reçues pour le modèle sont rejetées mais les connexions existantes qui utilisent ce modèle ne sont pas affectées.
Si vous devez redémarrer le serveur, vous devez réenregistrer le gestionnaire d'événements et son service.
Un gestionnaire d'événements peut gérer des connexions avec de nombreux clients. Le simple examen du descripteur d'une connexion peut donc se révéler insuffisant pour déterminer le service fourni.
De même, il peut être difficile de déterminer quel serveur fournit un service ou à quel client il le fournit. C'est notamment le cas pour les gestionnaires d'événements de type NetListen, qui répondent à toutes les demandes de services qu'ils reçoivent et partagent leurs données d'instance.
TSD Script fournit deux instructions qui permettent d'obtenir des informations sur l'hôte (serveur) et le service à partir d'un descripteur de connexion :
TSD Script prenant en charge les architectures client-serveur et d'égal à égal, l'instruction NetGetHostName est conçue pour obtenir des informations sur la machine éloignée que celle-ci joue ou non le rôle de serveur.
Si vous exécutez l'instruction NetGetHostName sur le client, vous obtiendrez des informations concernant le serveur. Si vous l'exécutez sur le serveur, vous obtiendrez le nom du client.
Un serveur contient généralement de nombreux gestionnaires d'événements NETCONNECTION. Parfois, vous aurez besoin que ces gestionnaires puissent échanger des messages. Comme faire circuler ces messages sur le réseau ne constituerait pas une méthode de transmission efficace, la boîte à outils du développeur (Developer's Toolkit) fournit l'instruction NetLoopBack, qui vous permet d'envoyer un message à un gestionnaire d'événements réseau à partir de votre machine locale.
Les applications réseau TSD Script utilisent un protocole basé sur les connexions. En effet, c'est par
l'intermédiaire de connexions que les machines du réseau interagissent entre elles. Ainsi, pour qu'un serveur
puisse fournir un service à un client, une connexion doit être établie entre les deux machines.
Une connexion se compose des trois éléments suivants :
La combinaison de ces trois éléments rend chaque connexion unique. L'établissement et la fermeture d'une
connexion implique chacun de ces trois éléments.
Plusieurs connexions peuvent être établies entre un client et un serveur. Toutefois, pour un même client, une
seule connexion peut être établie pour un service particulier sur un serveur/port.
Remarque : Si une connexion est déjà établie entre un client et un gestionnaire
d'événements particulier d'un serveur, toute nouvelle demande concernant le service correspondant a pour
résultat le renvoi du descripteur de cette connexion.
Une fois que vous avez enregistré un gestionnaire d'événements et le service associé, le serveur est prêt à recevoir les demandes relatives à ce service.
Cette section décrit comment établir une connexion.
Les différentes étapes de la procédure d'établissement d'une connexion sont expliquées ci-dessous.
Lorsqu'un client demande un service, il doit indiquer précisément le nom de ce dernier. (Le nom du service est défini lorsque le gestionnaire d'événements est enregistré sur le serveur.) Il n'existe aucune liste des services fournis par un serveur et les noms de services ne sont pas soumis à la distinction majuscules/minuscules.
Un port peut être indiqué dans la chaîne du service. Si tel n'est pas le cas, le port par défaut est utilisé.
Un client peut demander un service générique en indiquant une chaîne de longueur nulle ou $Unknown. Dans ce cas, pour pouvoir satisfaire la demande, le serveur doit comporter un service appelé NetListen ou $Unknown.
Remarque : Si le client demande un service qui n'est pas défini sur le serveur et que celui-ci comporte un service générique ou NetListen, le serveur traite la demande du client avec le service générique.
Si le client ne peut pas communiquer avec le serveur, un code d'erreur HOST_UNREACHABLE (-13) est renvoyé au client.
Si aucun serveur TSD Script ne s'exécute, un code d'erreur HOST_UNREACHABLE (-13 ) est renvoyé au client.
Si tel est le cas, la valeur TRUE est renvoyée au client, ainsi que le descripteur de la connexion.
Si un nom de service concordant est trouvé, le serveur renvoie un descripteur au client. Ce descripteur pointe vers une copie du modèle qui fournit le service. Lorsque le client reçoit ce descripteur, il peut poursuivre son traitement.
Si le serveur trouve un service générique, il renvoie le descripteur correspondant au client. Ce descripteur pointe vers une copie du modèle qui fournit le service générique. Lorsque le client reçoit ce descripteur, il peut poursuivre son traitement.
Si le serveur trouve un gestionnaire NetListen, il renvoie à la machine client le descripteur contenant les informations relatives à la connexion. Ce descripteur pointe directement vers le gestionnaire NetListen. Lorsque le client reçoit ce descripteur, il peut poursuivre le traitement des données d'événement.
Si le serveur ne trouve pas de gestionnaire NetListen, la procédure continue à l'étape 10. Si aucun descripteur d'événement NetListen n'est trouvé, la procédure continue à l'étape 8.
Une fois le message $MsgNetConnect traité sur le serveur, la connexion est établie et le service peut être utilisé.
La fermeture d'une connexion s'effectue généralement à l'initiative du client, mais elle peut également se produire à l'initiative du serveur. Dans les deux cas, l'instruction NetClose est utilisée pour interrompre la connexion.
Remarque : En cas de défaillance du client ou du serveur, la connexion qui les relie est automatiquement interrompue. Pour rétablir la communication entre les deux machines, vous devez alors rétablir la connexion.
Lorsqu'un client ferme une connexion, il se produit ce qui suit :
Remarque : Si le gestionnaire d'événements est de type NetListen, aucunes données d'instance spécifiques ne sont définies pour la connexion. La procédure de fermeture est donc terminée dès que le descripteur est marqué comme fermé et aucun message $MsgNetDestroy n'est envoyé.
Si le programme client ou serveur s'arrête, ou si une coupure intervient dans le réseau, les étapes 2 et 3 sont tout de mêmes exécutées.
Si le serveur décide de fermer la connexion, il n'existe alors plus aucune communication entre lui et le client.
La prochaine fois que le client tente de communiquer avec le serveur, il détecte la fermeture et génère un
message d'erreur indiquant, par exemple, "descripteur incorrect".
Dans un environnement d'égal à égal, NetClose ferme à la fois la connexion client et la
connexion serveur.
Les données d'instance sont des données TSD Script définies par l'utilisateur qui sont associées à une connexion. Elles sont créées en même temps que la connexion et sont détruites lors de sa fermeture.
Le gestionnaire d'événements reçoit une référence aux données d'instance dans chaque message concernant la connexion. Les données d'instance contiennent des informations spécifiques à la connexion.
Lorsque vous enregistrez un gestionnaire d'événements avec NetRegister, vous pouvez affecter une valeur initiale à ses données d'instance. Toutes les connexions ultérieurement établies pour le modèle correspondant reçoivent un exemplaire des données d'instance initialisées avec la valeur indiquée ou, à défaut, avec $Unknown.
Lorsque vous définissez des données d'instance, souvenez-vous que :
Par exemple :
connectionData is Record callCount = INTEGER; . . . END;
NETCONNECTION EVENT MyEvent (REF data: ConnectionData); ACTIONS When $Event IS $MsgCreate Then data.callCount=1; . . . END; END; StmtData : ConnectionData; NetRegister( MyEvent {StartDate}, 'Service');
Lors de l'établissement d'une connexion, les données d'instance définies pour le gestionnaire d'événements sont instanciées dans l'exemplaire du modèle associé à la connexion et reçoivent leur valeur initiale. Ce processus s'appelle initialisation.
Si vous définissez les données d'instance dans le modèle avec la valeur $Unknown, aucune initialisation n'a lieu.
Aucune initialisation n'a lieu si vous n'attribuez pas de valeur initiale aux données d'instance. En effet, dans ce cas, le système considère que la valeur initiale est $Unknown.
Plusieurs connexions peuvent être établies pour un gestionnaire d'événements NetRegister. Chacune de ces connexions possède son propre exemplaire des données d'instance.
Un client peut envoyer une demande à un serveur à tout moment, que ce serveur soit ou non en train de traiter une demande précédente. Selon que le client a besoin d'une réponse plus ou moins rapide du serveur et qu'il requiert que celui-ci lui renvoie ou non des données, il peut envoyer sa demande à l'aide d'une instruction bloquante ou non bloquante :
Lorsqu'un serveur reçoit une demande, il l'ajoute à sa file d'attente. Le serveur traite les demandes dans l'ordre dans lequel il les a reçues. (Dans certains cas, il se peut qu'il place les messages bloquants avant les messages non bloquants dans sa file d'attente.) Selon l'état du réseau, il peut se passer du temps avant que le serveur puisse traiter une demande.
Si l'instruction envoyée au serveur est bloquante, aucune information n'est renvoyée au client tant que le
traitement de la demande n'est pas terminé sur le serveur.
SendMessage est seule instruction bloquante de TSD Script.
Pour éviter tout risque d'interblocage entre un client et un serveur, une seule instruction
SendMessage peu être active simultanément sur une connexion.
Si l'instruction envoyée au serveur est non bloquante, le serveur ajoute la demande à sa file d'attente et renvoie au client une réponse qui lui indique en substance : "J'ai reçu votre demande". Le client peut alors poursuivre son traitement.
Les instructions non bloquantes sont les suivantes :
Pour communiquer avec le serveur, vous pouvez utiliser des instructions bloquantes ou non bloquantes. Ces deux types d'instructions présentent des risques dont vous devez être conscient :
Dans TSD Script et la boîte à outils du développeur (Developer's Toolkit), les descripteurs sont utilisés de façon intensive pour suivre l'activité des fenêtres et du réseau.
L'utilisation de descripteurs est obligatoire pour les connexions via lesquelles des instructions SendMessage ou PostMessage sont transmises. Ces instructions sont respectivement bloquantes et non bloquantes. Cette caractéristique détermine le comportement du client et du serveur.
Le serveur ouvre un descripteur lorsqu'il localise le modèle de gestionnaire d'événements qui contient le service demandé par le client. Le descripteur se trouve dans le paramètre $Handle ; il est transmis au groupe d'événements qui gère la connexion.
Le serveur marque un descripteur comme étant fermé lorsqu'il ferme son extrémité de la connexion. Si vous tentez d'accéder à une connexion fermée, vous recevez un message d'erreur (Invalid_Handle).
Les instructions TSD Script NETx sont utilisables avec les architectures client-serveur et d'égal à égal (entre homologues). L'instruction NetConnect possède deux formats, correspondants à ces deux architectures.
Dans une architecture client-serveur, le client doit préciser le nom d'hôte et le service de telle sorte que le serveur puisse satisfaire la requête du client en renvoyant le service demandé.
FUNCTION NetConnect(REF hndlHost: NETCONNECTION, .VAL hostName: STRING, . VAL service: STRING .): INTEGER;
Pour pouvoir répondre au client dans l'architecture d'égal à égal, le serveur doit établir une connexion de renvoi. Le format d'égal à égal est en réalité un raccourci permettant de créer une connexion de renvoi. Ce format est facultatif ; vous pouvez obtenir les mêmes résultats en utilisant le format client-serveur.
FUNCTION NetConnect( VAL hndlHost: NETCONNECTION ): INTEGER;
Pour les connexions d'égal à égal, une seul descripteur est nécessaire. Ce dernier contient toutes les données relatives à la connexion.
Pour une description détaillée de NetGetHostName ou NetGetService, reportez-vous au chapitre suivant.
Pour envoyer une réponse au serveur éloigné, utilisez la constante $Handle. Pour initialiser une connexion de renvoi, utilisez la commande suivante :
NetConnect( $Handle );
Jusqu'ici, ce chapitre s'est attaché à décrire la méthode "standard" permettant de créer et d'enregistrer un gestionnaire d'événements, à l'aide de l'instruction NetRegister. Pour les applications qui nécessitent un plus grand contrôle des connexions, TSD Script fournit d'autres instructions, qui peuvent être utilisées ensemble pour enregistrer un gestionnaire d'événements. Il s'agit des instructions :
Les gestionnaires d'événements NetAccept sont très similaires aux gestionnaires d'événements NetRegister.
Remarque : Vous n'êtes pas obligé d'utiliser l'instruction NetListen ou NetAccept pour créer une application réseau opérationnelle.
Ce tableau récapitule les différences existant entre les gestionnaires NetRegister et NetListen.
NetListen ne créant pas de nouvelles données d'instance pour chaque connexion, l'établissement d'une connexion à l'aide de NetListen est un peu plus rapide.
NetListen est bien adapté aux services simples, qui ne nécessitent pas le maintien d'un contexte entre les messages.
Elément de comparaison | NetRegister | NetListen |
Nombre de gestionnaires d'événements | De nombreux gestionnaires d'événements NetRegister peuvent s'exécuter simultanément sur un serveur. | Un seul gestionnaire d'événements NetListen peut être défini pour chaque serveur. |
Service enregistré | Un gestionnaire d'événements NetRegister est enregistré avec un service spécifique. Le client doit indiquer exactement ce nom de service pour qu'une concordance de service soit détectée avec le modèle approprié. | Un gestionnaire d'événements NetListen n'est associé à aucun service spécifique. Une concordance de service n'est établie avec le gestionnaire NetListen que si aucun autre modèle concordant n'existe sur le serveur. |
Modèle | Lors de l'enregistrement d'un gestionnaire d'événements NetRegister, un modèle de ce gestionnaire est créé. Ce modèle contient les informations spécifiques à la connexion. | Aucun modèle n'est créé lors de l'enregistrement d'un gestionnaire d'événements NetListen. Les informations spécifiques à la connexion doivent donc être gérées par l'application. |
Données d'instance | Chaque connexion possède son propre exemplaire des données d'instance. | Un jeu de données d'instance est défini pour le gestionnaire d'événements. Chaque connexion établie pour ce gestionnaire partage ces données d'instance. |
Ports | Le service peut utiliser un port de remplacement. | Le service ne peut utiliser que le port par défaut. |
Un gestionnaire NetListen et un gestionnaire NetRegister peuvent s'exécuter simultanément sur un serveur. Les clients ne sachant pas comment une demande est traitée, ils ne peuvent donc pas l'adresser à un gestionnaire spécifique.
Les gestionnaires d'événements NetListen sont utilisés pour fournir des services qui ne nécessitent pas le maintien d'informations contextuelles pour une connexion. Les gestionnaires d'événements NetListen nécessitent un peu moins de ressources serveur et créent les connexions un peu plus vite que les gestionnaires NetRegister.
La demande d'un client n'est mise en correspondance avec un gestionnaire NetListen que si
aucune autre concordance de service (y compris avec un modèle générique) n'est trouvée. Le client envoie le
nom du service au gestionnaire d'événements NetListen du serveur. Pour déterminer le nom du
service demandé, le gestionnaire NetListen doit examiner le descripteur à l'aide de
l'instruction NetGetService.
Toutefois, le client, n'a aucune garantie que le service demandé est pris en charge par le serveur.
Plusieurs connexions NetListen peuvent coexister puisqu'elles partagent les mêmes données d'instance. Par conséquent, lors de la fermeture d'une connexion NetListen, les données d'instance ne sont pas détruites.
Lors de la fermeture d'une connexion NetListen, vous devez faire le ménage dans les ressources qu'elle utilisait.
Le descripteur de chaque connexion NetListen contient les informations concernant le type de service demandé par le client.
Le gestionnaire d'événements NetListen n'associe pas de données d'instance à chaque connexion. Vous devez donc assurer vous-même le suivi de chaque connexion et de son activité. La possibilité de suivre individuellement les connexions constitue un autre avantage lié à l'utilisation de l'instruction NetListen pour enregistrer les gestionnaires d'événements.
Chaque connexion établie pour NetListen partage l'exemplaire des données d'instance défini pour le gestionnaire d'événements NetListen. Si vous voulez associer un ensemble de données d'instance spécifiques à l'une de vos connexions NetListen, vous pouvez utiliser l'instruction NetAccept pour cette connexion.
Remarque : L'instruction NetAccept ne peut être utilisée que pour une connexion NetListen. Cette connexion est accessible via son descripteur. NetAccept permet également d'associer un nouveau gestionnaire d'événements à la connexion.
Les données d'instance que vous associez à la connexion ne sont pas utilisées pour les connexions déjà établies ou qui le seront ultérieurement pour le gestionnaire d'événements NetListen. La connexion est modifiée dès que vous appelez NetAccept.
Toutes les demandes portant sur la même paire hôte-service sont dirigées directement vers le nouveau gestionnaire d'événements.
Remarque : La combinaison des instructions NetListen et NetAccept produisant le même résultat que l'instruction NetRegister, il vous paraîtra peut-être plus simple d'utiliser cette dernière.
Cet exemple illustre la création d'un programme de dialogue simple entre deux ordinateurs en réseau. Il démontre l'interaction entre deux machines dans un environnement d'égal à égal (entre homologues).
KNOWLEDGEBASE NetTalk;
CONSTANTS menuList IS { '~File', 'e~Xit', '', '~Host', '~Open', '', '~Help', '~About', '' }: LIST OF STRING; MsgUserChar IS $MsgUser; MsgRemoteChar IS $MsgUser + 1; MsgTalkClose IS $MsgUser + 2;
ROUTINES
EVENT TalkMainEvent; FUNCTION CreateTalkWindow( VAL host: NETCONNECTION ) : WINDOW; PROCEDURE NetTalkMain;
PRIVATE TYPES TALK_RECORD IS RECORD xLen: INTEGER; -- Width of window in characters yLen: INTEGER; -- Height of window in characters whdlMe: WINDOW; -- Window where local input is displayed whdlYou: WINDOW; -- Window where remote input is displayed host: NETCONNECTION; -- Handle host END;
PANNEL_DATA IS RECORD whdlParent: WINDOW; curX: INTEGER; -- X location of cursor on the window curY: INTEGER; -- Y location of cursor on the window lines: LIST OF STRING; -- List of all lines being edited END;
ROUTINES
NETCONNECTION EVENT TalkConnectEvent(REF whdl: WINDOW )IS VARIABLES result : INTEGER;
ACTIONS WHEN $Event IS $MsgNetConnect THEN -- Create a talk window. -- Create a connection to service this talk session result := NetConnect( $Handle ); IF result < 1 THEN WinMessageBox(whdl,'Error',$MBOk + $MBIconError, 'Connection failed ERROR ' & result ); Exit( 0 ); END; whdl := CreateTalkWindow( $handle ); IF whdl = $UNKNOWN THEN WinMessageBox(whdl,'Error',$MBOk + $MBIconError, 'Window creation failed' ); NetClose( $Handle ); Exit( 0 ); END; ELSWHEN MsgRemoteChar THEN -- Pass the character from the remote machine to the talk window SendMessage( whdl, MsgRemoteChar, $KeyCode ); ELSWHEN MsgTalkClose THEN NetClose( $Handle ); ELSWHEN $MsgNetClose THEN -- When the windows close on the remote machine clean up here SendMessage( whdl, $MsgClose ); NetClose( $Handle ); END; END;
EVENT TalkMainEvent IS VARIABLES host : NETCONNECTION; hostName : STRING; result : INTEGER;
ACTIONS WHEN $Event IS $MsgCreate THEN WinSetMenuBar( $Handle, menuList ); ELSWHEN $MsgMenu THEN WHEN $MenuSelection IS 101 THEN SendMessage( $Handle, $MsgClose ); ELSWHEN 201 THEN WinEditField($Desktop, hostName, 0, 0, 40, 'Enter host name', BitOr($WinTitle, $WinBorder, $WinAutoPos ) ); -- Create a talk connextion to hostname result := NetConnect( host, hostName, 'Talk' ); IF result <> 1 THEN WinMessageBox($Handle, 'Error', $MBOk + $MBIconError, 'Connection failed ERROR ' & result ); END; END; END; END; EVENT TalkPannelEvent( REF pannelData: PANNEL_DATA ) IS ACTIONS WHEN $Event IS $MsgCreate THEN pannelData.curX := 1; pannelData.curY := 1; ListInsert( pannelData.lines, '' ); ELSWHEN $MsgPaint THEN -- Clear window, and re display contents WinSetFont($Handle, 'System Monospaced', 10, 0 ); WinClear($Handle ); WinWriteLn($Handle, pannelData.lines ); ELSWHEN $MsgChar THEN -- The parent window processes all characters entered SendMessage(pannelData.whdlParent, $MsgChar, $KeyCode ); ELSWHEN MsgUserChar THEN WHEN $KeyCode IS $KeyReturn THEN -- Enter key is a new line pannelData.curX := 1; pannelData.curY := pannelData.curY + 1; ListInsert(pannelData.lines, '' ); ELSE -- Add character to current line, and display it WinSetFont($Handle, 'System Monospaced', 10, 0 ); WinGotoXY($Handle, pannelData.curX, pannelData.curY ); WinWrite($Handle, Char( $KeyCode ) ); pannelData.curX := pannelData.curX + 1; pannelData.lines[ $CURRENT ] := StrInsert(pannelData.lines [ $CURRENT ], Char( $KeyCode ), 1000 ); END; END; END;
EVENT TalkEvent( REF talkData: TALK_RECORD ) IS VARIABLES pannel : PANNEL_DATA; yLen : INTEGER;
ACTIONS WHEN $Event IS $MsgCreate THEN -- Create 2 display panels for local, and remote characters and pass in parent pannel.whdlParent := $Handle; yLen := talkData.yLen / 2; WinCreate($Handle, talkData.whdlMe, TalkPannelEvent{ pannel }, 0, 0, talkData.xLen, yLen, '', $WinField ); yLen := talkData.yLen - yLen; WinCreate($Handle, talkData.whdlYou, TalkPannelEvent{ pannel }, 0, yLen + 1, talkData.xLen, yLen,'', $WinField ); ELSWHEN $MsgDestroy THEN PostMessage( talkData.host, MsgTalkClose ); ELSWHEN $MsgSize THEN -- Position and size panels to fit window when it is resized talkData.xLen := $EventParm( 1, INTEGER ); talkData.yLen := $EventParm( 2, INTEGER ); yLen := talkData.yLen / 2; SendMessage(talkData.whdlMe,$MsgSetSize talkData.xLen, yLen); yLen := talkData.yLen - yLen; SendMessage(talkData.whdlYou,$MsgSetSize, talkData.xLen,yLen ); SendMessage(talkData.whdlYou,$MsgMove,1, yLen + 1 ); ELSWHEN $MsgChar THEN -- Send local characters to top pannel for display SendMessage(talkData.whdlMe, MsgUserChar, $KeyCode ); -- also send character to remote host to display PostMessage(talkData.host, MsgRemoteChar, $KeyCode ); ELSWHEN MsgRemoteChar THEN -- Send remote character to bottom pannel for display SendMessage(talkData.whdlYou, MsgUserChar, $KeyCode ); ELSWHEN $MsgPaint THEN WinClear( $Handle ); END; END;
FUNCTION CreateTalkWindow( VAL host : NETCONNECTION ) : WINDOW IS VARIABLES whdlNetTalk: WINDOW; talkData: TALK_RECORD; result: INTEGER;
ACTIONS talkData.host := host; result := WinCreate($Desktop, whdlNetTalk, TalkEvent{talkData}, 0, 0, 0, 0, NetGetHostName(host), BitOr($WinBorder, WinTitle, $WinResize, $WinSysMenu, $WinAutoSize, $WinAutoPos, $WinTaskList)); IF result < 1 THEN WinMessageBox($Desktop, 'Error', $MBOk + $MBIconError, 'Cannot create talk main window. Error: '&result ); END; EXIT( whdlNetTalk ); END;
PROCEDURE NetTalkMain IS VARIABLES whdlNetTalk: WINDOW; result: INTEGER;
ACTIONS result := WinCreate($Desktop, whdlNetTalk, TalkMainEvent, 0, 0, 40, 0, 'Network talk program', BitOr($WinBorder, $WinTitle, $WinResize, $WinSysMenu, $WinMenu, $WinTaskList)); IF result < 1 THEN WinMessageBox($Desktop, 'Error', $MBOk + $MBIconError, 'Cannot create talk main window. Error: ' &result ); END; NetRegister( TalkConnectEvent, 'Talk' ); WinWait( whdlNetTalk ); END;
Tivoli Service Desk 6.0 Developer's Toolkit - Guide de programmation TSD Script