socket 编程原理 zz
第二章 socket 编程原理
2.1 问题的引入
UNIX 系统的 I/O 命令集,是从 Maltics 和早期系统中的命令演变出来的,其模式为打开一读/写一关闭
(open-write-read- close)。在一个用户进程进行 I/O 操作时,它首先调用“打开”获得对指定文件或设备
的使用权,并返回称为文件描述符的整型数,以描述用户在打开的文件或设备上进行 I/O 操作的进程。然
后这个用户进程多次调用“读/写”以传输数据。当所有的传输操作完成后,用户进程关闭调用,通知操作系
统已经完成了对某对象的使用。
TCP/IP 协议被集成到 UNIX 内核中时,相当于在 UNIX 系统引入了一种新型的 I/O 操作。UNIX 用户
进程与网络协议的交互作用比用户进程与传统的 I/O 设备相互作用复杂得多。首先,进行网络操作的两个
进程在不同机器上,如何建立它们之间的联系?其次,网络协议存在多种,如何建立一种通用机制以支持
多种协议?这些都是网络应用编程界面所要解决的问题。
在 UNIX 系统中,网络应用编程界面有两类:UNIX BSD 的套接字(socket)和 UNIX System V 的
TLI。由于 Sun 公司采用了支持 TCP/IP 的 UNIX BSD 操作系统,使 TCP/IP 的应用有更大的发展,其网
络应用编程界面──套接字( socket)在网络软件中被广泛应用,至今已引进微机操作系统 DOS 和
Windows 系统中,成为开发网络应用软件的强有力工具,本章将要详细讨论这个问题。
2.2 套接字编程基本概念
在开始使用套接字编程之前,首先必须建立以下概念。
2.2.1 网间进程通信
进程通信的概念最初来源于单机系统。由于每个进程都在自己的地址范围内运行,为保证两个相互通
信的进程之间既互不干扰又协调一致工作,操作系统为进程通信提供了相应设施,如 UNIX BSD 中的管
道(pipe)、命名管道(named pipe)和软中断信号(signal),UNIX system V 的消息(message)、
共享存储区(shared memory)和信号量(semaphore)等,但都仅限于用在本机进程之间通信。网间进
程通信要解决的是不同主机进程间的相互通信问题(可把同机进程通信看作是其中的特例)。为此,首先
要解决的是网间进程标识问题。同一主机上,不同进程可用进程号( process ID)唯一标识。但在网络环
境下,各主机独立分配的进程号不能唯一标识该进程。例如,主机 A 赋于某进程号 5,在 B 机中也可以存
在 5 号进程,因此,“5 号进程”这句话就没有意义了。
其次,操作系统支持的网络协议众多,不同协议的工作方式不同,地址格式也不同。因此,网间进程
通信还要解决多重协议的识别问题。
为了解决上述问题,TCP/IP 协议引入了下列几个概念。
端口
网络中可以被命名和寻址的通信端口,是操作系统可分配的一种资源。
按照 OSI 七层协议的描述,传输层与网络层在功能上的最大区别是传输层提供进程通信能力。从这个
意义上讲,网络通信的最终地址就不仅仅是主机地址了,还包括可以描述进程的某种标识符。为此 ,
TCP/IP 协议提出了协议端口(protocol port,简称端口)的概念,用于标识通信的进程。
端口是一种抽象的软件结构(包括一些数据结构和 I/O 缓冲区)。应用程序(即进程)通过系统调用
与某端口建立连接(binding)后,传输层传给该端口的数据都被相应进程所接收,相应进程发给传输层
的数据都通过该端口输出。在 TCP/IP 协议的实现中,端口操作类似于一般的 I/O 操作,进程获取一个端
口,相当于获取本地唯一的 I/O 文件,可以用一般的读写原语访问之。
类似于文件描述符,每个端口都拥有一个叫端口号(port number)的整数型标识符,用于区别不同
端口。由于 TCP/IP 传输层的两个协议 TCP 和 UDP 是完全独立的两个软件模块,因此各自的端口号也相
互独立,如 TCP 有一个 255 号端口,UDP 也可以有一个 255 号端口,二者并不冲突。
端口号的分配是一个重要问题。有两种基本分配方式:第一种叫全局分配,这是一种集中控制方式,
由一个公认的中央机构根据用户需要进行统一分配,并将结果公布于众。第二种是本地分配,又称动态连