--- 套接字(Socket)起初来源于UNIX,是加利福尼亚大学Berkeley 分校开发的UNIX 操作系统下的网络通信接口。随着UNIX 操作系统 的广泛使用,Socket 亦当之无愧的成为了最流行的网络通信程序接口之一。90 年代初期,由Sun Microsystems,JSB.CO,FTP Software,Microdyne 和Microsoft 等几家公司联合制定了一套Windows 下套接字编程的规范,称为Windows Sockets 规范,初步实现了Windows下的Sockets 接口程序的标准化,并于1992 年推出了Windows Sockets V1.0 版,次年发表了其2.0 版,IBM 发行的TCP/IP V2.1 for DOS 就是其代表,它还提供了Windows Sockets 的应用程序 接口(API)。Microsoft 的Windows Sockets API 是Windows下的网络应 用程序接口,为了适用于Windows 下的消息机制和异步的I/O选择操作,Windows Sockets API 在功能上扩充了将近20个函数,其中 扩充的部分均冠以前缀WSA(Windows Sockets Asynchronous), 如WSAStartup、WSAClean 等,充分体现了Widnows 的优越性。
---- 此外,Windows Sockets API 有16 位版和32 位版两种,16 位版是 单进程的,32 位版则提供了多线程下的安全保护。
---- 本文将浅解Windows下的Sockets 编程的机理,旨在抛砖引玉。一并说明Windows Sockets 编程的重要性!
一、Windows Sockets 简介
---- 套接字是网络通信的基本构件,提供了不同主机间进程双向通 信的端点,如同电话,只有当一方拨通另一方时,双方方能建立对话,而套接字正好比双方的电话。通过Sockets 编程,程序可以跳过复杂的网络底层协议和结构,直接编制与平台无关的应用程序。随着Internet 的广泛应用,Sockets 已逐渐成为网络编程的通用接口。
---- 套接字存在于其特定的通信域(即地址族)中,只有隶属于同一地址族的套接字才能建立对话,Windows Sockets V1.0 目前只支持网际域(AF_INET),所有使用网际协议簇的进程均适用于该域。 一般情况下除非通信协议支持,只有相同类型的套接字方能相互传递数据,Windows Sockets V1.1 版主要支持两种类型的套接字:流式套接字和数据报套接字,还有一种是原始套接字,但为保证网络应用程序的兼容性,一般不鼓励使用原始套接字。
---- 流式套接字(SOCK_STREAM):该类套接字提供了面向连接 的、可靠的、数据无错并且无重复的数据发送服务。而且发送的数据是按顺序接收的。所有利用该套接字进行传递的数据均被视为连续的字节流的并且无长度限制。这对数据的稳定性、正确性和发送/ 接受顺序要求严格的应用十分适用,TCP 协议使用该类接口。但其对线路的占用率相对提高。流式套接字的实现屡见不鲜,如远程登录(TELNET)、文件传输协议(FTP)等均使用了流式套接字。
---- 数据报式套接字(SOCK_DGRAM):数据报式套接字提供了面向无连接的服务 , 它独立的数据包形式发送数据( 数据包长度不能大于32KB),不提供正确性检查,也不保证各数据包的发送顺序,因此,可能出现数据的重发、丢失等现象,并且接收顺序由具体路由决定。然而,数据报的实现对网络线路占用率较低。NFS(网络文件系统)即是采用此类套接字、在TCP/IP 协议族中,UDP(User Datagram Protocol)使用该类接口。
---- 原始套接字(SOCK_RAW): 该套接字一般不会出现在高级网络接口的实现中,因为它是直接针对协议的较低层( 如IP、TCP、UDP 等) 直接访问的。常用于检验新的协议实现或访问现有服务中配置的新设备,如前所述,一般不提倡他的直接应用。
---- 因为Windows Sockets 主要是面向C/S 体系结构的,即客户向服务器发出请求,服务器只有在接收到请求后才能提供相应服务。双方在建立对话前, 服务进程和接受服务的进程( 客户)必须首先建立起各自用于网间进程通信的半相关,即一个三元组( 协议,本地地址,本地端口),但只有双方独立的半相关还不能建立起沟通。一个完整的网络通信进程必须通过由两个独立进程组成的一个完整的全相关唯一确定方能得已实现,而且,只有两个性质相同的半相关才能建立一个完整的全相关五元组─ ─(协议,本地地址,本地端口,远地地址,远地端口),由此方能建立起一个网间进程通信的实例。
---- 让我们由C/S 模式的主动请求方式来解释用Windows Sockets 建立网络进程间对话的过程。
---- 首先启动服务器方,以提供相应服务:
---- (1)打开一个通信通道并通知网络:本机将在某一公认的端口上等待客户(Client)请求;
---- (2)服务器进入阻塞等待状态,等待客户请求的到来;
---- (3)当服务器接收到一个客户的连接请求时, 激活一个新的进程用于处理客户请求并建立C/S 对话,服务完成后 ,关闭此新进程与户的通信链路, 并将其终止;
---- (4)返回第(2)步,等待另一客户请求;
---- (5)关闭服务器。
---- 客户端进程:
---- (1)指定想与之建立连接的服务器相应服务的保留端口号;
---- (2)向服务器发送CONNECT 请求并等待服务器的应答;
---- (3)接收到服务器建立连接的响应后接受服务器相应服务;
---- (4)服务请求结束后关闭通信通道并终止。
---- 由此可见,用Windows Sockets 建立的面向连接的无重复套接字系统的过程实现图解如下:
---- 流式套接字首先由客户与正在某一端口监听的服务器建立起连接后方能进行数据传送,并且是双工的。与此不同,用数据报协议实现的网络进程间通信过程如下:
---- Windows Sockets 编 程 还 可 应 用 于 远 程 进 程 调 用(RPC), 它 使 得 用 户 进 程 可 调 用 远 端 的 进 程, 为 远 程 控 制 和 分 布 式 管 理 带 来 了 方 便。 在 对 等 网 络 中 应 用 也 极 其 广 泛, 如Windows 的 网 上 白 板(Chat) 和 红 心 大 战 均 是 通 过Windows Sockets 建 立 的 网 络 连 接 而 进 行 进 程 间 通 信 的。 现 今 的 许 多 网 络 游 戏 则 是Windows Sockets 的 直 接 利 用。 可 以 说Windows Sockets 是 网 络 游 戏
二、Windows Sockets 编 程 初 探---- 1、Microsoft Visual Basic 实 现
---- Microsoft Visual Basic 提 供 了 用 于Windows Sockets 编 程 的 可 用 控 件--Winsock 控 件。 该 控 件 为 用 户 提 供 了 访 问TCP 和UDP 网 络 的 极 其 方 便 的 途 径。 并 且 适 用 于Microsoft Access、Visual Basic、Visual C++ 和Visual FoxPro 等 多 种 可 视 化 环 境。 通 过Winsock 控 件 编 制C/S 程 序, 程 序 员 无 须 了 解TCP 或 低 级Winsock APIs 调 用 实 现 的 细 节, 如 用 户 无 须 考 虑 网 络 字 节 顺 序 与 本 机 字 接 顺 序 便 可 直 接 进 行 数 据 的 传 送。 用 该 控 件 实 现 网 间 进 程 通 信 极 其 方 便。
---- 在TCP 应 用 中, 为 了 建 立 一 个 网 络 连 接 实 例(Instance) 的 服 务 器 端, 只 需 设 置 本 地 服 务 断 口 号, 然 后 服 务 器 调 用 方 法Listen 进 入 阻 塞 状 态 等 待 来 自 客 户 的 连 接 请 求。 与 此 对 应 的 客 户 端 不 但 要 将Winsock 的 属 性RemoteHost 置 为 服 务 器 的 名 称(IP 地 址 或 网 络 代 号), 还 应 设 置 服 务 器 所 监 听 的 相 应 服 务 的 端 口 号(RemotePort), 如FTP 服 务 在21 号 端 口,HTTP 在81 号 端 口 等。 然 后 调 用 方 法Winsock.Connect 向 服 务 器 发 出 请 求。 服 务 器 接 收 到 客 户 请 求 时, 事 件ConnectionRequest 将 被 触 发。 如 服 务 器 愿 意 提 供 服 务 则 可 调 用Accept 方 法 接 受 连 接。
---- 一 旦 连 接 建 立, 两 端 均 可 使 用SendData 或GetData 进 行 数 据 的 发 送 或 接 收。 事 件DataArrival 将 在 另 一 端 数 据 准 备 就 绪 时 被 触 发。
---- UDP 协 议 的 实 现 与TCP 不 同 的 是, 调 用Sockets 的 两 端 无 需 建 立 连 接 便 可 进 行 数 据 的 传 输。 因 此, 一 个UDP 应 用 可 以 同 时 担 任 服 务 器 或 客 户 的 角 色。
---- 以 下 程 序 代 码 为Visual Basic Windows Sockets 编 程 的 基 本 框 架。 ' 服 务 器 方
Private Sub Command1.Click()
' 设 置 本 地 服 务 端 口 号
Winsock1.localport=2048
' 服 务 器 进 入 监 听 状 态
Winsock1.listen
End Sub
Private Sub Winsock1_ConnectionRequest(ByVal requestID As Long)
' 收 到 客 户 连 接 请 求
' 检 查Socket 状 态
If Winsock1.State <> sckClosed Then Winsock1.Close
' 接 受 客 户 请 求
Winsock1.Accept requestID
End Sub
Private Sub Winsock1_DataArrival(ByVal bytesTotal As Long)
' 对 方 数 据 已 准 备 好
' 可 用GetData()/SendData() 接 收/ 发 送 数 据
' 处 理 客 户 数 据
. . . . . .
End Sub
Private Sub Form_Unload(Cancel As Integer)
Winsock1.Close
End Sub
' 客 户 方
Private Sub Command1.Click()
' 设 置 服 务 器 网 络 名
Winsock1.RemoteHost=“193.168.1.40”
' 设 置 服 务 器 相 应 服 务 端 口 号
Winsock1.RemotePort=2048
' 向 服 务 器 发 出 连 接 请 求
Winsock1.Connect
End Sub
Private Sub Winsock1_Connect()
' 服 务 器 响 应 连 接
' 可 以 进 行GetData()/SendData() 进 行 数 据 传 输
. . . . . .
End Sub
Private Sub Form1.Unload()
Winsock1.Close
End Sub
---- 该 段 程 序 演 示 了 用Visual Basic 建 立TCP 连 接 的 基 本 过 程。 因 本 文 重 在 讲 解Sockets 编 程, 故 文 中 未 涉 及VB 自 己 封 装 的 故 障 处 理 函 数Winsock1.Erroe(), 读 者 可 自 行 编 制。 以 上 程 序 段 可 作 为 一 般TCP 应 用 的 基 本 框 架 加 以 扩 展 使 用。
---- 2、Microsoft Visual C++ 实 现
---- MFC(Microsoft Foundmation Complierment) 提 供 了 两 种 类 定 义 以 实 现Sockets 应 用, 它 们 是:CAsynSockets 类 和CSockets 类。 此 两 种 类 的 区 别 为:CAsynSockets 封 装 了Windows Sockets API 函 数, 提 供 了 对Sockets 的 底 层 支 持, 直 接 应 用CAsynSockets 需 要 程 序 员 谙 习 网 络。 与 此 不 同 的 是CSockets 类 抽 象 化 了 这 些 底 层 细 节, 并 将 其 进 行 了 封 装。 此 外,CSockets 类 与CAchieve 类 结 合 应 用, 使 得 网 络 数 据 传 输 如 同 实 现 串 行 协 议 一 样 容 易。
---- 利 用MFC 建 立 网 络 通 信 的 过 程 如 下 所 示:
---- (1) 构 造CSockets 对 象, 并 获 取 该 对 象 句 柄;
---- (2) 在TCP 应 用 中, 客 户 端 应 使 用 缺 省 参 数 的Create 调 用, 而 对 于 服 务 器 对 象 来 说, 则 应 在 调 用Create 使 指 明 本 地 服 务 端 口 号;
---- (3) 服 务 器 端 调 用CAsynSockets::Listen 进 入 监 听 状 态, 客 户 端 则 应 使 用CAsynSockets::Connect 向 服 务 器 发 出 请 求, 建 立 与 服 务 器 的 连 接。 服 务 器 在 接 收 到 客 户 请 求 后 由CAsynSockets::Accept 响 应 客 户 请 求;
---- (4) 将 已 建 立 连 接 的CSockets 对 象 与CSocketsFile 对 象 相 关 连, 并 利 用CArchive 对 象 进 行 双 向 数 据 传 输( 如 同 文 件 读 写 操 作);
---- (5) 网 络 通 信 进 程 结 束 后, 双 方 需 释 放CArchieve、CSockets 和CSocketsFile 对 象 的 占 用 资 源;
---- 其 大 体 实 现 过 程 与 前 述 的VB 实 现 类 同。 具 体 实 例 可 见Microsoft Visual C++ Samples 中 的chatsrv 与chater 程 序。
三、 综 述---- 随 着Internet 的 逐 步 兴 起,Sockets 编 程 必 将 成 为 流 行 的 网 络 编 程 接 口 之 一。 也 许 您 会 发 问:ISO 的OSI 模 型 又 是 何 等 地 位 呢 ? 笔 者 的 观 点 是:ISO 的OSI 模 型 必 将 成 为 网 络 应 用 的 统 一 界 面,Sockets 接 口 的 广 泛 应 用 则 为OSI 模 型 开 拓 了 更 广 泛 的 应 用 前 景 !