3 \documentclass[11pt]{article}
5 \textheight=23cm \textwidth=16cm
7 \oddsidemargin=0pt \evensidemargin=0pt \marginparwidth=2cm
9 \newcommand{\func}[1]{\texttt{#1}}
10 \newcommand{\T}[1]{\texttt{#1}}
12 \title{Communication Toolbox}
14 \date{Manual Version 1.0 for Scilab 2.4}
21 This is a beta version of the Communication Toolbox. It lacks security
22 problems when using remote communications (see~\ref{remote}). A good
23 error trapping is also under development, so you can ``block'' Scilab
24 when doing mistakes in the names of the linked applications.
29 GeCI is an interactive communication manager created in order to
30 manage remote executions of programs and allow exchanges of messages
31 between those programs. It offers the possibility to exploit numerous
32 machines on a network, as a virtual computer, by creating a
33 distributed group of independent softwares.
35 It has been originally developed in the CalICo Project (LaBRI-
36 Universit\'e Bordeaux I, France) by Nadine Rouillon.
38 In Scilab, GeCI manages communications between Scilab itself and other
39 applications (included Scilab itself). In fact, the \T{scilab}
40 command is a shell script which at last executes the command:
43 <Scilab directory>/bin/geci -local <Scilab directory>/bin/scilex
46 where \verb|<Scilab directory>| is the main directory of Scilab.
47 We will use \verb|<Scilab directory>| to denote this directory in
49 This means that Scilab is ready to communicate with others
50 applications. In particular, this is the way Metanet Windows are
51 executed in the Metanet toolbox.
53 In section~\ref{functions}, we explain how to use the Scilab functions of the
54 Communication Toolbox and in section~\ref{internal} we describe the
55 way to make an application able to communicate with Scilab.
57 \section{Functions of the Communication Toolbox}\label{functions}
59 There are six functions in the Communication Toolbox to make
60 communications. They are
61 \func{CreateLink}, \func{DestroyLink}, \func{ExecAppli},
62 \func{GetMsg}, \func{SendMsg} and \func{WaitMsg}. They are described
63 in the on-line manual. We are only going here to describe how to use
64 them for exchanging messages between two Scilab programs. You will find
65 in section~\ref{examples} how to communicate between Scilab and other
68 After executing Scilab, you can execute another Scilab on the same
69 computer from the first one and create a link to it and from it by
73 -->h=unix_g("hostname");
74 -->ExecAppli(SCI+"/bin/scilex",h,"Scilab2")
75 -->CreateLink("SELF","Scilab2")
76 -->CreateLink("Scilab2","SELF")
79 Each application linked to GeCI has a name. Two special names are defined,
80 \T{"SELF"} always stands for the name of the Scilab program where you
81 are and \T{"XGeCI"} stands for the first Scilab program.
83 Now, another Scilab named \T{Scilab2} appears and you can send a
84 message to it from the first Scilab:
87 -->SendMsg("Hi!","How are you?");
90 And in \T{Scilab2}, you can get it:
93 -->[type,msg,apply] = GetMsg()
105 You do not have to tell to which application you want to send the
106 message: you send it to all applications linked to you.
108 You can also send a message from \T{Scilab2} to first Scilab:
111 -->SendMsg("Answer","Fine and you?");
114 and you get it in Scilab:
117 -->[type,msg,apply] = GetMsg()
129 You can even open a new Scilab, named \T{Scilab3} for instance, link it
130 to Scilab and/or \T{Scilab2} and exchange messages between them after
131 having created links. Use the \func{DestroyLink} function to destroy a
134 Note that there is no notion of client and server. The server is the
135 GeCI program and all the applications which communicate are at the
136 same level. That means that the \func{CreateLink}, \func{DestroyLink}
137 and \func{ExecAppli} functions can be used in any Scilab instance.
139 \section{Creating applications to communicate with Scilab}\label{internal}
141 To communicate with Scilab, an application must have been prepared
142 for, by including a communication library in it.
143 The way to do this is described in this section.
145 Suppose you have a C or fortran program and you want to add in it the
146 functionalities to communicate using GeCI. For this you need to add
147 new C functions in the code. For instance, you can create a new C file
148 which you are going to link with your existing C or fortran
149 program. You also need to link the program with the following library:
152 <Scilab directory>/libs/libcomm.a
155 At the beginning of the C code, you must include the following header
159 #include "<Scilab directory>/routines/libcomm/libCalCom.h"
160 #include "<Scilab directory>/routines/libcomm/libCom.h"
163 Then you define the messages known by the application, usually:
166 static void QuitAppli();
167 static void EndAppli();
168 static void ParseMessage();
169 static void MsgError();
171 static actions_messages tb_messages[]={
172 {ID_GeCI,MSG_QUITTER_APPLI,NBP_QUITTER_APPLI,QuitAppli},
173 {ID_GeCI,MSG_FIN_APPLI,NBP_FIN_APPLI,EndAppli},
174 {NULL,MSG_DISTRIB_LISTE_ELMNT,NBP_DISTRIB_LISTE_ELMNT,ParseMessage},
175 {NULL,NULL,0,MsgError}};
178 All these functions have one argument of type \T{message}.
180 \T{QuitAppli} is executed when THIS application terminates.
182 \T{EndAppli} is executed when an application executed by THIS
183 application terminates.
185 \T{MsgError} is executed when there is an error in a message.
187 \T{ParseMessage} is executed to get the received messages.
188 For instance, you can write \T{ParseMessage} the following way:
191 static char *TheAppli;
192 static char *TheType;
195 static void ParseMessage(message)
198 int lappli, ltype, lmsg;
200 lappli = strlen(message.tableau[0]);
201 if ((TheAppli = (char *)malloc((unsigned)sizeof(char)*(lappli + 1)))
205 strcpy(TheAppli,message.tableau[0]);
207 ltype = strlen(message.tableau[3]);
208 if ((TheType = (char *)malloc((unsigned)sizeof(char)*(ltype + 1)))
212 strcpy(TheType,message.tableau[3]);
214 lmsg = strlen(message.tableau[4]);
215 if ((TheMsg = (char *)malloc((unsigned)sizeof(char)*(lmsg + 1)))
219 strcpy(TheMsg,message.tableau[4]);
226 \item in \T{TheAppli} the name of the application which has sent the message
227 \item in \T{TheType} the type of the message (an ASCII string)
228 \item in \T{TheMsg} the message (an ASCII string)
231 Then you must initialize the communications.
233 For this, the main function of the
234 application must understand the arguments \T{-pipes <pipe1> <pipe2>} which
235 are automatically given by GeCI when executing it by:
238 geci -local <my application>
241 A simple way to do this is to use the \T{find} function:
243 static int find(s,n,t)
250 if (!strcmp(s,t[i])) return(i);
260 igeci = find("-pipes",argc,argv);
261 if (igeci == -1) exit(1);
263 p1 = atoi(argv[igeci+1]); p2 = atoi(argv[igeci+2]);
266 And you initialize the communications:
269 init_messages(tb_messages,p1,p2);
272 Then it is possible to use the functions of GeCI. For this, you have
273 to send messages to GeCI.
276 \item You can execute an application from your program:
279 envoyer_message_parametres_var(ID_GeCI,
288 where \T{<appli>} is the name you give to the application you execute,
290 is the name of the host where you want to execute the application and
291 \T{<path appli>} is the path of the program of the application on the
292 host. If you want to execute an application locally on the same host,
293 you give the name of your host. You can also execute the application
294 on a remote host on Internet, see \ref{remote}.
296 Every application has a name. The name of your program has also a name
297 given automatically. When you have to use it (to link applications for
298 instance), you can get it by \T{identificateur\_appli()}.
300 \item To create a (directed) link from the application named \T{<appli1>} to
301 the application named \T{<appli2>}:
304 envoyer_message_parametres_var(ID_GeCI,
311 Then you are able to send messages from \T{<appli1>} to \T{<appli2>}.
313 Note that the two applications must have been executed first by the
316 \item To destroy a link from \T{<appli1>} to \T{<appli2>}:
319 envoyer_message_parametres_var(ID_GeCI,
320 MSG_DETRUIRE_LIAISON,
326 \item To send a message to all linked applications:
329 envoyer_message_parametres_var(ID_GeCI,
330 MSG_POSTER_LISTE_ELMNT,
336 where \T{<type>} is a string corresponding to the type of the message
337 and \T{<msg>} is the string corresponding to the message.
339 Note that before being able to exchange messages, applications must
342 \item To get a message in an asynchronous way:
348 \item To wait for a message from \T{<appli>} in a synchronous way:
351 attendre_reponse(<appli>,
352 MSG_DISTRIB_LISTE_ELMNT,
353 NBP_DISTRIB_LISTE_ELMNT);
357 \subsection{Communication between remote hosts}\label{remote}
360 CAUTION: With this beta version of the Communication Toolbox, nothing
361 has been done for adressing possibly security holes and problems when
362 using the \T{gecid} daemon and remote \T{geci} programs. So use them
368 With GeCI you can also have communications between programs on remote
371 Suppose you are on host \T{h1}, have a local application \T{a1} and
372 you want to execute an application \T{a2} on host \T{h2} and open a
373 communication between \T{a1} and \T{a2}.
375 First, you must have a \T{geci} program on both hosts. Second you must
376 have a daemon, called \T{gecid}, on the remote host. The C source code
377 of this daemon is given in the \T{geci} directory of Scilab
380 You have to give the good path of \T{geci} program in the source code
381 of program \T{gecid} in variable \T{GECI}.
383 Then, you first start the daemon \T{gecid} on host \T{h2}.
384 After, you execute application \T{a1}, Scilab for instance, on host
385 \T{h1} and use GeCI functions to execute application \T{a2} on host \T{h2}:
386 you have to give the complete Internet name of host \T{h2} in these
389 If application \T{a2} is another Scilab, do not forget to give the
390 good \T{-display} argument to the \T{scilex} command.
392 In fact the \T{gecid} daemon will wait for a socket connection on port
393 2001 and then start \T{geci} on host \T{h2}.
395 \subsection{Examples}\label{examples}
397 You will find below two complete C programs as examples.
399 The first program opens Scilab,
400 wait for messages and print them. We call the file of this program
402 and we suppose that the main directory of Scilab,
403 \verb|<Scilab directory>| is \T{/usr/local/lib/scilab-2.4}.
405 Compile this program with:
408 cc -o alpha alpha.c /usr/local/lib/scilab-2.4/libs/libcomm.a
411 and execute it with (if shell is csh):
414 setenv SCI /usr/local/lib/scilab-2.4
415 /usr/local/lib/scilab-2.4/bin/geci -local alpha
418 Then a new Scilab is executed and you can execute in it commands of the form
419 \T{SendMsg("Hi","How are you?")}. On the console you must see:
421 Message received from Scilab
423 message: How are you?
426 "alpha.c" is given below and in the directory \T{docs/comm} of Scilab
430 /***************************************************************************/
434 /* Communications headers */
435 #include "/usr/local/lib/scilab-2.4/routines/libcomm/libCalCom.h"
436 #include "/usr/local/lib/scilab-2.4/routines/libcomm/libCom.h"
438 static void QuitAppli();
439 static void EndAppli();
440 static void ParseMessage();
441 static void MsgError();
444 static actions_messages tb_messages[]={
445 {ID_GeCI,MSG_QUITTER_APPLI,NBP_QUITTER_APPLI,QuitAppli},
446 {ID_GeCI,MSG_FIN_APPLI,NBP_FIN_APPLI,EndAppli},
447 {NULL,MSG_DISTRIB_LISTE_ELMNT,NBP_DISTRIB_LISTE_ELMNT,ParseMessage},
448 {NULL,NULL,0,MsgError}};
450 static void QuitAppli(message)
453 printf("Quit application\n");
457 static void EndAppli(message)
460 printf("End application\n");
463 static void MsgError(message)
466 printf("Bad received message\n");
469 static char *TheAppli;
470 static char *TheType;
473 /* ParseMessage is executed when a message is received */
474 static void ParseMessage(message)
477 int lappli, ltype, lmsg;
479 lappli = strlen(message.tableau[0]);
480 if ((TheAppli = (char *)malloc((unsigned)sizeof(char)*(lappli + 1)))
484 strcpy(TheAppli,message.tableau[0]);
486 ltype = strlen(message.tableau[3]);
487 if ((TheType = (char *)malloc((unsigned)sizeof(char)*(ltype + 1)))
491 strcpy(TheType,message.tableau[3]);
493 lmsg = strlen(message.tableau[4]);
494 if ((TheMsg = (char *)malloc((unsigned)sizeof(char)*(lmsg + 1)))
498 strcpy(TheMsg,message.tableau[4]);
501 static int find(s,n,t)
508 if (!strcmp(s,t[i])) return(i);
519 /* Scilab application to execute */
520 char *scilex = "/usr/local/lib/scilab-2.4/bin/scilex";
522 igeci = find("-pipes",argc,argv);
523 if (igeci == -1) exit(1);
525 p1 = atoi(argv[igeci+1]); p2 = atoi(argv[igeci+2]);
527 /* Intialization of communications */
528 init_messages(tb_messages,p1,p2);
530 /* Get the name of my computer */
531 gethostname(myhost,128);
533 /* Execute Scilab with name "Scilab" on my local host */
534 envoyer_message_parametres_var(ID_GeCI,
542 /* Link THIS application with "Scilab" */
543 envoyer_message_parametres_var(ID_GeCI,
545 identificateur_appli(),
548 /* Link "Scilab" with THIS application */
549 envoyer_message_parametres_var(ID_GeCI,
552 identificateur_appli(),NULL);
554 /* Loop waiting for messages */
557 if (TheType != NULL) {
558 printf("Message received from %s\n",TheAppli);
559 printf(" type: %s\n",TheType);
560 printf(" message: %s\n",TheMsg);
561 TheAppli = NULL; TheType = NULL; TheMsg = NULL;
565 /***************************************************************************/
570 The second program has everything to communicate with another
571 application linked to GeCI, Scilab for instance.
572 It waits for messages and print them. We call the file of this program
574 and we suppose that the main directory of Scilab,
575 \verb|<Scilab directory>| is \T{/usr/local/lib/scilab-2.4}.
577 Compile this program with:
580 cc -o beta beta.c /usr/local/lib/scilab-2.4/libs/libcomm.a
583 Then, being in the directory where \T{beta} lies, execute Scilab and
584 issue the following Scilab command:
586 // get host name of my computer
588 // execute program beta from Scilab and give it "Beta" as a name
589 ExecAppli("beta",h,"Beta")
590 // create a link from Scilab to
591 CreateLink("SELF","Beta")
592 // send a message to "Beta"
593 SendMsg("Hi","How are you?")
596 On the console you must seen (written by \T{beta}):
598 Message received from Scilab
600 message: How are you?
603 "beta.c" is given below and in the directory \T{docs/comm} of Scilab
607 /***************************************************************************/
611 /* Communications headers */
612 #include "/usr/local/lib/scilab-2.4/routines/libcomm/libCalCom.h"
613 #include "/usr/local/lib/scilab-2.4/routines/libcomm/libCom.h"
615 static void QuitAppli();
616 static void EndAppli();
617 static void ParseMessage();
618 static void MsgError();
621 static actions_messages tb_messages[]={
622 {ID_GeCI,MSG_QUITTER_APPLI,NBP_QUITTER_APPLI,QuitAppli},
623 {ID_GeCI,MSG_FIN_APPLI,NBP_FIN_APPLI,EndAppli},
624 {NULL,MSG_DISTRIB_LISTE_ELMNT,NBP_DISTRIB_LISTE_ELMNT,ParseMessage},
625 {NULL,NULL,0,MsgError}};
627 static void QuitAppli(message)
630 printf("Quit application\n");
634 static void EndAppli(message)
637 printf("End application\n");
640 static void MsgError(message)
643 printf("Bad received message\n");
646 static char *TheAppli;
647 static char *TheType;
650 /* ParseMessage is executed when a message is received */
651 static void ParseMessage(message)
654 int lappli, ltype, lmsg;
656 lappli = strlen(message.tableau[0]);
657 if ((TheAppli = (char *)malloc((unsigned)sizeof(char)*(lappli + 1)))
661 strcpy(TheAppli,message.tableau[0]);
663 ltype = strlen(message.tableau[3]);
664 if ((TheType = (char *)malloc((unsigned)sizeof(char)*(ltype + 1)))
668 strcpy(TheType,message.tableau[3]);
670 lmsg = strlen(message.tableau[4]);
671 if ((TheMsg = (char *)malloc((unsigned)sizeof(char)*(lmsg + 1)))
675 strcpy(TheMsg,message.tableau[4]);
678 static int find(s,n,t)
685 if (!strcmp(s,t[i])) return(i);
696 igeci = find("-pipes",argc,argv);
697 if (igeci == -1) exit(1);
699 p1 = atoi(argv[igeci+1]); p2 = atoi(argv[igeci+2]);
701 /* Intialization of communications */
702 init_messages(tb_messages,p1,p2);
704 /* Loop waiting for messages */
707 if (TheType != NULL) {
708 printf("Message received from %s\n",TheAppli);
709 printf(" type: %s\n",TheType);
710 printf(" message: %s\n",TheMsg);
711 TheAppli = NULL; TheType = NULL; TheMsg = NULL;
715 /***************************************************************************/