1.1 TCP/IP的应用 1
1.2分布式环境下应用程序的设计 1
第1章 概述 1
1.4使用标准应用协议的例子 2
1.3标准和非标准的应用协议 2
1.6 用TELNET访问其他服务 3
1.5 telnet连接的例子 3
1.7应用协议和软件的灵活性 4
1.8从提供者的角度看服务 5
习题 6
进一步的研究 6
1.9本书的其余部分 6
1.10小结 6
2.2动机 8
2.1 简介 8
第2章 客户-服务器模型和软件的设计 8
2.3.2特权和复杂性 9
2.3.1 客户端和服务器 9
2.3术语和概念 9
2.3.4客户端的参数化 10
2.3.3标准和非标准的客户端软件 10
2.3.5无连接的与面向连接的服务 11
2.3.7有状态的文件服务器例子 12
2.3.6无状态与有状态的服务器 12
2.3.8无状态是一个协议问题 14
2.4 小结 15
2.3.9充当客户端的服务器 15
习题 16
进一步的研究 16
3.2网络中的并发 17
3.1 引言 17
第3章 客户-服务器软件的并发处理 17
3.3服务器中的并发 18
3.4.1进程的概念 19
3.4术语和概念 19
3.4.2线程 20
3.4.4过程调用 21
3.4.3程序和线程 21
3.5.1 一个顺序执行的C的示例 22
3.5一个创建并发线程的例子 22
3.5.2程序的并发版本 23
3.5.3 时间片 25
3.6分离的线程 26
3.8并发和异步I/O 27
3.7上下文切换和协议软件设计 27
3.9 UNIX下的并发 28
3.10执行一个单独编译的程序 29
习题 30
进一步的研究 30
3.11 小结 30
4.2 宽松定义的协议软件接口 32
4.1 引言 32
第4章 协议的程序接口 32
4.4概念性接口的规范 33
4.3接口功能 33
4.5 API的实现 34
4.7 ANSIC中提供的基本I/O函数 36
4.6 网络通信的两种基本方法 36
4.8 UNIX套接字API的历史 37
习题 38
进一步的研究 38
4.9 小结 38
5.2套接字的历史 40
5.1 简介 40
第5章 套接字API 40
5.4.1 套接字描述符 41
5.4套接字的抽象 41
5.3 一个协议接口的制订 41
5.4.2套接字的系统数据结构 42
5.5指定端点地址 43
5.4.3使用套接字 43
5.6 通用地址结构 44
5.7套接字API中的函数 45
5.7.5 send函数 46
5.7.4 connect函数 46
5.7.1 WSAStartup函数 46
5.7.2 WSACleanup函数 46
5.7.3 Socket函数 46
5.7.8 bind函数 47
5.7.7 closesocket函数 47
5.7.6 recv函数 47
5.7.11 TCP套接字调用小结 48
5.7.10 accept调用 48
5.7.9 listen函数 48
5.9程序中使用套接字调用 49
5.8 用于整数转换的实用例程 49
5.10用作套接字调用参数的符号常量 50
习题 51
进一步的研究 51
5.11 小结 51
6.2学习算法而不研究细节 53
6.1 引言 53
第6章 客户软件设计中的算法和问题 53
6.4标识服务器的地址 54
6.3客户体系结构 54
6.5分析地址参数 55
6.6 查找域名 56
6.7 由名字查找熟知端口 57
6.9 由名字查找协议 58
6.8 端口号和网络字节顺序 58
6.11分配套接字 59
6.10 TCP客户算法 59
6.13选择本地 IP地址的一个基本问题 60
6.12选择本地协议端口号 60
6.15 使用TCP和服务器通信 61
6.14 将TCP套接字连接到服务器 61
6.16 从TCP连接上读取响应 62
6.17.2部分关闭的操作 63
6.17.1需要部分关闭 63
6.17 关闭TCP连接 63
6.19面向连接的和无连接的UDP套接字 64
6.18 UDP客户端的编程 64
6.23 对UDP的部分关闭 65
6.22关闭使用UDP的套接字 65
6.20 对UDP使用connect 65
6.21 使用UDP和服务器通信 65
6.25小结 66
6.24关于UDP不可靠性的警告 66
习题 67
进一步的研究 67
7.3 隐藏细节 68
7.2小例子的重要性 68
第7章 客户软件举例 68
7.1 引言 68
7.4客户程序的过程库例子 69
7.6 ConUPD的实现 70
7.5 ConTCP的实现 70
7.7用来建立连接的过程 71
7.9 DAYTIME服务 74
7.8使用例子库 74
7.10 DAYTIME的TCP客户实现 75
7.11 从TCP连接上读取数据 76
7.13 访问TIME服务 77
7.12TIME服务 77
7.15 TIME服务的UDP客户 78
7.14精确的时间和网络时延 78
7.16 ECHO服务 80
7.17 ECHO服务的TCP客户 81
7.18 ECHO 服务的UDP客户 83
进一步的研究 85
7.19 小结 85
习题 86
8.3并发服务器和循环服务器 87
8.2概念性的服务器算法 87
第8章 服务器软件设计的算法和问题 87
8.1 引言 87
8.5面向连接的服务器 88
8.4 面向连接的访问和无连接的访问 88
8.6无连接的服务器 89
8.8优化无状态服务器 90
87 故障、可靠性和无状态 90
8.9 四种基本类型的服务器 92
8.10请求处理时间 93
8.13用INADDR_ANY绑定熟知地址 94
8.12循环的、面向连接的服务器算法 94
8.11循环服务器的算法 94
8.16循环的、无连接的服务器算法 95
8.15接受连接并使用这些连接 95
8.14 将套接字设置为被动模式 95
8.17在无连接的服务器上构造响应地址 96
8.19主线程和子线程 97
8.18并发服务器的算法 97
8.21 并发的、面向连接的服务器算法 98
8.20并发的、无连接的服务器的算法 98
8.23使用单个线程实现表面上的并发性 99
8.22用分离的程序作为子进程 99
8.24各服务器类型的使用场合 100
8.25.4并发的、面向连接的服务器 101
8.25.3并发的、无连接的服务器 101
8.25服务类型小结 101
8.25.1循环的、无连接的服务器 101
8.25.2循环的、面向连接的服务器 101
8.26重要的服务器死锁的问题 102
进一步的研究 103
8.28小结 103
8.27其他的实现方法 103
习题 104
9.2创建被动套接字 105
9.1 引言 105
第9章 循环无连接服务器(UDP) 105
9.3 线程结构 108
9.4 TIME服务器举例 109
习题 111
进一步的研究 111
9.5小结 111
10.2 分配被动的TCP套接字 112
10.1 引言 112
第10章 循环的、面向连接的服务器(TCP) 112
10.4 线程结构 113
10.3实现DAYTIME服务的服务器 113
10.5 DAYTIME服务器举例 114
10.6关闭连接 116
10.8 小结 117
10.7 连接终止和服务器的脆弱性 117
习题 118
进一步的研究 118
11.2 并发ECHO 119
11.1 引言 119
第11章 并发的、面向连接的服务器(TCP) 119
11.4 线程结构 120
11.3 循环的实现和并发的实现的比较 120
11.5 并发的ECHO服务器举例 121
习题 124
进一步的研究 124
11.6小结 124
12.2服务器中的数据驱动处理 125
12.1 引言 125
第12章 单线程、并发服务器(TCP) 125
12.4 单线程服务器的线程结构 126
12.3 单线程的数据驱动处理 126
12.5 单线程ECHO服务器举例 127
习题 130
进一步的研究 130
12.6小结 130
13.2减少服务器数量的动机 132
13.1引言 132
第13章 多协议服务器(TCP,UDP) 132
13.4线程结构 133
13.3 多协议服务器的设计 133
13.5多协议DAYTIME服务器举例 134
13.7并发的多协议服务器 137
13.6共享代码的概念 137
习题 138
进一步的研究 138
13.8小结 138
14.2服务器程序的合并 139
14.1 引言 139
第14章 多服务服务器(TCP,UDP) 139
14.4面向连接的、多服务服务器的设计 140
14.3 无连接的、多服务服务器的设计 140
14.5 并发的、面向连接的、多服务服务器 141
14.6单线程多服务服务器的实现 142
14.7 多服务服务器对其他单独程序的调用 143
14.9 一个多服务服务器的例子 144
14.8多服务、多协议设计 144
14.10静态的和动态的服务器配置 150
14.11 一个超级服务器的例子,Inetd 151
习题 153
进一步的研究 153
14.12小结 153
15.2 在循环设计和并发设计之间做出选择 155
15.1引言 155
第15章 服务器并发性的统一高效管理 155
15.4需求驱动的并发 156
15.3并发等级 156
15.7小时延会出问题 157
15.6额外开销和时延 157
15.5 并发的代价 157
15.8.1预分配技术 159
15.8线程预分配 159
15.8.2面向连接的服务器的预分配 160
15.8.4 预分配、突发通信量和NFS 161
15.8.3无连接服务器的预分配 161
15.9延迟的线程分配 162
15.8.5 多处理器上的预分配 162
15.10两种技术统一的基础 163
15.12小结 164
15.11 两种技术的结合 164
习题 165
进一步的研究 165
16.2并发的优点 166
16.1 引言 166
第16章 客户端的并发 166
16.4与多个服务器的并发联系 167
16.3运行控制的动机 167
16.5实现并发的客户端 168
16.6单线程实现 169
16.7 使用ECHO的并发客户端例子 170
16.8并发客户端的执行 175
16.10输出举例 176
16.9计时器的管理 176
习题 177
16.12小结 177
16.11例子代码中的并发性 177
17.2多协议环境 179
17.1 引言 179
第17章 传输层和应用层的隧道技术 179
17.3混合各种网络技术 180
17.4动态电路分配 181
17.5封装和隧道技术 182
17.7客户端和服务器之间的应用层隧道技术 183
17.6通过IP互联网的隧道技术 183
17.8隧道技术、封装以及拨号电话线 184
进一步的研究 185
17.9小结 185
习题 186
18.2.1 多重技术的现实 187
18.2受限环境中的客户端与服务器 187
第18章 应用层网关 187
18.1 引言 187
18.3使用应用网关 188
18.2.3 安全性引发的连通性约束 188
18.2.2功能有限的计算机 188
18.4通过邮件网关的交互 189
18.6应用网关和隧道技术的比较 190
18.5邮件网关的实现 190
18.7应用网关和功能受限的系统 192
18.8为了安全性使用的应用网关 193
18.9应用网关和额外跳问题 194
18.10 一个应用网关的例子 195
18.11 基于Web的应用网关的细节 196
18.12调用CGI程序 197
18.14通用的应用网关 198
18.13 RFC应用网关的URL 198
18.16 SLIRP如何处理连接 199
18.15 SLIRP的运行 199
18.17 IP寻址与SLIRP 200
进一步的研究 201
18.18 小结 201
习题 202
19.2计算机中数据的表示 203
19.1 引言 203
第19章 外部数据表示(XDR) 203
19.3 N平方转换问题 204
19.4网络标准字节序 205
19.6 XDR数据类型 206
19.5外部数据表示事实上的标准 206
19.9 XDR库例行程序 207
19.8 使用XDR的软件支持 207
19.7 隐含类型 207
19.10一次一部分地构建报文 208
19.11 XDR库的转换例行程序 209
19.12 XDR流、I/O和TCP 210
19.14小结 211
19.13 记录、记录边界和数据报I/O 211
习题 212
进一步的研究 212
20.3构建分布式程序的两种模式 213
20.2 远程过程调用模型 213
第20章 远程过程调用(RPC)的概念 213
20.1 引言 213
20.4常规过程调用的概念模型 214
20.6常规过程调用的执行和返回 215
20.5 过程模型的扩充 215
20.7分布式系统中的过程模型 216
208客户-服务器和RPC的相似性 217
20.10 Sun Microsystems的远程过程调用定义 218
20.9作为程序的分布式计算 218
20.12减少参数的数量 219
20.11 远程程序和过程 219
20.13标记远程程序和过程 220
20.14 适应远程程序的多个版本 221
20.17 至少一次语义 222
20.16 通信语义 222
20.15 远程程序中的过程互斥 222
20.18 RPC重传 223
20.20 动态端口映射 224
20.19把远程程序映射到协议端口 224
20.21 RPC端口映射器算法 225
20.22 RPC消息格式 226
20.23为远程过程排列参数 227
20.24 身份认证 228
20.26认证字段的例子 229
20.25 RPC消息表示的例子 229
20.27小结 230
习题 231
进一步的研究 231
21.2用使用远程过程调用 232
21.1引言 232
第21章 分布式程序的生成(Rpcgen概念) 232
21.3支持RPC的编程机制 233
21.4将程序分割成本地过程和远程过程 234
21.6桩(stub)过程 235
21.5为 RPC增加代码 235
21.8客户端的桩过程名称 236
21.7多个远程过程和分发 236
21.9使用Rpcgen生成分布式程序 237
21.10 Rpcgen输出和接口过程 238
21.12使用Rpcgen构建客户端和服务器 239
21.11 Rpcgen的输入和输出 239
进一步的研究 240
21.13小结 240
习题 241
22.3查询字典 242
22.2 举例说明Rpcgen 242
第22章 分布式程序的生(Rpcgen的例子) 242
22.1 引言 242
22.4建立分布式程序的八个步骤 243
22.5步骤1:建立常规应用程序 244
22.6 步骤2:将程序分割成两部分 248
22.7步骤3:创建Rpcgen规范 254
22.8步骤4:运行Rpcgen 255
22.9 Rpcgen生成的.h文件 256
22.10 Rpcgen生成的XDR转换文件 257
22.11 Rpcgen生成的客户端代码 258
22.12 Rpcgen生成的服务器代码 260
22.13.1客户端接口例程 263
22.13步骤5:编写桩接口过程 263
22.13.2客户端接口例程 265
22.14步骤6:编译链接客户端程序 267
22.15步骤7:编译链接服务器程序 270
22.17小结 272
22.16步骤8:启动服务器和运行客户端 272
习题 273
进一步的研究 273
23.2远程文件访问与文件传输 274
23.1 引言 274
第23章 网络文件系统(NFS)的概念 274
23.5无状态的服务器 275
23.4异构计算机之间的文件访问 275
23.3对远程文件的操作 275
23.7.2无记录边界的字节序列 276
23.7.1基本定义 276
23.6 NFS和UNIX文件语义 276
23.7 UNIX文件系统概述 276
23.7.4保护和访问 277
23.7.3文件的拥有者和组标识符 277
23.7.6 UNIX中的数据传输 278
23.7.5 UNIX中的打开-读-写-关闭范例 278
23.7.8 UNIX中的随机访问 279
23.7.7搜索目录的权限 279
23.7.10 UNIX文件位置和并发访问 280
23.7.9搜索超过UNIX文件结尾 280
23.7.12 UNIX中的文件名和路径 281
23.7.11 并发访问时的写操作的语义 281
23.7.13 UNIX索引节点:存储在文件中的信息 282
23.7.14 UNIX中的Stat操作 283
23.7.16装配UNIX文件系统 284
23.7.15 UNIX的文件命名机制 284
23.7.18 UNIX符号链接 286
23.7.17 UNIX文件名解析 286
23.9 NFS文件类型 287
23.8 NFS下的文件 287
23.10 NFS文件模式 288
23.12 NFS的客户端和服务器 289
23.11 NFS文件属性 289
23.14 NFS的客户端和UNIX 291
23.13 NFS客户端的操作 291
23.15 NFS的装配(Mounts) 292
23.17 NFS句柄取代路径名 293
23.16文件句柄 293
23.18 Windows下的NFS客户端 294
23.20对目录的操作 295
23.19无状态服务器的文件定位 295
23.22 NFS服务器中的多个分层结构 296
23.21无状态地读目录 296
23.24小结 297
23.23装配协议 297
习题 298
进一步的研究 298
24.2用RPC定义协议 300
24.1 引言 300
第24章 网络文件系统协议(NFS,Mount) 300
24.4.1 NFS的常量 301
24.4 NFS的常量、类型和数据声明 301
24.3用数据结构和过程定义协议 301
24.4.2 NFS的Typedef声明 302
24.4.3 NFS的数据结构 303
24.5 NFS的过程 305
24.6.5 NFSPROC_LOOKUP(过程4) 306
24.6.4 NFSPROC_ROOT(过程3)[在NFS3中已经不用了] 306
24.6 NFS中的操作的语义 306
24.6.1 NFSPROC_NULL(过程0) 306
24.6.2 NFSPROC_GETATTR (过程1) 306
24.6.3 NFSPROC_SETATTR(过程2) 306
24.6.11 NFSPROC_REMOVE (过程10) 307
24.6.10 NFSPROC_CREATE(过程9) 307
24.6.6 NFSPROC_READLINK(过程5) 307
24.6.7 NFSPROC_READ(过程6) 307
24.6.8 NFSPROC_WRITECACHE(过程7)[在NFS3中已经不用了] 307
24.6.9 NFSPROC_WRITE (过程8) 307
24.6.17 NFSPROC_READDIR(过程16) 308
24.6.16 NFSPROC_RMDIR(过程15) 308
24.6.12 NFSPROC_RENAME (过程11) 308
24.6.13 NFSPROC_LINK(过程12) 308
24.6.14 NFSPROC_SYMLINK(过程13) 308
24.6.15 NFSPROC_MKDIR(过程14) 308
24.7.1 装配协议的常量定义 309
24.7装配协议 309
24.6.18 NFSPROC_STATFS(过程17) 309
24.7.3装配协议的数据结构 310
24.7.2装配协议的类型定义 310
24.8装配协议中的过程 311
24.9.4 MNTPROC_UMNT(过程3) 312
24.9.3 MNTPROC_DUMP(过程2) 312
24.9装配操作的语义 312
24.9.1 MNTPROC_NULL(过程0) 312
24.9.2 MNTPROC_MNT(过程1) 312
24.10 NFS和装配的鉴别 313
24.9.6 MNTPROC_EXPORT(过程5) 313
24.9.5 MNTPROC_UMNTALL(过程4) 313
24.11 NFS版本3中的变化 314
24.12 小结 315
习题 316
进一步的研究 316
25.2.1用户终端 317
25.2概述 317
第25章 TELNET客户端(程序结构) 317
25.1 引言 317
25.2.4对并发性的需要 318
25.2.3终端、窗口和文件 318
25.2.2命令和控制信息 318
25.3 TELNET客户端的算法 319
25.2.5 TELNET客户端的线程模型 319
25.4 Windows中的键盘I/O 320
25.5键盘控制中使用的全局变量 321
25.6初始化键盘线程 322
25.8 ELNET数据流中内嵌的命令 325
25.7有限状态机的特点 325
25.10请求/提供的对称 326
25.9选项协商 326
25.11 TELNET字符定义 327
25.12从服务器来的数据的有限状态机 328
25.13状态之间的转换 329
25.14实现有限状态机 330
25.15紧凑的FSM表达 331
25.17实现紧凑表示 332
25.16在运行时维持紧凑表示 332
25.18构造FSM转移矩阵 334
25.19套接字输出的有限状态机 335
25.20套接字输出FSM的定义 337
25.21选项子协商的有限状态机 338
25.22选项子协商FSM的定义 339
25.23初始化FSM 340
25.24 TELNET客户端的参数 341
25.25 TELNET客户端的核心 342
25.26 TELNET的同步 345
25.28实现主FSM 346
25.27处理严重的错误 346
25.29 立即断开连接的过程 347
25.30 中止过程 348
进一步的研究 349
25.31 小结 349
习题 350
26.3记录选项请求的类型 351
26.2有限状态机的动作过程 351
第26章 TELNET客户端(实现细节) 351
26.1引言 351
26.4执行空操作 352
26.5 响应针对回显选项的WILL/WONT 353
26.6发送响应 354
26.7 响应针对不被支持选项的WILL/WONT 355
26.8 响应针对No Go-Ahead选项的WILL/WONT 356
26.9 为二进制传输生成DO/DONT 357
26.10 响应针对不被支持选项的DO/DONT 358
26.11 响应针对传输二进制选项的DO/DONT 359
26.12 响应针对终端类型选项的DO/DONT 360
26.13选项的子协商 362
26.14发送终端类型信息 363
26.15 中止子协商 364
26.16向服务器发送一个字符 365
26.17在用户终端上显示传入的数据 366
26.18将一块数据写到服务器中 369
26.19与本地客户端的交互 370
26.21 抄写脚本到文件 371
26.20对非法命令的响应 371
26.23抄写脚本的初始化 372
26.22抄写脚本的实现 372
26.24收集脚本文件名的字符 373
26.25 打开脚本文件 374
26.26中止抄写脚本 375
26.27打印状态信息 377
进一步的研究 378
26.28 小结 378
习题 379
27.2后台操作 380
27.1 引言 380
第27章 将服务器程序从UNIX移植到WINDOWS 380
27.3共享描述符和继承 381
27.5工作目录 382
27.4 控制TTY 382
27.7进程组 383
27.6建立文件和Umask 383
27.9服务器互斥 384
27.8标准I/O描述符 384
27.11 等待一个子进程退出 385
27.10记录进程ID 385
27.12使用系统日志设施 386
27.13其他的不兼容 387
27.14小结 388
习题 389
进一步的研究 389
28.2死锁的定义 390
28.1引言 390
第28章 客户-服务器系统中的死锁和饿死 390
28.4避免死锁 391
28.3死锁检测的难度 391
28.6在单个交互中避免死锁 392
28.5单个客户端和服务器间的死锁 392
28.8忙连接和饿死 393
28.7一组客户端和单个服务器之间的饿死 393
28.10线程、连接和其他限制 394
28.9避免阻塞的操作 394
28.11 客户端和服务器的循环 395
28.12给依赖性建立文档 396
习题 397
进一步的研究 397
28.13 小结 397
附录A 套接字使用的函数和库例程 399
附录B Windows套接字描述符的操作 433
参考文献 436