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

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。