1.1
| Use Of TCP/IP   1
|
1.2
| Designing Applications For A Distributed Environment   2
|
1.3
| Standard And Nonstandard Application Protocols   2
|
1.4
| An Example Of Standard Application Protocol Use   2
|
1.5
| An Example Connection   3
|
1.6
| Using TELNET To Access An Alternative Service   4
|
1.7
| Application Protocols And Software Flexibility   5
|
1.8
| Viewing Services From The Provider's Perspective   6
|
1.9
| The Remainder Of The Text   7
|
1.10
| Summary   7
|
| For Further Study   7
|
| Exercises   8
|
2.1
| Introduction   9
|
2.2
| Motivation   10
|
2.3
| Terminology And Concepts   10
|
| 2.3.1
| Clients And Servers   10
|
| 2.3.2
| Privilege And Complexity   11
|
| 2.3.3
| Standard Vs. Nonstandard Client Software   11
|
| 2.3.4
| Parameterization Of Clients   12
|
| 2.3.5
| Connectionless Vs. Connection-Oriented Servers   13
|
| 2.3.6
| Stateless Vs. Stateful Servers   14
|
| 2.3.7
| A Stateful File Server Example   14
|
| 2.3.8
| Statelessness Is A Protocol Issue   16
|
| 2.3.9
| Servers As Clients   17
|
2.4
| Summary   18
|
| For Further Study   18
|
| Exercises   18
|
3.1
| Introduction   21
|
3.2
| Concurrency In Networks   22
|
3.3
| Concurrency In Servers   23
|
3.4
| Terminology And Concepts   24
|
| 3.4.1
| The Process Concept   25
|
| 3.4.2
| Threads   25
|
| 3.4.3
| Programs vs. Threads   26
|
| 3.4.4
| Procedure Calls   26
|
3.5
| An Example Of Concurrent Thread Creation   27
|
| 3.5.1
| A Sequential C Example   27
|
| 3.5.2
| A Concurrent Version   28
|
| 3.5.3
| Timeslicing   30
|
3.6
| Diverging Threads   31
|
3.7
| Context Switching And Protocol Software Design   32
|
3.8
| Concurrency And Asynchronous I/O   32
|
3.9
| Concurrency Under UNIX   33
|
3.10
| Executing A Separately Compiled Program   34
|
3.11
| Summary   35
|
| For Further Study   35
|
| Exercises   36
|
4.1
| Introduction   37
|
4.2
| Loosely Specified Protocol Software Interface   37
|
| 4.2.1
| Advantages And Disadvantages   38
|
4.3
| Interface Functionality   38
|
4.4
| Conceptual Interface Specification   39
|
4.5
| Implementation Of An API   39
|
4.6
| Two Basic Approaches To Network Communication   41
|
4.7
| The Basic I/O Functions Available In ANSI C   42
|
4.8
| History Of The UNIX Socket API   43
|
4.9
| Summary   44
|
| For Further Study   44
|
| Exercises   45
|
5.1
| Introduction   47
|
5.2
| The History Of Sockets   47
|
5.3
| Specifying A Protocol Interface   48
|
5.4
| The Socket Abstraction   49
|
| 5.4.1
| Socket Descriptors   49
|
| 5.4.2
| System Data Structures For Sockets   50
|
| 5.4.3
| Using Sockets   51
|
5.5
| Specifying An Endpoint Address   51
|
5.6
| A Generic Address Structure   52
|
5.7
| Functions In The Socket API   53
|
| 5.7.1
| The WSAStartup Function   53
|
| 5.7.2
| The WSACleanup Function   54
|
| 5.7.3
| The Socket Function   54
|
| 5.7.4
| The Connect Function   54
|
| 5.7.5
| The Send Function   54
|
| 5.7.6
| The Recv Function   55
|
| 5.7.7
| The Closesocket Function   55
|
| 5.7.8
| The Bind Function   55
|
| 5.7.9
| The Listen Function   55
|
| 5.7.10
| The Accept Function   56
|
| 5.7.11
| Summary Of Socket Calls Used With TCP   56
|
5.8
| Utility Routines For Integer Conversion   56
|
5.9
| Using Socket Calls In A Program   58
|
5.10
| Symbolic Constants For Socket Call Parameters   59
|
5.11
| Summary   59
|
| For Further Study   60
|
| Exercises   60
|
6.1
| Introduction   61
|
6.2
| Learning Algorithms Instead Of Details   61
|
6.3
| Client Architecture   62
|
6.4
| Identifying The Location Of A Server   62
|
6.5
| Parsing An Address Argument   64
|
6.6
| Looking Up A Domain Name   65
|
6.7
| Looking Up A Well-Known Port By Name   66
|
6.8
| Port Numbers And Network Byte Order   66
|
6.9
| Looking Up A Protocol By Name   67
|
6.10
| The TCP Client Algorithm   67
|
6.11
| Allocating A Socket   68
|
6.12
| Choosing A Local Protocol Port Number   69
|
6.13
| A Fundamental Problem In Choosing A Local IP Address   69
|
6.14
| Connecting A TCP Socket To A Server   70
|
6.15
| Communicating With The Server Using TCP   70
|
6.16
| Reading A Response From A TCP Connection   71
|
6.17
| Closing A TCP Connection   72
|
| 6.17.1
| The Need For Partial Close   72
|
| 6.17.2
| A Partial Close Operation   72
|
6.18
| Programming A UDP Client   73
|
6.19
| Connected And Unconnected UDP Sockets   73
|
6.20
| Using Connect With UDP   74
|
6.21
| Communicating With A Server Using UDP   74
|
6.22
| Closing A Socket That Uses UDP   74
|
6.23
| Partial Close For UDP   75
|
6.24
| A Warning About UDP Unreliability   75
|
6.25
| Summary   75
|
| For Further Study   76
|
| Exercises   76
|
7.1
| Introduction   79
|
7.2
| The Importance Of Small Examples   79
|
7.3
| Hiding Details   80
|
7.4
| An Example Procedure Library For Client Programs   80
|
7.5
| Implementation Of ConTCP   81
|
7.6
| Implementation Of ConUDP   82
|
7.7
| A Procedure That Forms Connections   82
|
7.8
| Using The Example Library   85
|
7.9
| The DAYTIME Service   85
|
7.10
| Implementation Of A TCP Client For DAYTIME   86
|
7.11
| Reading From A TCP Connection   87
|
7.12
| The TIME Service   88
|
7.13
| Accessing The TIME Service   88
|
7.14
| Accurate Times And Network Delays   89
|
7.15
| A UDP Client For The TIME Service   89
|
7.16
| The ECHO Service   91
|
7.17
| A TCP Client For The ECHO Service   92
|
7.18
| A UDP Client For The ECHO Service   94
|
7.19
| Summary   96
|
| For Further Study   96
|
| Exercises   96
|
8.1
| Introduction   99
|
8.2
| The Conceptual Server Algorithm   99
|
8.3
| Concurrent Vs. Iterative Servers   100
|
8.4
| Connection-Oriented Vs. Connectionless Access   100
|
8.5
| Connection-Oriented Servers   101
|
8.6
| Connectionless Servers   101
|
8.7
| Failure, Reliability, And Statelessness   102
|
8.8
| Optimizing Stateless Servers   103
|
8.9
| Four Basic Types Of Servers   105
|
8.10
| Request Processing Time   106
|
8.11
| Iterative Server Algorithms   106
|
8.12
| An Iterative, Connection-Oriented Server Algorithm   107
|
8.13
| Binding To A Well-Known Address Using INADDR_ANY   107
|
8.14
| Placing The Socket In Passive Mode   108
|
8.15
| Accepting Connections And Using Them   108
|
8.16
| An Iterative, Connectionless Server Algorithm   108
|
8.17
| Forming A Reply Address In A Connectionless Server   109
|
8.18
| Concurrent Server Algorithms   110
|
8.19
| Master And Slave Threads   110
|
8.20
| A Concurrent, Connectionless Server Algorithm   111
|
8.21
| A Concurrent, Connection-Oriented Server Algorithm   111
|
8.22
| Using Separate Programs As Slaves   112
|
8.23
| Apparent Concurrency Using A Single Thread   113
|
8.24
| When To Use Each Server Type   114
|
8.25
| A Summary of Server Types   115
|
8.26
| The Important Problem Of Server Deadlock   116
|
8.27
| Alternative Implementations   116
|
8.28
| Summary   117
|
| For Further Study   117
|
| Exercises   117
|
14.1
| Introduction   159
|
14.2
| Consolidating Servers   159
|
14.3
| A Connectionless, Multiservice Server Design   160
|
14.4
| A Connection-Oriented, Multiservice Server Design   161
|
14.5
| A Concurrent, Connection-Oriented, Multiservice Server   162
|
14.6
| A Singly-Threaded, Multiservice Server Implementation   162
|
14.7
| Invoking Separate Programs From A Multiservice Server   163
|
14.8
| Multiservice, Multiprotocol Designs   164
|
14.9
| An Example Multiservice Server   165
|
14.10
| Static and Dynamic Server Configuration   171
|
14.11
| An Example Super Server, Inetd   172
|
14.12
| Summary   174
|
| For Further Study   175
|
| Exercises   175
|
15.1
| Introduction   177
|
15.2
| Choosing Between An Iterative And A Concurrent Design   177
|
15.3
| Level Of Concurrency   178
|
15.4
| Demand-Driven Concurrency   179
|
15.5
| The Cost Of Concurrency   179
|
15.6
| Overhead And Delay   179
|
15.7
| Small Delays Can Matter   180
|
15.8
| Thread Preallocation   181
|
| 15.8.1
| Preallocation Techniques   182
|
| 15.8.2
| Preallocation In A Connection-Oriented Server   182
|
| 15.8.3
| Preallocation In A Connectionless Server   183
|
| 15.8.4
| Preallocation, Bursty Traffic, And NFS   184
|
| 15.8.5
| Preallocation On A Multiprocessor   185
|
15.9
| Delayed Thread Allocation   185
|
15.10
| The Uniform Basis For Both Techniques   186
|
15.11
| Combining Techniques   187
|
15.12
| Summary   187
|
| For Further Study   188
|
| Exercises   188
|
16.1
| Introduction   189
|
16.2
| The Advantages Of Concurrency   189
|
16.3
| The Motivation For Exercising Control   190
|
16.4
| Concurrent Contact With Multiple Servers   191
|
16.5
| Implementing Concurrent Clients   191
|
16.6
| Singly-Threaded Implementations   193
|
16.7
| An Example Concurrent Client That Uses ECHO   194
|
16.8
| Execution Of The Concurrent Client   198
|
16.9
| Managing A Timer   199
|
16.10
| Example Output   200
|
16.11
| Concurrency In The Example Code   200
|
16.12
| Summary   201
|
| Exercises   201
|
17.1
| Introduction   203
|
17.2
| Multiprotocol Environments   203
|
17.3
| Mixing Network Technologies   205
|
17.4
| Dynamic Circuit Allocation   206
|
17.5
| Encapsulation And Tunneling   207
|
17.6
| Tunneling Through An IP Internet   208
|
17.7
| Application-Level Tunneling Between Clients And Servers   208
|
17.8
| Tunneling, Encapsulation, And Dialup Phone Lines   209
|
17.9
| Summary   210
|
| For Further Study   211
|
| Exercises   211
|
18.1
| Introduction   213
|
18.2
| Clients And Servers In Constrained Environments   213
|
| 18.2.1
| The Reality Of Multiple Technologies   213
|
| 18.2.2
| Computers With Limited Functionality   214
|
| 18.2.3
| Connectivity Constraints That Arise From Security   214
|
18.3
| Using Application Gateways   215
|
18.4
| Interoperability Through A Mail Gateway   216
|
18.5
| Implementation Of A Mail Gateway   217
|
18.6
| A Comparison Of Application Gateways And Tunneling   217
|
18.7
| Application Gateways And Limited Functionality Systems   219
|
18.8
| Application Gateways Used For Security   220
|
18.9
| Application Gateways And The Extra Hop Problem   221
|
18.10
| An Example Application Gateway   223
|
18.11
| Details Of A Web-Based Application Gateway   224
|
18.12
| Invoking A CGI Program   225
|
18.13
| URLs For The RFC Application Gateway   226
|
18.14
| A General-Purpose Application Gateway   226
|
18.15
| Operation Of SLIRP   227
|
18.16
| How SLIRP Handles Connections   227
|
18.17
| IP Addressing And SLIRP   228
|
18.18
| Summary   229
|
| For Further Study   229
|
| Exercises   230
|
19.1
| Introduction   231
|
19.2
| Representations For Data In Computers   231
|
19.3
| The N-Squared Conversion Problem   232
|
19.4
| Network Standard Byte Order   233
|
19.5
| A De Facto Standard External Data Representation   234
|
19.6
| XDR Data Types   235
|
19.7
| Implicit Types   236
|
19.8
| Software Support For Using XDR   236
|
19.9
| XDR Library Routines   236
|
19.10
| Building A Message One Piece At A Time   236
|
19.11
| Conversion Routines In The XDR Library   238
|
19.12
| XDR Streams, I/O, and TCP   240
|
19.13
| Records, Record Boundaries, And Datagram I/O   241
|
19.14
| Summary   241
|
| For Further Study   242
|
| Exercises   242
|
20.1
| Introduction   243
|
20.2
| Remote Procedure Call Model   243
|
20.3
| Two Paradigms For Building Distributed Programs   244
|
20.4
| A Conceptual Model For Conventional Procedure Calls   245
|
20.5
| An Extension Of the Procedural Model   245
|
20.6
| Execution Of Conventional Procedure Call And Return   246
|
20.7
| The Procedural Model In Distributed Systems   247
|
20.8
| Analogy Between Client-Server And RPC   248
|
20.9
| Distributed Computation As A Program   249
|
20.10
| Sun Microsystems' Remote Procedure Call Definition   250
|
20.11
| Remote Programs And Procedures   250
|
20.12
| Reducing The Number Of Arguments   251
|
20.13
| Identifying Remote Programs And Procedures   251
|
20.14
| Accommodating Multiple Versions Of A Remote Program   252
|
20.15
| Mutual Exclusion For Procedures In A Remote Program   253
|
20.16
| Communication Semantics   254
|
20.17
| At Least Once Semantics   254
|
20.18
| RPC Retransmission   255
|
20.19
| Mapping A Remote Program To A Protocol Port   255
|
20.20
| Dynamic Port Mapping   256
|
20.21
| RPC Port Mapper Algorithm   257
|
20.22
| RPC Message Format   259
|
20.23
| Marshaling Arguments For A Remote Procedure   260
|
20.24
| Authentication   260
|
20.25
| An Example Of RPC Message Representation   261
|
20.26
| An Example Of An Authentication Field   262
|
20.27
| Summary   263
|
| For Further Study   264
|
| Exercises   264
|
21.1
| Introduction   267
|
21.2
| Using Remote Procedure Calls   268
|
21.3
| Programming Mechanisms To Support RPC   269
|
21.4
| Dividing A Program Into Local And Remote Procedures   270
|
21.5
| Adding Code For RPC   271
|
21.6
| Stub Procedures   271
|
21.7
| Multiple Remote Procedures And Dispatching   272
|
21.8
| Name Of The Client-Side Stub Procedure   273
|
21.9
| Using Rpcgen To Generate Distributed Programs   274
|
21.10
| Rpcgen Output And Interface Procedures   274
|
21.11
| Rpcgen Input And Output   275
|
21.12
| Using Rpcgen To Build A Client And Server   276
|
21.13
| Summary   276
|
| For Further Study   278
|
| Exercises   278
|
22.1
| Introduction   279
|
22.2
| An Example To Illustrate Rpcgen   280
|
22.3
| Dictionary Look Up   280
|
22.4
| Eight Steps To A Distributed Application   281
|
22.5
| Step 1: Build A Conventional Application Program   282
|
22.6
| Step 2: Divide The Program Into Two Parts   286
|
22.7
| Step 3: Create An Rpcgen Specification   292
|
22.8
| Step 4: Run Rpcgen   294
|
22.9
| The .h File Produced By Rpcgen   294
|
22.10
| The XDR Conversion File Produced By Rpcgen   296
|
22.11
| The Client Code Produced By Rpcgen   297
|
22.12
| The Server Code Produced By Rpcgen   298
|
22.13
| Step 5: Write Stub Interface Procedures   301
|
| 22.13.1
| Client-Side Interface Routines   301
|
| 22.13.2
| Server-Side Interface Routines   304
|
22.14
| Step 6: Compile And Link The Client Program   305
|
22.15
| Step 7: Compile And Link The Server Program   309
|
22.16
| Step 8: Start The Server And Execute The Client   311
|
22.17
| Summary   311
|
| For Further Study   311
|
| Exercises   312
|
23.1
| Introduction   313
|
23.2
| Remote File Access Vs. Transfer   313
|
23.3
| Operations On Remote Files   314
|
23.4
| File Access Among Heterogeneous Computers   314
|
23.5
| Stateless Servers   315
|
23.6
| NFS And UNIX File Semantics   315
|
23.7
| Review Of The UNIX File System   315
|
| 23.7.1
| Basic Definitions   315
|
| 23.7.2
| A Byte Sequence Without Record Boundaries   316
|
| 23.7.3
| A File's Owner And Group Identifiers   316
|
| 23.7.4
| Protection And Access   316
|
| 23.7.5
| The UNIX Open-Read-Write-Close Paradigm   318
|
| 23.7.6
| UNIX Data Transfer   319
|
| 23.7.7
| Permission To Search A Directory   319
|
| 23.7.8
| UNIX Random Access   320
|
| 23.7.9
| Seeking Beyond The End Of A UNIX File   320
|
| 23.7.10
| UNIX File Position And Concurrent Access   321
|
| 23.7.11
| Semantics Of Write During Concurrent Access   322
|
| 23.7.12
| UNIX File Names And Paths   322
|
| 23.7.13
| The UNIX Inode: Information Stored With A File   323
|
| 23.7.14
| The UNIX Stat Operation   324
|
| 23.7.15
| The UNIX File Naming Mechanism   325
|
| 23.7.16
| UNIX File System Mounts   326
|
| 23.7.17
| UNIX File Name Resolution   328
|
| 23.7.18
| UNIX Symbolic Links   329
|
23.8
| Files Under NFS   329
|
23.9
| NFS File Types   330
|
23.10
| NFS File Modes   330
|
23.11
| NFS File Attributes   331
|
23.12
| NFS Client And Server   332
|
23.13
| NFS Client Operation   333
|
23.14
| NFS Client And UNIX   334
|
23.15
| NFS Mounts   335
|
23.16
| File Handle   336
|
23.17
| NFS Handles Replace Path Names   336
|
23.18
| An NFS Client Under Windows   338
|
23.19
| File Positioning With A Stateless Server   338
|
23.20
| Operations On Directories   339
|
23.21
| Reading A Directory Statelessly   339
|
23.22
| Multiple Hierarchies In An NFS Server   340
|
23.23
| The Mount Protocol   340
|
23.24
| Summary   341
|
| For Further Study   341
|
| Exercises   341
|
24.1
| Introduction   343
|
24.2
| Using RPC To Define A Protocol   343
|
24.3
| Defining A Protocol With Data Structures And Procedures   344
|
24.4
| NFS Constant, Type, And Data Declarations   345
|
| 24.4.1
| NFS Constants   345
|
| 24.4.2
| NFS Typedef Declarations   346
|
| 24.4.3
| NFS Data Structures   346
|
24.5
| NFS Procedures   348
|
24.6
| Semantics Of NFS Operations   349
|
| 24.6.1
| NFSPROC_NULL (Procedure 0)   350
|
| 24.6.2
| NFSPROC_GETATTR (Procedure 1)   350
|
| 24.6.3
| NFSPROC_SETATTR (Procedure 2)   350
|
| 24.6.4
| NFSPROC_ROOT (Procedure 3) [Obsolete in NFS3]   350
|
| 24.6.5
| NFSPROC_LOOKUP (Procedure 4)   350
|
| 24.6.6
| NFSPROC_READLINK (Procedure 5)   350
|
| 24.6.7
| NFSPROC_READ (Procedure 6)   350
|
| 24.6.8
| NFSPROC_WRITECACHE (Procedure 7) [Obsolete in NFS3]   350
|
| 24.6.9
| NFSPROC_WRITE (Procedure 8)   351
|
| 24.6.10
| NFSPROC_CREATE (Procedure 9)   351
|
| 24.6.11
| NFSPROC_REMOVE (Procedure 10)   351
|
| 24.6.12
| NFSPROC_RENAME (Procedure 11)   351
|
| 24.6.13
| NFSPROC_LINK (Procedure 12)   351
|
| 24.6.14
| NFSPROC_SYMLINK (Procedure 13)   351
|
| 24.6.15
| NFSPROC_MKDIR (Procedure 14)   352
|
| 24.6.16
| NFSPROC_RMDIR (Procedure 15)   352
|
| 24.6.17
| NFSPROC_READDIR (Procedure 16)   352
|
| 24.6.18
| NFSPROC_STATFS (Procedure 17)   352
|
24.7
| The Mount Protocol   353
|
| 24.7.1
| Mount Constant Definitions   353
|
| 24.7.2
| Mount Type Definitions   353
|
| 24.7.3
| Mount Data Structures   354
|
24.8
| Procedures In The Mount Protocol   355
|
24.9
| Semantics of Mount Operations   355
|
| 24.9.1
| MNTPROC_NULL (Procedure 0)   355
|
| 24.9.2
| MNTPROC_MNT (Procedure 1)   355
|
| 24.9.3
| MNTPROC_DUMP (Procedure 2)   356
|
| 24.9.4
| MNTPROC_UMNT (Procedure 3)   356
|
| 24.9.5
| MNTPROC_UMNTALL (Procedure 4)   356
|
| 24.9.6
| MNTPROC_EXPORT (Procedure 5)   356
|
24.10
| NFS And Mount Authentication   356
|
24.11
| Changes In NFS Version 3   358
|
24.12
| Summary   359
|
| For Further Study   359
|
| Exercises   360
|
25.1
| Introduction   361
|
25.2
| Overview   362
|
| 25.2.1
| The User's Terminal   362
|
| 25.2.2
| Command And Control Information   362
|
| 25.2.3
| Terminals, Windows, and Files   362
|
| 25.2.4
| The Need For Concurrency   363
|
| 25.2.5
| A Thread Model For A TELNET Client   364
|
25.3
| A TELNET Client Algorithm   364
|
25.4
| Keyboard I/O In Windows   365
|
25.5
| Global Variables Used For Keyboard Control   366
|
25.6
| Initializing The Keyboard Thread   367
|
25.7
| Finite State Machine Specification   370
|
25.8
| Embedding Commands In A TELNET Data Stream   370
|
25.9
| Option Negotiation   371
|
25.10
| Request/Offer Symmetry   372
|
25.11
| TELNET Character Definitions   372
|
25.12
| A Finite State Machine For Data From The Server   373
|
25.13
| Transitions Among States   374
|
25.14
| A Finite State Machine Implementation   376
|
25.15
| A Compact FSM Representation   376
|
25.16
| Keeping The Compact Representation At Run-Time   378
|
25.17
| Implementation Of A Compact Representation   378
|
25.18
| Building An FSM Transition Matrix   380
|
25.19
| The Socket Output Finite State Machine   382
|
25.20
| Definitions For The Socket Output FSM   384
|
25.21
| The Option Subnegotiation Finite State Machine   385
|
25.22
| Definitions For The Option Subnegotiation FSM   386
|
25.23
| FSM Initialization   387
|
25.24
| Arguments For The TELNET Client   387
|
25.25
| The Heart Of The TELNET Client   389
|
25.26
| TELNET Synchronization   391
|
25.27
| Handling A Severe Error   392
|
25.28
| Implementation Of The Main FSM   393
|
25.29
| A Procedure For Immediate Disconnection   394
|
25.30
| Abort Procedure   395
|
25.31
| Summary   395
|
| For Further Study   396
|
| Exercises   396
|
26.1
| Introduction   399
|
26.2
| The FSM Action Procedures   399
|
26.3
| Recording The Type Of An Option Request   400
|
26.4
| Performing No Operation   401
|
26.5
| Responding To WILL/WONT For The Echo Option   401
|
26.6
| Sending A Response   402
|
26.7
| Responding To WILL/WONT For Unsupported Options   403
|
26.8
| Responding To WILL/WONT For The No Go-Ahead Option   404
|
26.9
| Generating DO/DONT For Binary Transmission   405
|
26.10
| Responding To DO/DONT For Unsupported Options   406
|
26.11
| Responding To DO/DONT For Transmit Binary Option   406
|
26.12
| Responding To DO/DONT For The Terminal Type Option   408
|
26.13
| Option Subnegotiation   409
|
26.14
| Sending Terminal Type Information   410
|
26.15
| Terminating Subnegotiation   412
|
26.16
| Sending A Character To The Server   412
|
26.17
| Displaying Incoming Data On The User's Terminal   414
|
26.18
| Writing A Block Of Data To The Server   417
|
26.19
| Interacting With The Local Client   418
|
26.20
| Responding To Illegal Commands   419
|
26.21
| Scripting To A File   419
|
26.22
| Implementation Of Scripting   420
|
26.23
| Initialization Of Scripting   420
|
26.24
| Collecting Characters Of The Script File Name   421
|
26.25
| Opening A Script File   422
|
26.26
| Terminating Scripting   424
|
26.27
| Printing Status Information   425
|
26.28
| Summary   426
|
| For Further Study   427
|
| Exercises   427
|
27.1
| Introduction   429
|
27.2
| Operating In Background   429
|
27.3
| Shared Descriptors And Inheritance   431
|
27.4
| The Controlling TTY   431
|
27.5
| Working Directories   432
|
27.6
| File Creation And Umask   432
|
27.7
| Process Groups   433
|
27.8
| Descriptors For Standard I/O   433
|
27.9
| Mutual Exclusion For A Server   434
|
27.10
| Recording A Process ID   434
|
27.11
| Waiting For A Child Process To Exit   435
|
27.12
| Using A System Log Facility   435
|
| 27.12.1
| Generating Log Messages   435
|
27.13
| Miscellaneous Incompatibilities   437
|
27.14
| Summary   438
|
| For Further Study   438
|
| Exercises   439
|
28.1
| Introduction   441
|
28.2
| Definition Of Deadlock   442
|
28.3
| Difficulty Of Deadlock Detection   442
|
28.4
| Deadlock Avoidance   443
|
28.5
| Deadlock Between A Client And Server   443
|
28.6
| Avoiding Deadlock In A Single Interaction   444
|
28.7
| Starvation Among A Set Of Clients And A Server   444
|
28.8
| Busy Connections And Starvation   445
|
28.9
| Avoiding Blocking Operations   446
|
28.10
| Threads, Connections, And Other Limits   446
|
28.11
| Cycles Of Clients And Servers   447
|
28.12
| Documenting Dependencies   447
|
28.13
| Summary   448
|
| For Further Study   449
|
| Exercises   449
|