《BSD进程间通信编程入门,主要讲socket编程》由会员分享,可在线阅读,更多相关《BSD进程间通信编程入门,主要讲socket编程(23页珍藏版)》请在金锄头文库上搜索。
1、Introductory 4.4BSD IPCPSD:20-1An Introductory 4.4BSDInterprocess Communication TutorialStuart SechrestComputer Science Research GroupComputer Science DivisionDepartment of Electrical Engineering and Computer ScienceUniversity of California, BerkeleyABSTRACTBerkeley UNIX 4.4BSD offers several choice
2、s for interprocess communication. To aid the pro-grammer in developing programs which are comprised of cooperating processes, the different choices arediscussed and a series of example programs are presented. These programs demonstrate in a simple waythe use of pipes, socketpairs, sockets and the us
3、e of datagram and stream communication. The intent of thisdocument is to present a few simple example programs, not to describe the networking system in full.1. GoalsFacilities for interprocess communication (IPC) and networking were a major addition to UNIX inthe Berkeley UNIX 4.2BSD release. These
4、 facilities required major additions and some changes to the sys-tem interface. The basic idea of this interface is to make IPC similar to file I/O. In UNIX a process has aset of I/O descriptors, from which one reads and to which one writes. Descriptors may refer to normal files,to devices (includin
5、g terminals), or to communication channels. The use of a descriptor has three phases:its creation, its use for reading and writing, and its destruction. By using descriptors to write files, ratherthan simply naming the target file in the write call, one gains a surprising amount of flexibility. Ofte
6、n, theprogram that creates a descriptor will be different from the program that uses the descriptor. For examplethe shell can create a descriptor for the output of the ls command that will cause the listing to appear in afile rather than on a terminal. Pipes are another form of descriptor that have
7、been used in UNIX for sometime. Pipes allow one-way data transmission from one process to another; the two processes and the pipemust be set up by a common ancestor.The use of descriptors is not the only communication interface provided by UNIX. The signal mech-anism sends a tiny amount of informati
8、on from one process to another. The signaled process receives onlythe signal type, not the identity of the sender, and the number of possible signals is small. The signalsemantics limit the flexibility of the signaling mechanism as a means of interprocess communication.The identification of IPC with
9、 I/O is quite longstanding in UNIX and has proved quite successful. Atfirst, however, IPC was limited to processes communicating within a single machine. With Berkeley UNIX4.2BSD this expanded to include IPC between machines. This expansion has necessitated some change inthe way that descriptors are
10、 created. Additionally, new possibilities for the meaning of read and write havebeen admitted. Originally the meanings, or semantics, of these terms were fairly simple. When you wrotesomething it was delivered. When you read something, you were blocked until the data arrived. Other pos-sibilities ex
11、ist, however. One can write without full assurance of delivery if one can check later to catchoccasional failures. Messages can be kept as discrete units or merged into a stream. One can ask to read,UNIX is a trademark of AT&T Bell Laboratories.PSD:20-2 Introductory 4.4BSD IPCbut insist on not waiti
12、ng if nothing is immediately available. These new possibilities are allowed in theBerkeley UNIX IPC interface.Thus Berkeley UNIX 4.4BSD offers several choices for IPC. This paper presents simple examplesthat illustrate some of the choices. The reader is presumed to be familiar with the C programming
13、 languageKernighan & Ritchie 1978, but not necessarily with the system calls of the UNIX system or with pro-cesses and interprocess communication. The paper reviews the notion of a process and the types of com-munication that are supported by Berkeley UNIX 4.4BSD. A series of examples are presented
14、that createprocesses that communicate with one another. The programs show different ways of establishing channelsof communication. Finally, the calls that actually transfer data are reviewed. To clearly present how com-munication can take place, the example programs have been cleared of anything tha
15、t might be construed asuseful work. They can, therefore, serve as models for the programmer trying to construct programs whichare comprised of cooperating processes.2. ProcessesA program is both a sequence of statements and a rough way of referring to the computation thatoccurs when the compiled sta
16、tements are run. A process can be thought of as a single line of control in aprogram. Most programs execute some statements, go through a few loops, branch in various directionsand then end. These are single process programs. Programs can also have a point where control splits intotwo independent li
17、nes, an action called forking. In UNIX these lines can never join again. A call to thesystem routine fork(), causes a process to split in this way. The result of this call is that two independentprocesses will be running, executing exactly the same code. Memory values will be the same for all values
18、set before the fork, but, subsequently, each version will be able to change only the value of its own copy ofeach variable. Initially, the only difference between the two will be the value returned by fork(). The par-ent will receive a process id for the child, the child will receive a zero. Calls t
19、o fork(), therefore, typicallyprecede, or are included in, an if-statement.A process views the rest of the system through a private table of descriptors. The descriptors can rep-resent open files or sockets (sockets are communication objects that will be discussed below). Descriptorsare referred to
20、by their index numbers in the table. The first three descriptors are often known by specialnames, stdin, stdout and stderr. These are the standard input, output and error. When a process forks, itsdescriptor table is copied to the child. Thus, if the parents standard input is being taken from a term
21、inal(devices are also treated as files in UNIX), the childs input will be taken from the same terminal. Whoeverreads first will get the input. If, before forking, the parent changes its standard input so that it is readingfrom a new file, the child will take its input from the new file. It is also p
22、ossible to take input from a socket,rather than from a file.3. PipesMost users of UNIX know that they can pipe the output of a program prog1 to the input ofanother, prog2, by typing the command prog1 | pro g2. This is called piping the output of one pro-gram to another because the mechanism used to
23、transfer the output is called a pipe. When the user types acommand, the command is read by the shell, which decides how to execute it. If the command is simple,for example, prog1, the shell forks a process, which executes the program, prog1, and then dies. Theshell waits for this termination and the
24、n prompts for the next command. If the command is a compoundcommand, prog1 | pro g2, the shell creates two processes connected by a pipe. One process runs the pro-gram, prog1, the other runs prog2. The pipe is an I/O mechanism with two ends, or sockets. Data that iswritten into one socket can be rea
25、d from the other.Since a program specifies its input and output only by the descriptor table indices, which appear asvariables or constants, the input source and output destination can be changed without changing the text ofthe program. It is in this way that the shell is able to set up pipes. Befor
26、e executing prog1, the process canclose whatever is at stdout and replace it with one end of a pipe. Similarly, the process that will executeprog2 can substitute the opposite end of the pipe for stdin.Introductory 4.4BSD IPCPSD:20-3#include #define DATA Bright star, would I were steadfast as thou ar
27、t . . ./* This program creates a pipe, then forks.The child communicates to the* parent over the pipe. Notice that a pipe is a one-way communications* device. I can write to the output socket (sockets1, the second socket* of the array returned by pipe() and read from the input socket* (sockets0), bu
28、t not vice versa.*/main()int sockets2, child;/* Create a pipe */if (pipe(sockets) 0) perror(opening stream socket pair);exit(10);if (child = fork() = -1)perror(fork);else if (child) char buf1024;/* This is still the parent.It reads the childs message. */close(sockets1);if (read(sockets0, buf, 1024)
29、%sn, buf);close(sockets0); else /* This is the child.It writes a message to its parent. */close(sockets0);if (write(sockets1, DATA, sizeof(DATA) 0)perror(writing message);close(sockets1);Figure 1 Use of a pipeLet us now examine a program that creates a pipe for communication between its child and it
30、self(Figure 1). A pipe is created by a parent process, which then forks. When a process forks, the parentsdescriptor table is copied into the childs.In Figure 1, the parent process makes a call to the system routine pipe(). This routine creates a pipeand places descriptors for the sockets for the tw
31、o ends of the pipe in the processs descriptor table. Pipe() ispassed an array into which it places the index numbers of the sockets it created. The two ends are notequivalent. The socket whose index is returned in the low word of the array is opened for reading only,while the socket in the high end
32、is opened only for writing. This corresponds to the fact that the standardinput is the first descriptor of a processs descriptor table and the standard output is the second. AfterPSD:20-4 Introductory 4.4BSD IPCcreating the pipe, the parent creates the child with which it will share the pipe by call
33、ing fork(). Figure 2illustrates the effect of a fork. The parent processs descriptor table points to both ends of the pipe. Afterthe fork, both parents and childs descriptor tables point to the pipe. The child can then use the pipe tosend a message to the parent.Just what is a pipe? It is a one-way
34、communication mechanism, with one end opened for reading andthe other end for writing. Therefore, parent and child need to agree on which way to turn the pipe, fromparent to child or the other way around. Using the same pipe for communication both from parent to childand from child to parent would b
35、e possible (since both processes have references to both ends), but verycomplicated. If the parent and child are to have a two-way conversation, the parent creates two pipes, onefor use in each direction. (In accordance with their plans, both parent and child in the example above closethe socket tha
36、t they will not use. It is not required that unused descriptors be closed, but it is good prac-tice.) A pipe is also a stream communication mechanism; that is, all messages sent through the pipe areChildParentParentPIPEPIPEFigure 2 Sharing a pipe between parent and childIntroductory 4.4BSD IPCPSD:20
37、-5placed in order and reliably delivered. When the reader asks for a certain number of bytes from this stream,he is given as many bytes as are available, up to the amount of the request. Note that these bytes may havecome from the same call to write() or from several calls to write() which were conc
38、atenated.4. SocketpairsBerkeley UNIX 4.4BSD provides a slight generalization of pipes. A pipe is a pair of connected sock-ets for one-way stream communication. One may obtain a pair of connected sockets for two-way streamcommunication by calling the routine socketpair(). The program in Figure 3 call
39、s socketpair() to createsuch a connection. The program uses the link for communication in both directions. Since socketpairs arean extension of pipes, their use resembles that of pipes. Figure 4 illustrates the result of a fork following acall to socketpair().Socketpair() takes as arguments a specif
40、ication of a domain, a style of communication, and a proto-col. These are the parameters shown in the example. Domains and protocols will be discussed in the nextsection. Briefly, a domain is a space of names that may be bound to sockets and implies certain other con-ventions. Currently, socketpairs
41、 have only been implemented for one domain, called the UNIX domain.The UNIX domain uses UNIX path names for naming sockets. It only allows communication betweensockets on the same machine.Note that the header files and . are required in this program. The con-stants AF_UNIX and SOCK_STREAM are define
42、d in , which in turn requires the file for some of its definitions.5. Domains and ProtocolsPipes and socketpairs are a simple solution for communicating between a parent and child or betweenchild processes. What if we wanted to have processes that have no common ancestor with whom to set upcommunica
43、tion? Neither standard UNIX pipes nor socketpairs are the answer here, since both mechanismsrequire a common ancestor to set up the communication. We would like to hav e two processes separatelycreate sockets and then have messages sent between them. This is often the case when providing or using as
44、ervice in the system. This is also the case when the communicating processes are on separate machines.In Berkeley UNIX 4.4BSD one can create individual sockets, give them names and send messages betweenthem.Sockets created by different programs use names to refer to one another; names generally must
45、 betranslated into addresses for use. The space from which an address is drawn is referred to as a domain.There are several domains for sockets. Two that will be used in the examples here are the UNIX domain(or AF_UNIX, for Address Format UNIX) and the Internet domain (or AF_INET). UNIX domain IPC i
46、san experimental facility in 4.2BSD and 4.3BSD. In the UNIX domain, a socket is given a path name withinthe file system name space. A file system node is created for the socket and other processes may then referto the socket by giving the proper pathname. UNIX domain names, therefore, allow communic
47、ationbetween any two processes that work in the same file system. The Internet domain is the UNIX implemen-tation of the DARPA Internet standard protocols IP/TCP/UDP. Addresses in the Internet domain consist ofa machine network address and an identifying number, called a port. Internet domain names
48、allow commu-nication between machines.Communication follows some particular style. Currently, communication is either through astream or by datagram. Stream communication implies several things. Communication takes place acrossa connection between two sockets. The communication is reliable, error-fr
49、ee, and, as in pipes, no messageboundaries are kept. Reading from a stream may result in reading the data sent from one or several calls towrite() or only part of the data from a single call, if there is not enough room for the entire message, or ifnot all the data from a large message has been tran
50、sferred. The protocol implementing such a style willretransmit messages received with errors. It will also return error messages if one tries to send a messageafter the connection has been broken. Datagram communication does not use connections. Each messageis addressed individually. If the address
51、is correct, it will generally be received, although this is not guaran-teed. Often datagrams are used for requests that require a response from the recipient. If no responsePSD:20-6 Introductory 4.4BSD IPC#include #include #include #define DATA1 In Xanadu, did Kublai Khan . . .#define DATA2 A statel
52、y pleasure dome decree . . ./* This program creates a pair of connected sockets then forks and* communicates over them.This is very similar to communication with pipes,* however, socketpairs are two-way communications objects. Therefore I can* send messages in both directions.*/main()int sockets2, c
53、hild;char buf1024;if (socketpair(AF_UNIX, SOCK_STREAM, 0, sockets) 0) perror(opening stream socket pair);exit(1);if (child = fork() = -1)perror(fork);else if (child) /* This is the parent. */close(sockets0);if (read(sockets1, buf, 1024, 0) %sn, buf);if (write(sockets1, DATA2, sizeof(DATA2) 0)perror(
54、writing stream message);close(sockets1); else /* This is the child. */close(sockets1);if (write(sockets0, DATA1, sizeof(DATA1) 0)perror(writing stream message);if (read(sockets0, buf, 1024, 0) %sn, buf);close(sockets0);Figure 3 Use of a socketpairIntroductory 4.4BSD IPCPSD:20-7ChildParentParentFigur
55、e 4 Sharing a socketpair between parent and childarrives in a reasonable amount of time, the request is repeated. The individual datagrams will be kept sepa-rate when they are read, that is, message boundaries are preserved.The difference in performance between the two styles of communication is gen
56、erally less importantthan the difference in semantics. The performance gain that one might find in using datagrams must beweighed against the increased complexity of the program, which must now concern itself with lost or out oforder messages. If lost messages may simply be ignored, the quantity of
57、traffic may be a consideration.The expense of setting up a connection is best justified by frequent use of the connection. Since the perfor-mance of a protocol changes as it is tuned for different situations, it is best to seek the most up-to-dateinformation when making choices for a program in whic
58、h performance is crucial.A protocol is a set of rules, data formats and conventions that regulate the transfer of data betweenparticipants in the communication. In general, there is one protocol for each socket type (stream, datagram,etc.) within each domain. The code that implements a protocol keep
59、s track of the names that are bound tosockets, sets up connections andtransfers data between sockets, perhaps sending the data across a net-work. This code also keeps track of the names that are bound to sockets. It is possible for severalPSD:20-8 Introductory 4.4BSD IPCprotocols, differing only in
60、low lev el details, to implement the same style of communication within a partic-ular domain. Although it is possible to select which protocol should be used, for nearly all uses it is suffi-cient to request the default protocol. This has been done in all of the example programs.One specifies the do
61、main, style and protocol of a socket when it is created. For example, in Figure 5athe call to socket() causes the creation of a datagram socket with the default protocol in the UNIX domain.6. Datagrams in the UNIX DomainLet us now look at two programs that create sockets separately. The programs in
62、Figures 5a and 5buse datagram communication rather than a stream. The structure used to name UNIX domain sockets isdefined in the file . The definition has also been included in the example for clarity.Each program creates a socket with a call to socket(). These sockets are in the UNIX domain. Oncea
63、 name has been decided upon it is attached to a socket by the system call bind(). The program in Figure 5auses the name socket, which it binds to its socket. This name will appear in the working directory of theprogram. The routines in Figure 5b use its socket only for sending messages. It does not
64、create a name forthe socket because no other process has to refer to it.Names in the UNIX domain are path names. Like file path names they may be either absolute (e.g./dev/imaginary) or relative (e.g. socket). Because these names are used to allow processes to ren-dezvous, relative path names can po
65、se difficulties and should be used with care. When a name is boundinto the name space, a file (inode) is allocated in the file system. If the inode is not deallocated, the namewill continue to exist even after the bound socket is closed. This can cause subsequent runs of a program tofind that a name
66、 is unavailable, and can cause directories to fill up with these objects. The names areremoved by calling unlink() or using the rm(1) command. Names in the UNIX domain are only used forrendezvous. They are not used for message delivery once a connection is established. Therefore, in con-trast with t
67、he Internet domain, unbound sockets need not be (and are not) automatically given addresseswhen they are connected.There is no established means of communicating names to interested parties. In the example, theprogram in Figure 5b gets the name of the socket to which it will send its message through
68、 its commandline arguments. Once a line of communication has been created, one can send the names of additional, per-haps new, sockets over the link. Facilities will have to be built that will make the distribution of names lessof a problem than it now is.7. Datagrams in the Internet DomainThe examp
69、les in Figure 6a and 6b are very close to the previous example except that the socket is inthe Internet domain. The structure of Internet domain addresses is defined in the file . Inter-net addresses specify a host address (a 32-bit number) and a delivery slot, or port, on that machine. Theseports a
70、re managed by the system routines that implement a particular protocol. Unlike UNIX domainnames, Internet socket names are not entered into the file system and, therefore, they do not have to beunlinked after the socket has been closed. When a message must be sent between machines it is sent to thep
71、rotocol routine on the destination machine, which interprets the address to determine to which socket themessage should be delivered. Several different protocols may be active on the same machine, but, in gen-eral, they will not communicate with one another. As a result, different protocols are allo
72、wed to use thesame port numbers. Thus, implicitly, an Internet address is a triple including a protocol as well as the portand machine address. An association is a temporary or permanent specification of a pair of communicatingsockets. An association is thus identified by the tuple . An association
73、may be transient when using datagram sockets; the associa-tion actually exists during a send operation.The protocol for a socket is chosen when the socket is created. The local machine address for asocket can be any valid network address of the machine, if it has more than one, or it can be the wild
74、cardvalue INADDR_ANY. The wildcard value is used in the program in Figure 6a. If a machine has severalnetwork addresses, it is likely that messages sent to any of the addresses should be deliverable to a socket.This will be the case if the wildcard value has been chosen. Note that even if the wildca
75、rd value is chosen,Introductory 4.4BSD IPCPSD:20-9#include #include #include /* In the included file a sockaddr_un is defined as follows* struct sockaddr_un *short sun_family;*char sun_path108;* ;*/#include #define NAME socket/* This program creates a UNIX domain datagram socket, binds a name to it,
76、* then reads from the socket.*/main()int sock, length;struct sockaddr_un name;char buf1024;/* Create socket from which to read. */sock = socket(AF_UNIX, SOCK_DGRAM, 0);if (sock %sn, NAME);/* Read from the socket */if (read(sock, buf, 1024) %sn, buf);close(sock);unlink(NAME);Figure 5a Reading UNIX do
77、main datagramsPSD:20-10 Introductory 4.4BSD IPC#include #include #include #include #define DATA The sea is calm tonight, the tide is full . . ./* Here I send a datagram to a receiver whose name I get from the command* line arguments.The form of the command line is udgramsend pathname*/main(argc, arg
78、v)int argc;char *argv;int sock;struct sockaddr_un name;/* Create socket on which to send. */sock = socket(AF_UNIX, SOCK_DGRAM, 0);if (sock 0) perror(opening datagram socket);exit(1);/* Construct name of socket to send to. */name.sun_family = AF_UNIX;strcpy(name.sun_path, argv1);/* Send message. */if
79、 (sendto(sock, DATA, sizeof(DATA), 0,&name, sizeof(struct sockaddr_un) 0) perror(sending datagram message);close(sock);Figure 5b Sending a UNIX domain datagramsIntroductory 4.4BSD IPCPSD:20-11#include #include #include #include /* In the included file a sockaddr_in is defined as follows:* struct soc
80、kaddr_in *short sin_family;*u_short sin_port;*struct in_addr sin_addr;*char sin_zero8;* ;* This program creates a datagram socket, binds a name to it, then reads* from the socket.*/main()int sock, length;struct sockaddr_in name;char buf1024;/* Create socket from which to read. */sock = socket(AF_INE
81、T, SOCK_DGRAM, 0);if (sock 0) perror(opening datagram socket);exit(1);/* Create name with wildcards. */name.sin_family = AF_INET;name.sin_addr.s_addr = INADDR_ANY;name.sin_port = 0;if (bind(sock, &name, sizeof(name) perror(binding datagram socket);exit(1);/* Find assigned port value and print it out
82、. */length = sizeof(name);if (getsockname(sock, &name, &length) perror(getting socket name);exit(1);printf(Socket has port #%dn, ntohs(name.sin_port);/* Read from the socket */if (read(sock, buf, 1024) %sn, buf);close(sock);Figure 6a Reading Internet domain datagramsPSD:20-12 Introductory 4.4BSD IPC
83、#include #include #include #include #include #define DATA The sea is calm tonight, the tide is full . . ./* Here I send a datagram to a receiver whose name I get from the command* line arguments.The form of the command line is dgramsend hostname* portnumber*/main(argc, argv)int argc;char *argv;int s
84、ock;struct sockaddr_in name;struct hostent *hp, *gethostbyname();/* Create socket on which to send. */sock = socket(AF_INET, SOCK_DGRAM, 0);if (sock h_addr, &name.sin_addr, hp-h_length);name.sin_family = AF_INET;name.sin_port = htons(atoi(argv2);/* Send message. */if (sendto(sock, DATA, sizeof(DATA)
85、, 0, &name, sizeof(name) 0)perror(sending datagram message);close(sock);Figure 6b Sending an Internet domain datagrama program sending messages to the named socket must specify a valid network address. One can be willingto receive from anywhere, but one cannot send a message anywhere. The program in
86、 Figure 6b isgiven the destination host name as a command line argument. To determine a network address to which itcan send the message, it looks up the host address by the call to gethostbyname(). The returned structureIntroductory 4.4BSD IPCPSD:20-13includes the hosts network address, which is cop
87、ied into the structure specifying the destination of themessage.The port number can be thought of as the number of a mailbox, into which the protocol places onesmessages. Certain daemons, offering certain advertised services, have reserved or well-known portnumbers. These fall in the range from 1 to
88、 1023. Higher numbers are available to general users. Onlyservers need to ask for a particular number. The system will assign an unused port number when an addressis bound to a socket. This may happen when an explicit bind call is made with a port number of 0, or whena connect or send is performed o
89、n an unbound socket. Note that port numbers are not automaticallyreported back to the user. After calling bind(), asking for port 0, one may call getsockname() to discoverwhat port was actually assigned. The routine getsockname() will not work for names in the UNIX domain.The format of the socket ad
90、dress is specified in part by standards within the Internet domain. Thespecification includes the order of the bytes in the address. Because machines differ in the internal repre-sentation they ordinarily use to represent integers, printing out the port number as returned by getsock-name() may resul
91、t in a misinterpretation. To print out the number, it is necessary to use the routine ntohs()(for network to host: short) to convert the number from the network representation to the hosts representa-tion. On some machines, such as 68000-based machines, this is a null operation. On others, such asVA
92、Xes, this results in a swapping of bytes. Another routine exists to convert a short integer from the hostformat to the network format, called htons(); similar routines exist for long integers. For further informa-tion, refer to the entry for byteorder in section 3 of the manual.8. ConnectionsTo send
93、 data between stream sockets (having communication style SOCK_STREAM), the socketsmust be connected. Figures 7a and 7b show two programs that create such a connection. The program in7a is relatively simple. To initiate a connection, this program simply creates a stream socket, then callsconnect(), s
94、pecifying the address of the socket to which it wishes its socket connected. Provided that thetarget socket exists and is prepared to handle a connection, connection will be complete, and the programcan begin to send messages. Messages will be delivered in order without message boundaries, as withpi
95、pes. The connection is destroyed when either socket is closed (or soon thereafter). If a process persists insending messages after the connection is closed, a SIGPIPE signal is sent to the process by the operatingsystem. Unless explicit action is taken to handle the signal (see the manual page for s
96、ignal or sigvec), theprocess will terminate and the shell will print the message broken pipe.Forming a connection is asymmetrical; one process, such as the program in Figure 7a, requests a con-nection with a particular socket, the other process accepts connection requests. Before a connection can be
97、accepted a socket must be created and an address bound to it. This situation is illustrated in the top half ofFigure 8. Process 2 has created a socket and bound a port number to it. Process 1 has created an unnamedsocket. The address bound to process 2s socket is then made known to process 1 and, pe
98、rhaps to severalother potential communicants as well. If there are several possible communicants, this one socket mightreceive sev eral requests for connections. As a result, a new socket is created for each connection. This newsocket is the endpoint for communication within this process for this co
99、nnection. A connection may bedestroyed by closing the corresponding socket.The program in Figure 7b is a rather trivial example of a server. It creates a socket to which it binds aname, which it then advertises. (In this case it prints out the socket number.) The program then calls lis-ten() for thi
100、s socket. Since several clients may attempt to connect more or less simultaneously, a queue ofpending connections is maintained in the system address space. Listen() marks the socket as willing toaccept connections and initializes the queue. When a connection is requested, it is listed in the queue.
101、 Ifthe queue is full, an error status may be returned to the requester. The maximum length of this queue isspecified by the second argument of listen(); the maximum length is limited by the system. Once the listencall has been completed, the program enters an infinite loop. On each pass through the
102、loop, a new connec-tion is accepted and removed from the queue, and, hence, a new socket for the connection is created. Thebottom half of Figure 8 shows the result of Process 1 connecting with the named socket of Process 2, andProcess 2 accepting the connection. After the connection is created, the
103、service, in this case printing out thePSD:20-14 Introductory 4.4BSD IPC#include #include #include #include #include #define DATA Half a league, half a league . . ./* This program creates a socket and initiates a connection with the socket* given in the command line.One message is sent over the conne
104、ction and* then the socket is closed, ending the connection. The form of the command* line is streamwrite hostname portnumber*/main(argc, argv)int argc;char *argv;int sock;struct sockaddr_in server;struct hostent *hp, *gethostbyname();char buf1024;/* Create socket */sock = socket(AF_INET, SOCK_STREA
105、M, 0);if (sock h_addr, &server.sin_addr, hp-h_length);server.sin_port = htons(atoi(argv2);if (connect(sock, &server, sizeof(server) 0) perror(connecting stream socket);exit(1);if (write(sock, DATA, sizeof(DATA) 0)perror(writing on stream socket);close(sock);Figure 7a Initiating an Internet domain st
106、ream connectionIntroductory 4.4BSD IPCPSD:20-15#include #include #include #include #include #define TRUE 1/* This program creates a socket and then begins an infinite loop. Each time* through the loop it accepts a connection and prints out messages from it.* When the connection breaks, or a terminat
107、ion message comes through, the* program accepts a new connection.*/main()int sock, length;struct sockaddr_in server;int msgsock;char buf1024;int rval;int i;/* Create socket */sock = socket(AF_INET, SOCK_STREAM, 0);if (sock 0) perror(opening stream socket);exit(1);/* Name socket using wildcards */ser
108、ver.sin_family = AF_INET;server.sin_addr.s_addr = INADDR_ANY;server.sin_port = 0;if (bind(sock, &server, sizeof(server) perror(binding stream socket);exit(1);/* Find out assigned port number and print it out */length = sizeof(server);if (getsockname(sock, &server, &length) perror(getting socket name
109、);exit(1);printf(Socket has port #%dn, ntohs(server.sin_port);/* Start accepting connections */listen(sock, 5);do msgsock = accept(sock, 0, 0);if (msgsock = -1)perror(accept);else do bzero(buf, sizeof(buf);PSD:20-16 Introductory 4.4BSD IPCif (rval = read(msgsock, buf, 1024) %sn, buf); while (rval !=
110、 0);close(msgsock); while (TRUE);/* Since this program has an infinite loop, the socket sock is* never explicitly closed.However, all sockets will be closed* automatically when a process is killed or terminates normally.*/Figure 7b Accepting an Internet domain stream connection#include #include #inc
111、lude #include #include #include #define TRUE 1/* This program uses select() to check that someone is trying to connect* before calling accept().*/main()int sock, length;struct sockaddr_in server;int msgsock;char buf1024;int rval;fd_set ready;struct timeval to;/* Create socket */sock = socket(AF_INET
112、, SOCK_STREAM, 0);if (sock 0) perror(opening stream socket);exit(1);/* Name socket using wildcards */server.sin_family = AF_INET;server.sin_addr.s_addr = INADDR_ANY;server.sin_port = 0;if (bind(sock, &server, sizeof(server) Introductory 4.4BSD IPCPSD:20-17perror(binding stream socket);exit(1);/* Fin
113、d out assigned port number and print it out */length = sizeof(server);if (getsockname(sock, &server, &length) perror(getting socket name);exit(1);printf(Socket has port #%dn, ntohs(server.sin_port);/* Start accepting connections */listen(sock, 5);do FD_ZERO(&ready);FD_SET(sock, &ready);to.tv_sec = 5
114、;if (select(sock + 1, &ready, 0, 0, &to) 0) perror(select);continue;if (FD_ISSET(sock, &ready) msgsock = accept(sock, (struct sockaddr *)0, (int *)0);if (msgsock = -1)perror(accept);else do bzero(buf, sizeof(buf);if (rval = read(msgsock, buf, 1024) %sn, buf); while (rval 0);close(msgsock); elseprint
115、f(Do something elsen); while (TRUE);Figure 7c Using select() to check for pending connectionsPSD:20-18 Introductory 4.4BSD IPCProcess 1Process 2Process 2Process 1NAMENAMEFigure 8 Establishing a stream connectionmessages, is performed and the connection socket closed. The accept() call will take a pe
116、nding connectionrequest from the queue if one is available, or block waiting for a request. Messages are read from the con-nection socket. Reads from an active connection will normally block until data is available. The number ofbytes read is returned. When a connection is destroyed, the read call r
117、eturns immediately. The number ofbytes returned will be zero.The program in Figure 7c is a slight variation on the server in Figure 7b. It avoids blocking whenthere are no pending connection requests by calling select() to check for pending requests before callingaccept(). This strategy is useful wh
118、en connections may be received on more than one socket, or when datamay arrive on other connected sockets before another connection request.The programs in Figures 9a and 9b show a program using stream communication in the UNIXdomain. Streams in the UNIX domain can be used for this sort of program i
119、n exactly the same way asInternet domain streams, except for the form of the names and the restriction of the connections to a singlefile system. There are some differences, however, in the functionality of streams in the two domains,notably in the handling of out-of-band data (discussed briefly bel
120、ow). These differences are beyond theIntroductory 4.4BSD IPCPSD:20-19scope of this paper.9. Reads, Writes, Recvs, etc.UNIX 4.4BSD has several system calls for reading and writing information. The simplest calls areread() and write(). Write() takes as arguments the index of a descriptor, a pointer to
121、 a buffer containing thedata and the size of the data. The descriptor may indicate either a file or a connected socket. Connectedcan mean either a connected stream socket (as described in Section 8) or a datagram socket for which aconnect() call has provided a default destination (see the connect()
122、manual page). Read() also takes adescriptor that indicates either a file or a socket. Write() requires a connected socket since no destination isspecified in the parameters of the system call. Read() can be used for either a connected or an unconnectedsocket. These calls are, therefore, quite flexib
123、le and may be used to write applications that require noassumptions about the source of their input or the destination of their output. There are variations on read()and write() that allow the source and destination of the input and output to use several separate buffers,while retaining the flexibil
124、ity to handle both files and sockets. These are readv() and writev(), for read andwrite vector.It is sometimes necessary to send high priority data over a connection that may have unread low pri-ority data at the other end. For example, a user interface process may be interpreting commands and send-
125、ing them on to another process through a stream connection. The user interface may have filled the streamwith as yet unprocessed requests when the user types a command to cancel all outstanding requests. Ratherthan have the high priority data wait to be processed after the low priority data, it is p
126、ossible to send it asout-of-band (OOB) data. The notification of pending OOB data results in the generation of a SIGURG sig-nal, if this signal has been enabled (see the manual page for signal or sigvec). See Leffler 1986 for a morecomplete description of the OOB mechanism. There are a pair of calls
127、 similar to read and write that allowoptions, including sending and receiving OOB information; these are send() and recv(). These calls areused only with sockets; specifying a descriptor for a file will result in the return of an error status. Thesecalls also allow peeking at data in a stream. That
128、is, they allow a process to read data without removing thedata from the stream. One use of this facility is to read ahead in a stream to determine the size of the nextitem to be read. When not using these options, these calls have the same functions as read() and write().To send datagrams, one must
129、be allowed to specify the destination. The call sendto() takes a destina-tion address as an argument and is therefore used for sending datagrams. The call recvfrom() is often usedto read datagrams, since this call returns the address of the sender, if it is available, along with the data. Ifthe iden
130、tity of the sender does not matter, one may use read() or recv().Finally, there are a pair of calls that allow the sending and receiving of messages from multiplebuffers, when the address of the recipient must be specified. These are sendmsg() and recvmsg(). Thesecalls are actually quite general and
131、 have other uses, including, in the UNIX domain, the transmission of afile descriptor from one process to another.The various options for reading and writing are shown in Figure 10, together with their parameters.The parameters for each system call reflect the differences in function of the differen
132、t calls. In the exam-ples given in this paper, the calls read() and write() have been used whenever possible.10. ChoicesThis paper has presented examples of some of the forms of communication supported by BerkeleyUNIX 4.4BSD. These have been presented in an order chosen for ease of presentation. It
133、is useful toreview these options emphasizing the factors that make each attractive.Pipes have the advantage of portability, in that they are supported in all UNIX systems. They also arerelatively simple to use. Socketpairs share this simplicity and have the additional advantage of allowingbidirectio
134、nal communication. The major shortcoming of these mechanisms is that they require communi-cating processes to be descendants of a common process. They do not allow intermachine communication.The two communication domains, UNIX and Internet, allow processes with no common ancestor tocommunicate. Of t
135、he two, only the Internet domain allows communication between machines. This makesPSD:20-20 Introductory 4.4BSD IPC#include #include #include #include #define DATA Half a league, half a league . . ./* This program connects to the socket named in the command line and sends a* one line message to that
136、 socket. The form of the command line is* ustreamwrite pathname*/main(argc, argv)int argc;char *argv;int sock;struct sockaddr_un server;char buf1024;/* Create socket */sock = socket(AF_UNIX, SOCK_STREAM, 0);if (sock 0) perror(opening stream socket);exit(1);/* Connect socket using name specified by c
137、ommand line. */server.sun_family = AF_UNIX;strcpy(server.sun_path, argv1);if (connect(sock, &server, sizeof(struct sockaddr_un) 0) close(sock);perror(connecting stream socket);exit(1);if (write(sock, DATA, sizeof(DATA) 0)perror(writing on stream socket);Figure 9a Initiating a UNIX domain stream conn
138、ection#include #include #include #include #define NAME socket/* This program creates a socket in the UNIX domain and binds a name to it.* After printing the sockets name it begins a loop. Each time through the* loop it accepts a connection and prints out messages from it.When theIntroductory 4.4BSD
139、IPCPSD:20-21* connection breaks, or a termination message comes through, the program* accepts a new connection.*/main()int sock, msgsock, rval;struct sockaddr_un server;char buf1024;/* Create socket */sock = socket(AF_UNIX, SOCK_STREAM, 0);if (sock 0) perror(opening stream socket);exit(1);/* Name so
140、cket using file system name */server.sun_family = AF_UNIX;strcpy(server.sun_path, NAME);if (bind(sock, &server, sizeof(struct sockaddr_un) perror(binding stream socket);exit(1);printf(Socket has name %sn, server.sun_path);/* Start accepting connections */listen(sock, 5);for (;) msgsock = accept(sock
141、, 0, 0);if (msgsock = -1)perror(accept);else do bzero(buf, sizeof(buf);if (rval = read(msgsock, buf, 1024) %sn, buf); while (rval 0);close(msgsock);/* The following statements are not executed, because they follow an* infinite loop.However, most ordinary programs will not run* forever. In the UNIX d
142、omain it is necessary to tell the file* system that one is through using NAME.In most programs one uses* the call unlink() as below. Since the user will have to kill this* program, it will be necessary to remove the name by a command from* the shell.*/close(sock);unlink(NAME);Figure 9b Accepting a U
143、NIX domain stream connectionPSD:20-22 Introductory 4.4BSD IPC/* The variable descriptor may be the descriptor of either a file* or of a socket.*/cc = read(descriptor, buf, nbytes)int cc, descriptor; char *buf; int nbytes;/* An iovec can include several source buffers.*/cc = readv(descriptor, iov, io
144、vcnt)int cc, descriptor; struct iovec *iov; int iovcnt;cc = write(descriptor, buf, nbytes)int cc, descriptor; char *buf; int nbytes;cc = writev(descriptor, iovec, ioveclen)int cc, descriptor; struct iovec *iovec; int ioveclen;/* The variable sock must be the descriptor of a socket.* Flags may includ
145、e MSG_OOB and MSG_PEEK.*/cc = send(sock, msg, len, flags)int cc, sock; char *msg; int len, flags;cc = sendto(sock, msg, len, flags, to, tolen)int cc, sock; char *msg; int len, flags;struct sockaddr *to; int tolen;cc = sendmsg(sock, msg, flags)int cc, sock; struct msghdr msg; int flags;cc = recv(sock
146、, buf, len, flags)int cc, sock; char *buf; int len, flags;cc = recvfrom(sock, buf, len, flags, from, fromlen)int cc, sock; char *buf; int len, flags;struct sockaddr *from; int *fromlen;cc = recvmsg(sock, msg, flags)int cc, socket; struct msghdr msg; int flags;Figure 10 Varieties of read and write co
147、mmandsthe Internet domain a necessary choice for processes running on separate machines.The choice between datagrams and stream communication is best made by carefully considering thesemantic and performance requirements of the application. Streams can be both advantageous and disad-vantageous. One
148、disadvantage is that a process is only allowed a limited number of open streams, as thereare usually only 64 entries available in the open descriptor table. This can cause problems if a single servermust talk with a large number of clients. Another is that for delivering a short message the stream s
149、etupand teardown time can be unnecessarily long. Weighed against this are the reliability built into the streams.This will often be the deciding factor in favor of streams.Introductory 4.4BSD IPCPSD:20-2311. What to do NextMany of the examples presented here can serve as models for multiprocess prog
150、rams and for pro-grams distributed across several machines. In developing a new multiprocess program, it is often easiest tofirst write the code to create the processes and communication paths. After this code is debugged, the codespecific to the application can be added.An introduction to the UNIX
151、system and programming using UNIX system calls can be found inKernighan and Pike 1984. Further documentation of the Berkeley UNIX 4.4BSD IPC mechanisms can befound in Leffler et al. 1986. More detailed information about particular calls and protocols is provided insections 2, 3 and 4 of the UNIX Pro
152、grammers Manual CSRG 1986. In particular the following manualpages are relevant:creating and naming sockets socket(2), bind(2)establishing connectionslisten(2), accept(2), connect(2)transferring dataread(2), write(2), send(2), recv(2)addresses inet(4F)protocols tcp(4P), udp(4P).AcknowledgementsI wou
153、ld like to thank Sam Leffler and Mike Karels for their help in understanding the IPCmechanisms and all the people whose comments have helped in writing and improving this re-port.This work was sponsored by the Defense Advanced Research Projects Agency (DoD),ARPA Order No. 4031, monitored by the Nava
154、l Electronics Systems Command under contractNo. N00039-C-0235. The views and conclusions contained in this document are those of the au-thor and should not be interpreted as representing official policies, either expressed or implied, ofthe Defense Research Projects Agency or of the US Government.Re
155、ferencesB.W. Kernighan & R. Pike, 1984,The UNIX Programming Environment.Englewood Cliffs, N.J.: Prentice-Hall.B.W. Kernighan & D.M. Ritchie, 1978,The C Programming Language,Englewood Cliffs, N.J.: Prentice-Hall.S.J. Leffler, R.S. Fabry, W.N. Joy, P. Lapsley, S. Miller & C. Torek, 1986,An Advanced 4.
156、4BSD Interprocess Communication Tutorial.Computer Systems Research Group,Department of Electrical Engineering and Computer Science,University of California, Berkeley.Computer Systems Research Group, 1986,UNIX Programmers Manual, 4.4 Berkeley Software Distribution.Computer Systems Research Group,Department of Electrical Engineering and Computer Science,University of California, Berkeley.