开发Windows Sockets通信应用程序的经验与实践
青岛海军潜艇学院软件中心(266071) 徐立国
摘要 本文阐述了开发Windows Sockets通信程 序的软、硬件环境,基本步骤和技术要点,并以在Windows 95环境下,用Visual C++ 4.0编程为例 ,进一步阐述了开发Windows Soc-kets通信程序的经验与实践。
关键词 套接字 Windows Sockets 计算机网络 通信
一、引言
套接字(Socket)最初是由加利福尼亚大学Berkeley分校为UNIX操作系统开发的网络通信接口,随着UNIX操作系统的广泛使用,套接字成为当前最流行的网络通信应用程序接口之一。90年代初,由Sun Microsystems,JSB Corporation,FTP software,Microdyne和Microsoft等几家公司共同制定了一套标准,即Windows Sockets规范。
Windows Sockets API是Microsoft Windows的网络程序设计接口,它在继承了Berkeley Sockets主要特征的基础上,又对它进行了重要扩充。这些扩充主要是提供了一些异步函数,并增加了符合Windows消息驱动特性的网络事件异步选择机制 。这些扩充有利于应用程序开发者编制符合Windows编程模式的软件,它使在Windows下开发高性能的网络通信程序成为可能。
Socket实际上是指一个通信端点,借助于它,用户所开发的Socket应用程序,可以通过网络与其它Socket应用程序进行通信。
近年来,随着计算机网络与Windows 95的流行,许多用户所开发的应用程序需要实现网络间的数据通信,在此,笔者根据在Windows 95环境下,利用Visual C++ 4.0进行Windows Sockets应用程序的开发经验,阐述一下有关网络间数据通信程序的开发内容。
二、开发Windows Sockets网络通信程序的软、硬件环境
所采用的操作系统软件可以是Windows 95,也可以是Windows NT,因为它们都支持Windows Sockets API,在以下的介绍中,我们将以在Windows 95环境下的开发为例。
所采用的编程语言一般可选目前较流行使用的可视化和采用面向对象技术的Microsoft Visual C++ 4.0。Visual C++ 4.0可在Windows 95或Windows NT环境下运行,其开发系统增加了全面集成的基于Windows 的开发工具以及一个基于传统C/C++开发过程的“可视化”用户界面驱动模型。Visual C++ 4.0中的Microsoft基类(MFC,即Microsoft Foundation Class)库是一系列C++类,其中封装着为Microsoft Windows操作系统系列编写应用程序的各种功能 。在有关套接字方面,Visual C++ 4.0对原来的Windows Sockets库函数进行了一系列封装,继而产生了CSocket 、CSocketFile等类,它们封装着有关Socket的各种功能。
所采用的网络通信协议一般是TCP / IP。Windows 95和Windows NT都带有该协议。但是,所开发的网络通信应用程序并不能直接与TCP / IP核心打交道,而是与网络应用编程界面Windows Sockets API打交道。Windows Sockets API则可直接与TCP/IP核心进行沟通。TCP / IP核心协议连同网络物理介质(如网卡)一起,都是提供网络应用程序间相互通信的设施。其关系如图1所示。
网络通信应用程序
Windows Sockets API
TCP / IP核心协议
物理介质
图1 TCP / IP协议核心与网络通信应用程序关系图
在采用TCP / IP网络协议的应用中,各网络节点计算机之上的Windows Sockets网络通信程序之间相互作用的主要模式为客户 / 服务器(Client / Server ) 模式。即客户向服务器发出服务请求,服务器接收到请求后,提供相应的服务。采用这种模式的网络应用程序在进行通信时,服务器方的网络应用程序需首先启动,并打开一通信通道告知本地主机,它可以在某一公认地址上(保留端口,如文件传送协议FTP为21)接收客户请求。而客户方的网络应用程序随后启动,并打开一通信通道,连接到服务器所在主机的保留端口。
图2是客户方的PC机1、PC机2和PC机3上的Windows Sockets通信程序,与服务器方的PC机0上的Windows Sockets通信程序,采用客户 / 服务器模式进行通信的典型拓扑结构。
PC机0
以太网交换机或集线器
PC机1 PC机2 PC机3
图2 采用客户/ 服务器模式相互作用的Windows Sockets通信程序
所采用的典型网络拓扑结构
网络中的所采用的计算机应满足Windows 95运行的配置要求。如果有条件,最好采用Pentium或其以上档次的微机,将内存配置到16MB,并采用1GB左右的硬盘。
网络中各节点上的计算机需安装网卡,并通过Windows 95或其它途径安装上该网卡的驱动程序。此外,象图2那样的网络若采用以太网交换机(SWITCH),需购买一台带有一个100Mbps端口和数个10Mbps端口的以太网交换机,如3COM公司的 SWITCH 1000 ,并通过5类线(UTP)将各计算机上的网卡连接入交换机中相应的端口,即:将带有100Mbps以太网卡的PC 0接入100Mbps端口,将其它各计算机接入3个10Mbps端口。
在配置网络时,首先应通过Windows 95控制面板中的网络配置项及Windows 95资源管理器中文件属性共享性的设置,使各计算机节点能在“网上邻居”中找到自己和其它各计算机,并能实现文件资源相互共享。有关这方面内容介绍的文章已有不少,在此笔者不再赘述。
要实现Windows Sockets应用程序在网上的数据通信,仅仅达到文件资源相互共享还不够,还必须在Windows 95控制面板中的网络配置项添加上TCP / IP协议,同时给定相应的IP地址,这些IP地址在所建的局域网中,不能有重复。象图2中的网络,一般要采用C类地址。
以图2网络为例,在对TCP / IP的属性进行设置的对话框中,在“IP地址”一项可选“指定IP地址” ,在将“子网屏蔽”都设置为255.255.0.0的情况下 ,PC机 0、PC 机1、PC 机2、PC机3各计算机的IP地址可依此设置为166.166.100.101,166.166.100.102,166.166.100.103,166.166.100.104。
三、进行Windows Sockets通信程序开发的基本步骤
Windows Sockets支持两种类型的套接字,即流式套接字(SOCK_STREAM)、和数据报套接字(SOCK_DGRAM)。对于要求精确传输数据的Windows Sockets通信程序,一般采用流式套接字。流式套接字提供了一个面向连接的、可靠的、数据无错的、无重复发送的及按发送顺序接收数据的服务。其内设流量控制,避免数据流超限,同时,数据被看作是字节流,无长度限制。采用流式套接字的应用程序的开发都有其基本步骤,图3是服务器方及客户方通信程序的基本流程及作用关系。
服务器方 客户机方
创建流式套接字
s1=socket(......)
将本地地址与s1相连
bind(s1, ..... )
监听来自客户方的连接
listen(s1, .....)
建立流式套接字
s=socket(........)
接收连接,并得到
新的套接字s2
s2=accept(s1, ....)
将套接字s与服务器
建立连接 方主机连接
connect(s, .......)
在套接字s2上,
读/ 写数据,直至 在套接字s上写/读数据,
数据交换完 直到数据交换完
recv(s2, .....) 数据传输 send(s, .....)
send(s2, .....) recv(s, .....)
关闭套接字s2 关闭套接字s
closesocket ( s2 ) closesocket( s )
关闭套接字s1
closesocket(s1)
图3 服务器及客户机方通信程序基本流程及作用关系
尽管Visual C++ 4.0对原来的Windows Sockets库函数进行了一系列封装,但利用Visual C++ 4.0进行Windows Sockets应用程序开发,其基本流程及作用关系仍然同图3类似。以在Visual C++ 4.0中,经常结合使用CSocket、CSocketFile、CArchive等类开发通信程序的方法为例,阐述其基本步骤,如图4所示。
服务器方(SERVER) 客户方(CLIENT)
1、构造一个套接字 1、构造一个套接字
CSocket ser_s1; CSocket cli_s;
2、创建该套接字 2、创建该套接字
ser_s1.Create (port) ; cli_s.Create ( ) ;
其中,port为服务器方打开
的通信通道号
3、开始监听来自客户机的连接
ser_s1.Listen( );
3、客户机方套接字cli_s向服务器方
套接字ser_s1发出连接请求
cli_s .Connect (Addr,port);
(其中,Addr是欲连接服务器方
套接字地址结构指针,可采用IP地
址或机器名。port即打开的通道号,
其值与服务器方的一致。)
4、构造一个新的套接字
Csocket ser_s2 ;
5、服务器等待从ser_s2上
接受客户连接请求
ser_s1.Accept (ser_s2) ;
6、构造一个类CSocketFile的对象 4、构造一个类CSocketFile的对象
CSocketFile file(&ser_s2) ; CSocketFile file(&cli_s) ;
7、构造类CArchive的对象arIn、arOut 5、构造类CArchive的对象arIn、arOut
,以用于数据的收和发。 ,以用于数据的收和发。
CArchive arIn(&file , CArchive ::load) ; CArchive arIn(&file , CArchive ::load) ;
CArchive arOut(&file , CArchive ::store) ;CArchive arOut(&file , CArchive ::store) ;
8、使用arIn和 arOut 进行收或发数据 6、使用arIn和 arOut 进行发或收数据
arIn >> value ; arOut << value ;
arOut << value ; arIn >> value ;
其中,value是所传输的数据
9、摧毁所创建的CSocket、 7、摧毁所创建的CSocket、
CSocketFile 、CArchive 等类的对象 CSocketFile 、CArchive 等类的对象
图4 使用Visual C++ 4.0进行Windows Sockets应用程序开发的基本步骤
四、使用Visual C++ 4.0进行Windows Sockets程序开发的其
它技术要点
针对使用Visual C++ 4.0进行Windows Sockets应用程序开发,需要注意以下几点:
1、 同常规编程一样,无论服务器方还是客户方应用程序都要进行所谓的初始化处理,如图4中Addr、port缺省值的设定等,这部分工作仍可采用消息驱动机制来先期完成。
2、一般情况下,网络通信程序是某应用程序中的一模块。在单独调试网络通信程序时,要尽量与采用该通信模块的其它应用程序开发者约定好,统一采用一种界面形式,即单文档界面SDI、多文档界面MDI和基于对话框界面中的一种(这在使用AppWizard形成项目[Project]文件时有提示),尽管这并非必须,但可使通信模块在移植到所需的应用程序时省时省力,因为Visual C++ 4.0这种可视化语言在给我们提供方便的同时,也给我们带来某些不便,譬如所形成的项目文件中的许多相关文件与所采用的界面形式密切联系,许多消息驱动功能,随所采用的界面形式不同而各异。
当然,也可将通信模块函数化,并形成一个动态连接库文件(DLL文件),供主程序调用。
3、以通信程序作为其中一个模块的应用程序往往不是在等待数据发送或接收完之后再做其它工作,因而在主程序中要采用多线程(Multithreaded)技术。即将数据的发或收,放在一个具有一定优先级(一般宜取较高优先级)的辅助线程中,在数据发或收期间,主程序仍可进行其它工作,譬如利用上一个周期收到的数据绘制曲线 。Visual C++ 4.0中的MFC提供了许多有关启动线程、管理线程、同步化线程、终止线程等功能函数。
4、在许多情况下,要求通信模块应实时地收、发数据。譬如调用之的主程序以0.5秒为一周期,在这段时间内 ,要进行如下工作:接收数据,利用收到的数据进行运算,将运算结果发送到其它计算机节点,周而复始。我们在充分利用Windows Sockets的基于消息的网络事件异步选择机制,用消息来驱动数据的发送和接收的基础上,结合使用其他措施,如将数据的收和发放在高优先级线程,在软件设计上,安排好时序,尽量避免在同一时间内,双方都在向对方发送大量数据的情况发生,保证网络要有足够的带宽等,成功地实现了数据传输的实时性。
主要参考文献:
1、蒋东兴 林鄂华 编著,Windows Sockets网络程序设计指南
清华大学出版社 1996年9月
2、胡道元主编,信息网络系统集成技术
清华大学出版社 1996年3月
3、Microsoft公司,Visual C++ 4.0教程
4、Visual C++ 4.0软件上的在线帮助
文中部分英文字词辨析:
Berkeley、Sun Microsystems、JSB Corporation、FTP software、Microdyne、Microsoft、AppWizard、Multithreaded