home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / bsd_srcs / share / doc / ps1 / 08.ipc / 4.t < prev    next >
Encoding:
Text File  |  1991-04-17  |  17.9 KB  |  512 lines

  1. .\" Copyright (c) 1986 The Regents of the University of California.
  2. .\" All rights reserved.
  3. .\"
  4. .\" Redistribution and use in source and binary forms, with or without
  5. .\" modification, are permitted provided that the following conditions
  6. .\" are met:
  7. .\" 1. Redistributions of source code must retain the above copyright
  8. .\"    notice, this list of conditions and the following disclaimer.
  9. .\" 2. Redistributions in binary form must reproduce the above copyright
  10. .\"    notice, this list of conditions and the following disclaimer in the
  11. .\"    documentation and/or other materials provided with the distribution.
  12. .\" 3. All advertising materials mentioning features or use of this software
  13. .\"    must display the following acknowledgement:
  14. .\"    This product includes software developed by the University of
  15. .\"    California, Berkeley and its contributors.
  16. .\" 4. Neither the name of the University nor the names of its contributors
  17. .\"    may be used to endorse or promote products derived from this software
  18. .\"    without specific prior written permission.
  19. .\"
  20. .\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  21. .\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  22. .\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  23. .\" ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  24. .\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  25. .\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  26. .\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  27. .\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  28. .\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  29. .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  30. .\" SUCH DAMAGE.
  31. .\"
  32. .\"    @(#)4.t    5.1 (Berkeley) 4/17/91
  33. .\"
  34. .\".ds RH "Client/Server Model
  35. .bp
  36. .nr H1 4
  37. .nr H2 0
  38. .sp 8i
  39. .bp
  40. .LG
  41. .B
  42. .ce
  43. 4. CLIENT/SERVER MODEL
  44. .sp 2
  45. .R
  46. .NL
  47. .PP
  48. The most commonly used paradigm in constructing distributed applications
  49. is the client/server model.  In this scheme client applications request
  50. services from a server process.  This implies an asymmetry in establishing
  51. communication between the client and server which has been examined
  52. in section 2.  In this section we will look more closely at the interactions
  53. between client and server, and consider some of the problems in developing
  54. client and server applications.
  55. .PP
  56. The client and server require a well known set of conventions before
  57. service may be rendered (and accepted).  This set of conventions
  58. comprises a protocol which must be implemented at both ends of a
  59. connection.  Depending on the situation, the protocol may be symmetric
  60. or asymmetric.  In a symmetric protocol, either side may play the 
  61. master or slave roles.  In an asymmetric protocol, one side is
  62. immutably recognized as the master, with the other as the slave.  
  63. An example of a symmetric protocol is the TELNET protocol used in
  64. the Internet for remote terminal emulation.  An example
  65. of an asymmetric protocol is the Internet file transfer protocol,
  66. FTP.  No matter whether the specific protocol used in obtaining
  67. a service is symmetric or asymmetric, when accessing a service there
  68. is a \*(lqclient process\*(rq and a \*(lqserver process\*(rq.  We
  69. will first consider the properties of server processes, then
  70. client processes.
  71. .PP
  72. A server process normally listens at a well known address for
  73. service requests.  That is, the server process remains dormant
  74. until a connection is requested by a client's connection
  75. to the server's address.  At such a time
  76. the server process ``wakes up'' and services the client,
  77. performing whatever appropriate actions the client requests of it.
  78. .PP
  79. Alternative schemes which use a service server
  80. may be used to eliminate a flock of server processes clogging the
  81. system while remaining dormant most of the time.  For Internet
  82. servers in 4.3BSD,
  83. this scheme has been implemented via \fIinetd\fP, the so called
  84. ``internet super-server.''  \fIInetd\fP listens at a variety
  85. of ports, determined at start-up by reading a configuration file.
  86. When a connection is requested to a port on which \fIinetd\fP is
  87. listening, \fIinetd\fP executes the appropriate server program to handle the
  88. client.  With this method, clients are unaware that an
  89. intermediary such as \fIinetd\fP has played any part in the
  90. connection.  \fIInetd\fP will be described in more detail in
  91. section 5.
  92. .PP
  93. A similar alternative scheme is used by most Xerox services.  In general,
  94. the Courier dispatch process (if used) accepts connections from
  95. processes requesting services of some sort or another.  The client
  96. processes request a particular <program number, version number, procedure
  97. number> triple.  If the dispatcher knows of such a program, it is
  98. started to handle the request; if not, an error is reported to the
  99. client.  In this way, only one port is required to service a large
  100. variety of different requests.  Again, the Courier facilities are
  101. not available without the use and installation of the Courier
  102. compiler.  The information presented in this section applies only
  103. to NS clients and services that do not use Courier.
  104. .NH 2
  105. Servers
  106. .PP
  107. In 4.3BSD most servers are accessed at well known Internet addresses
  108. or UNIX domain names.  For
  109. example, the remote login server's main loop is of the form shown
  110. in Figure 2.
  111. .KF
  112. .if t .ta .5i 1.0i 1.5i 2.0i 2.5i 3.0i 3.5i
  113. .if n .ta .7i 1.4i 2.1i 2.8i 3.5i 4.2i 4.9i
  114. .sp 0.5i
  115. .DS
  116. main(argc, argv)
  117.     int argc;
  118.     char *argv[];
  119. {
  120.     int f;
  121.     struct sockaddr_in from;
  122.     struct servent *sp;
  123.  
  124.     sp = getservbyname("login", "tcp");
  125.     if (sp == NULL) {
  126.         fprintf(stderr, "rlogind: tcp/login: unknown service\en");
  127.         exit(1);
  128.     }
  129.     ...
  130. #ifndef DEBUG
  131.     /* Disassociate server from controlling terminal */
  132.     ...
  133. #endif
  134.  
  135.     sin.sin_port = sp->s_port;    /* Restricted port -- see section 5 */
  136.     ...
  137.     f = socket(AF_INET, SOCK_STREAM, 0);
  138.     ...
  139.     if (bind(f, (struct sockaddr *) &sin, sizeof (sin)) < 0) {
  140.         ...
  141.     }
  142.     ...
  143.     listen(f, 5);
  144.     for (;;) {
  145.         int g, len = sizeof (from);
  146.  
  147.         g = accept(f, (struct sockaddr *) &from, &len);
  148.         if (g < 0) {
  149.             if (errno != EINTR)
  150.                 syslog(LOG_ERR, "rlogind: accept: %m");
  151.             continue;
  152.         }
  153.         if (fork() == 0) {
  154.             close(f);
  155.             doit(g, &from);
  156.         }
  157.         close(g);
  158.     }
  159. }
  160. .DE
  161. .ce
  162. Figure 2.  Remote login server.
  163. .sp 0.5i
  164. .KE
  165. .PP
  166. The first step taken by the server is look up its service
  167. definition:
  168. .sp 1
  169. .nf
  170. .in +5
  171. .if t .ta .5i 1.0i 1.5i 2.0i
  172. .if n .ta .7i 1.4i 2.1i 2.8i
  173. sp = getservbyname("login", "tcp");
  174. if (sp == NULL) {
  175.     fprintf(stderr, "rlogind: tcp/login: unknown service\en");
  176.     exit(1);
  177. }
  178. .sp 1
  179. .in -5
  180. .fi
  181. The result of the \fIgetservbyname\fP call
  182. is used in later portions of the code to
  183. define the Internet port at which it listens for service
  184. requests (indicated by a connection).
  185. .KS
  186. .PP
  187. Step two is to disassociate the server from the controlling
  188. terminal of its invoker:
  189. .DS
  190.     for (i = 0; i < 3; ++i)
  191.         close(i);
  192.  
  193.     open("/", O_RDONLY);
  194.     dup2(0, 1);
  195.     dup2(0, 2);
  196.  
  197.     i = open("/dev/tty", O_RDWR);
  198.     if (i >= 0) {
  199.         ioctl(i, TIOCNOTTY, 0);
  200.         close(i);
  201.     }
  202. .DE
  203. .KE
  204. This step is important as the server will
  205. likely not want to receive signals delivered to the process
  206. group of the controlling terminal.  Note, however, that
  207. once a server has disassociated itself it can no longer
  208. send reports of errors to a terminal, and must log errors
  209. via \fIsyslog\fP.
  210. .PP
  211. Once a server has established a pristine environment, it
  212. creates a socket and begins accepting service requests.
  213. The \fIbind\fP call is required to insure the server listens
  214. at its expected location.  It should be noted that the
  215. remote login server listens at a restricted port number, and must
  216. therefore be run
  217. with a user-id of root.
  218. This concept of a ``restricted port number'' is 4BSD
  219. specific, and is covered in section 5.
  220. .PP
  221. The main body of the loop is fairly simple:
  222. .DS
  223. .if t .ta .5i 1.0i 1.5i 2.0i
  224. .if n .ta .7i 1.4i 2.1i 2.8i
  225. for (;;) {
  226.     int g, len = sizeof (from);
  227.  
  228.     g = accept(f, (struct sockaddr *)&from, &len);
  229.     if (g < 0) {
  230.         if (errno != EINTR)
  231.             syslog(LOG_ERR, "rlogind: accept: %m");
  232.         continue;
  233.     }
  234.     if (fork() == 0) {    /* Child */
  235.         close(f);
  236.         doit(g, &from);
  237.     }
  238.     close(g);        /* Parent */
  239. }
  240. .DE
  241. An \fIaccept\fP call blocks the server until
  242. a client requests service.  This call could return a
  243. failure status if the call is interrupted by a signal
  244. such as SIGCHLD (to be discussed in section 5).  Therefore,
  245. the return value from \fIaccept\fP is checked to insure
  246. a connection has actually been established, and
  247. an error report is logged via \fIsyslog\fP if an error
  248. has occurred.
  249. .PP
  250. With a connection
  251. in hand, the server then forks a child process and invokes
  252. the main body of the remote login protocol processing.  Note
  253. how the socket used by the parent for queuing connection
  254. requests is closed in the child, while the socket created as
  255. a result of the \fIaccept\fP is closed in the parent.  The
  256. address of the client is also handed the \fIdoit\fP routine
  257. because it requires it in authenticating clients.
  258. .NH 2
  259. Clients
  260. .PP
  261. The client side of the remote login service was shown
  262. earlier in Figure 1.
  263. One can see the separate, asymmetric roles of the client
  264. and server clearly in the code.  The server is a passive entity,
  265. listening for client connections, while the client process is
  266. an active entity, initiating a connection when invoked.  
  267. .PP
  268. Let us consider more closely the steps taken
  269. by the client remote login process.  As in the server process,
  270. the first step is to locate the service definition for a remote
  271. login:
  272. .DS
  273. sp = getservbyname("login", "tcp");
  274. if (sp == NULL) {
  275.     fprintf(stderr, "rlogin: tcp/login: unknown service\en");
  276.     exit(1);
  277. }
  278. .DE
  279. Next the destination host is looked up with a
  280. \fIgethostbyname\fP call:
  281. .DS
  282. hp = gethostbyname(argv[1]);
  283. if (hp == NULL) {
  284.     fprintf(stderr, "rlogin: %s: unknown host\en", argv[1]);
  285.     exit(2);
  286. }
  287. .DE
  288. With this accomplished, all that is required is to establish a
  289. connection to the server at the requested host and start up the
  290. remote login protocol.  The address buffer is cleared, then filled
  291. in with the Internet address of the foreign host and the port
  292. number at which the login process resides on the foreign host:
  293. .DS
  294. bzero((char *)&server, sizeof (server));
  295. bcopy(hp->h_addr, (char *) &server.sin_addr, hp->h_length);
  296. server.sin_family = hp->h_addrtype;
  297. server.sin_port = sp->s_port;
  298. .DE
  299. A socket is created, and a connection initiated.  Note
  300. that \fIconnect\fP implicitly performs a \fIbind\fP
  301. call, since \fIs\fP is unbound.
  302. .DS
  303. s = socket(hp->h_addrtype, SOCK_STREAM, 0);
  304. if (s < 0) {
  305.     perror("rlogin: socket");
  306.     exit(3);
  307. }
  308.  ...
  309. if (connect(s, (struct sockaddr *) &server, sizeof (server)) < 0) {
  310.     perror("rlogin: connect");
  311.     exit(4);
  312. }
  313. .DE
  314. The details of the remote login protocol will not be considered here.
  315. .NH 2
  316. Connectionless servers
  317. .PP
  318. While connection-based services are the norm, some services
  319. are based on the use of datagram sockets.  One, in particular,
  320. is the \*(lqrwho\*(rq service which provides users with status
  321. information for hosts connected to a local area
  322. network.  This service, while predicated on the ability to
  323. \fIbroadcast\fP information to all hosts connected to a particular
  324. network, is of interest as an example usage of datagram sockets.
  325. .PP
  326. A user on any machine running the rwho server may find out
  327. the current status of a machine with the \fIruptime\fP(1) program.
  328. The output generated is illustrated in Figure 3.
  329. .KF
  330. .DS B
  331. .TS
  332. l r l l l l l.
  333. arpa    up    9:45,    5 users, load    1.15,    1.39,    1.31
  334. cad    up    2+12:04,    8 users, load    4.67,    5.13,    4.59
  335. calder    up    10:10,    0 users, load    0.27,    0.15,    0.14
  336. dali    up    2+06:28,    9 users, load    1.04,    1.20,    1.65
  337. degas    up    25+09:48,    0 users, load    1.49,    1.43,    1.41
  338. ear    up    5+00:05,    0 users, load    1.51,    1.54,    1.56
  339. ernie    down    0:24
  340. esvax    down    17:04
  341. ingres    down    0:26
  342. kim    up    3+09:16,    8 users, load    2.03,    2.46,    3.11
  343. matisse    up    3+06:18,    0 users, load    0.03,    0.03,    0.05
  344. medea    up    3+09:39,    2 users, load    0.35,    0.37,    0.50
  345. merlin    down    19+15:37
  346. miro    up    1+07:20,    7 users, load    4.59,    3.28,    2.12
  347. monet    up    1+00:43,    2 users, load    0.22,    0.09,    0.07
  348. oz    down    16:09
  349. statvax    up    2+15:57,    3 users, load    1.52,    1.81,    1.86
  350. ucbvax    up    9:34,    2 users, load    6.08,    5.16,    3.28
  351. .TE
  352. .DE
  353. .ce
  354. Figure 3. ruptime output.
  355. .sp
  356. .KE
  357. .PP
  358. Status information for each host is periodically broadcast
  359. by rwho server processes on each machine.  The same server
  360. process also receives the status information and uses it
  361. to update a database.  This database is then interpreted
  362. to generate the status information for each host.  Servers
  363. operate autonomously, coupled only by the local network and
  364. its broadcast capabilities.
  365. .PP
  366. Note that the use of broadcast for such a task is fairly inefficient,
  367. as all hosts must process each message, whether or not using an rwho server.
  368. Unless such a service is sufficiently universal and is frequently used,
  369. the expense of periodic broadcasts outweighs the simplicity.
  370. .PP
  371. The rwho server, in a simplified form, is pictured in Figure
  372. 4.  There are two separate tasks performed by the server.  The
  373. first task is to act as a receiver of status information broadcast
  374. by other hosts on the network.  This job is carried out in the
  375. main loop of the program.  Packets received at the rwho port
  376. are interrogated to insure they've been sent by another rwho
  377. server process, then are time stamped with their arrival time
  378. and used to update a file indicating the status of the host.
  379. When a host has not been heard from for an extended period of
  380. time, the database interpretation routines assume the host is
  381. down and indicate such on the status reports.  This algorithm
  382. is prone to error as a server may be down while a host is actually
  383. up, but serves our current needs.
  384. .KF
  385. .DS
  386. .if t .ta .5i 1.0i 1.5i 2.0i
  387. .if n .ta .7i 1.4i 2.1i 2.8i
  388. main()
  389. {
  390.     ...
  391.     sp = getservbyname("who", "udp");
  392.     net = getnetbyname("localnet");
  393.     sin.sin_addr = inet_makeaddr(INADDR_ANY, net);
  394.     sin.sin_port = sp->s_port;
  395.     ...
  396.     s = socket(AF_INET, SOCK_DGRAM, 0);
  397.     ...
  398.     on = 1;
  399.     if (setsockopt(s, SOL_SOCKET, SO_BROADCAST, &on, sizeof(on)) < 0) {
  400.         syslog(LOG_ERR, "setsockopt SO_BROADCAST: %m");
  401.         exit(1);
  402.     }
  403.     bind(s, (struct sockaddr *) &sin, sizeof (sin));
  404.     ...
  405.     signal(SIGALRM, onalrm);
  406.     onalrm();
  407.     for (;;) {
  408.         struct whod wd;
  409.         int cc, whod, len = sizeof (from);
  410.  
  411.         cc = recvfrom(s, (char *)&wd, sizeof (struct whod), 0,
  412.             (struct sockaddr *)&from, &len);
  413.         if (cc <= 0) {
  414.             if (cc < 0 && errno != EINTR)
  415.                 syslog(LOG_ERR, "rwhod: recv: %m");
  416.             continue;
  417.         }
  418.         if (from.sin_port != sp->s_port) {
  419.             syslog(LOG_ERR, "rwhod: %d: bad from port",
  420.                 ntohs(from.sin_port));
  421.             continue;
  422.         }
  423.         ...
  424.         if (!verify(wd.wd_hostname)) {
  425.             syslog(LOG_ERR, "rwhod: malformed host name from %x",
  426.                 ntohl(from.sin_addr.s_addr));
  427.             continue;
  428.         }
  429.         (void) sprintf(path, "%s/whod.%s", RWHODIR, wd.wd_hostname);
  430.         whod = open(path, O_WRONLY | O_CREAT | O_TRUNC, 0666);
  431.         ...
  432.         (void) time(&wd.wd_recvtime);
  433.         (void) write(whod, (char *)&wd, cc);
  434.         (void) close(whod);
  435.     }
  436. }
  437. .DE
  438. .ce
  439. Figure 4.  rwho server.
  440. .sp
  441. .KE
  442. .PP
  443. The second task performed by the server is to supply information
  444. regarding the status of its host.  This involves periodically
  445. acquiring system status information, packaging it up in a message
  446. and broadcasting it on the local network for other rwho servers
  447. to hear.  The supply function is triggered by a timer and 
  448. runs off a signal.  Locating the system status
  449. information is somewhat involved, but uninteresting.  Deciding
  450. where to transmit the resultant packet
  451. is somewhat problematical, however.
  452. .PP
  453. Status information must be broadcast on the local network.
  454. For networks which do not support the notion of broadcast another
  455. scheme must be used to simulate or
  456. replace broadcasting.  One possibility is to enumerate the
  457. known neighbors (based on the status messages received
  458. from other rwho servers).  This, unfortunately,
  459. requires some bootstrapping information,
  460. for a server will have no idea what machines are its
  461. neighbors until it receives status messages from them.
  462. Therefore, if all machines on a net are freshly booted,
  463. no machine will have any
  464. known neighbors and thus never receive, or send, any status information.
  465. This is the identical problem faced by the routing table management
  466. process in propagating routing status information.  The standard
  467. solution, unsatisfactory as it may be, is to inform one or more servers
  468. of known neighbors and request that they always communicate with
  469. these neighbors.  If each server has at least one neighbor supplied
  470. to it, status information may then propagate through
  471. a neighbor to hosts which
  472. are not (possibly) directly neighbors.  If the server is able to
  473. support networks which provide a broadcast capability, as well as
  474. those which do not, then networks with an
  475. arbitrary topology may share status information*.
  476. .FS
  477. * One must, however, be concerned about \*(lqloops\*(rq.
  478. That is, if a host is connected to multiple networks, it
  479. will receive status information from itself.  This can lead
  480. to an endless, wasteful, exchange of information.
  481. .FE
  482. .PP
  483. It is important that software operating in a distributed
  484. environment not have any site-dependent information compiled into it.
  485. This would require a separate copy of the server at each host and
  486. make maintenance a severe headache.  4.3BSD attempts to isolate
  487. host-specific information from applications by providing system
  488. calls which return the necessary information*.
  489. .FS
  490. * An example of such a system call is the \fIgethostname\fP(2)
  491. call which returns the host's \*(lqofficial\*(rq name.
  492. .FE
  493. A mechanism exists, in the form of an \fIioctl\fP call,
  494. for finding the collection
  495. of networks to which a host is directly connected.
  496. Further, a local network broadcasting mechanism
  497. has been implemented at the socket level.
  498. Combining these two features allows a process
  499. to broadcast on any directly connected local
  500. network which supports the notion of broadcasting
  501. in a site independent manner.  This allows 4.3BSD
  502. to solve the problem of deciding how to propagate
  503. status information in the case of \fIrwho\fP, or
  504. more generally in broadcasting:
  505. Such status information is broadcast to connected
  506. networks at the socket level, where the connected networks
  507. have been obtained via the appropriate \fIioctl\fP
  508. calls.
  509. The specifics of
  510. such broadcastings are complex, however, and will
  511. be covered in section 5.
  512.