Chapter 1 Introduction And Overview 1
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
Chapter 2 The Client Server Model And Software Design 9
2.1 Introduction 9
2.2 Motivation 10
2.3 Terminology And Concepts 10
2.3.1 Clients And Servers 10
2.3.3 Standard Vs.Nonstandard Client Software 11
2.3.2 Privilege And Complexity 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
Chapter 3 Concurrent Processing In Client-Server Software 21
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.4 Procedure Calls 26
3.4.3 Programs vs.Threads 26
3.5.1 A Sequential C Example 27
3.5 An Example Of Concurrent Thread Creation 27
3.5.2A 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
Chapter 4 Program Interface To Protocols 37
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.5 Implementation Of An API 39
4.4 Conceptual Interface Specification 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
Chapter 5 The Socket API 47
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.1 The WSAStartup Function 53
5.7 Functions In The Socket API 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.7The Closesocket Function 55
5.7.8 The Bind Function 55
5.7.9The 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
6.2 Learning Algorithms Instead Of Details 61
6.1 Introduction 61
Chapter 6 Algorithms And Issues In Client Software Design 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.7Looking 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 Cnnection 71
6.17.2 A Partial Close Operation 72
6.17.1 The Need For Partial Close 72
6.17 Closing A TCP Connection 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
Chapter 7 Example Client Software 79
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.7A Procedure That Forms Connections 82
7.6 Implementation Of ConUDP 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.16The 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
Chapter 8 Aigorithms And Issues In Server Software Design 99
8.1 Introduction 99
8.2 The Conceptual Server Algorithm 99
8.4 Connection-Oriented Vs.Connectionless Access 100
8.3 Concurrent Vs.Iterative Servers 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.19 Master And Slave Threads 110
8.18 Concurrent Server Algorithms 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.27 Alternative Implementations 116
8.26 The Important Problem Of Server Deadlock 116
8.28 Summary 117
Chapter 9 Iterative , Connectioniess Servers(UDP) 119
9.1 Introduction 119
9.2 Creating A Passive Socket 119
9.3 Thread Structure 122
9.4 An Example TIME Server 123
9.5 Summary 125
10.2 Allocating A Passive TCP Socket 127
10.1 Introduction 127
Chapter 10 Iterative , Connection-Oriented Servers(TCP) 127
10.3 A Server For The DAYTIME Service 128
10.4 Thread Structure 128
10.5 An Example DAYTIME Server 129
10.6 Closing Connections 132
10.7 Connection Termination And Server Vulnerability 132
10.8 Summary 133
Chapter 11 Concurrent, Connection-Oriented Servers(TCP) 135
11.1 Introduction 135
11.2 Concurrent ECHO 135
11.3 Iterative Vs.Concurrent Implementations 136
11.4 Thread Structure 136
11.5 An Example Concurrent ECHO Server 137
11.6 Summary 140
12.1 Introduction 143
12.2 Data-driven Processing In A Server 143
Chapter 12 Singly-Threaded, Concurrent Servers(TCP) 143
12.3 Data-Driven Processing With A Single Thread 144
12.4 Thread Structure Of A Singly-Threaded Server 145
12.5 An Example Singly-Threaded ECHO Server 146
12.6 Summary 148
Chapter 13 Multiprotocol Servers(TCP,UDP) 151
13.1 Introduction 151
13.2 The Motivation For Reducing The Number Of Servers 151
13.4 Thread Structure 152
13.3 Multiprotocol Server Design 152
13.5 An Example Multiprotocol DAYTIME Server 153
13.6The Concept Of Shared Code 157
13.7 Concurrent Multiprotocol Servers 157
13.8 Summary 157
Chapter 14 Multiservice Servers(TCP, UDP) 159
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
Chapter 15 Uniform,Efficient Management Of Server Concurrency 177
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
Chapter 16 Concurrency In Clients 189
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
17.1 Introduction 203
17.2 Multiprotocol Environments 203
Chapter 17 Tunneling At The Transport And Application Levels 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
18.2.1 The Reality Of Multiple Technologies 213
18.2Clients And Servers In Constrained Environments 213
Chapter 18 Application Level Gateways 213
18.1 Introduction 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.14 A General-Purpose Application Gateway 226
18.13 URLs For The RFC 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
Chapter 19 External Data Representation(XDR) 231
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 XDP 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
Chapter 20 Remote Procedure Call Concept(RPC) 243
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 Microsystem s Remote Procedure Call Definition 250
20.11 Remote Programs And Procedures 250
20.13 Identifying Remote Programs And Procedures 251
20.12 Reducing The Number Of Arguments 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
21.1 Introduction 267
Chapter 21 Distributed Program Generation(Rpcgen Concept) 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.10 Rpcgen Output And Interface Procedures 274
21.9 Using Rpcgen To Generate Distributed Programs 274
21.11 Rpcgen Input And Output 275
21.12 Using Rpcgen To Build A Client And Server 276
21.13 Summary 276
Chapter 22 Distributed Program Generation(Rpcgen Example) 279
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
23.2 Remote File Access Vs.Transfer 313
Chapter 23 Network File System Concepts(NFS) 313
23.1 Introduction 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.8 Files Under NFS 329
23.7.18 UNIX Symbolic Links 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.17 NFS Handles Replace Path Names 336
23.16 File Handle 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
Chapter 24 Network File System Protocol(NFS,Mount) 343
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(Procedure1) 350
24.6.3 NFSPROC_SETATTR(Procedure2) 350
24.6.4 NFSPROC_ROOT(Procedure3)[Obsolete in NFS3] 350
24.6.5 NFSPROC_LOOKUP(Procedure4) 350
24.6.6 NFSPROC_READLINK(Procedure 5) 350
24.6.7 NFSPROC_READ(Procedure 6) 350
24.6.8NFSPROC_WRITECACHE(Procedure7)[Obsolete in NFS 3] 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.18 NFSPROC_STATFS(Procedure 17) 352
24.6.17 NFSPROC_READDIR(Procedure 16) 352
24.6.15 NFSPROC_MKDIR(Procedure 14) 352
24.6.16 NFSPROC_RMDIR(Procedure 15) 352
24.7 The Mount Protocol 353
24.7.1 Mount Constant Definitions 353
24.7.2 Mount Type Definitions 353
27.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
Chapter 25 A TELNET Client(Program Structure) 361
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.3 A TELNET Client Algorithm 364
25.2.5 A Thread Model For A TELNET Client 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.11 TELNET Character Definitions 372
25.10 Request/Offer Symmetry 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 Rum-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
nt(Implementation Details) 399
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.27 Printing Status Information 425
26.28 Summary 426
27.2 Operating In Background 429
Chapter 27 Porting Servers From UNIX To Windows 429
27.1 Introduction 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
28.1 Introduction 441
Chapter 28 Deadlock And Starvation In Client-Server Systems 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.10 Threads, Connections, And Other Limits 446
28.9 Avoiding Blocking Operations 446
28.11 Cycles Of Clients And Servers 447
28.12 Documenting Dependencies 447
28.13 Summary 448
Appendix 1 Functions And Library Routines Used With Sockets 451
Appendix 2 Manipulation Of Windows Socket Descriptors 485
Bibliography 489
Index 499