Windows Sockets

     该文在介绍Windows Sockets背景知识的基础上,结合在Win
dows
环境中建立So ckets的过程,重点介绍了Windows Sockets的特点
,
及其基本的结构体和函数;继而结合开发Windows Sockets应用程序
的经验,介绍了Windows Sockets对系统硬软件环境的要求、调试方法
及其在Internet互联联网上的应用。
   
关键词  Sockets  Internet  TCP/IPSocket指一个通信端点,
户的应用程序可以籍助它通过网络与其他Socdets应用程序相互通信
Windows 系统中的Socket则是该环境中的一个通信端点。
   
近年来,鉴于PC机上Windows系统的流行,以及Internet互联网在
全球范围内的广泛使用,很多用户需要在Windows环境中开发可通过互
联网进行通信的应用软件。笔者所在课题组在用Wavelet小波方法对
图像进行实时压缩与传输应用程序的开发中曾采用Windows Socdets
进行数据文件与实时图像经由Internet互联网的传输。本文将根据笔
者的实践对有关内容进行介绍。

   
一、背景知识
   
众所周知,ISO颁布的OSI开放式网络系统互连标准由7层组成,
中第14层用于保证不同格式数据的传输,而第57层则用于保证通
信双方相互间的正确理解。附图给出了Window sSockets的网络层次,
通过与OSI标准对照,可以看出Windows Sockets是处在第4层与第5
的位置上。
    Internet
互联网采用TCP/IP(Transmission Control Protocol/I
nternet Protocol)
协议。从附图可以看出:Windows Sockets正好在
该协议的上面一层。
   
Microsoft公司开发的Windows Socdets API建立了Windows
境与网络之间的编程界面,它以伯克利大学的BSD Sockets的编程模块
为基础,同时含有BSD式的函数(30个左右,其函数名只采用小写英文
字母)和专门为Windows视窗系统扩展的函数(20,其函数名采用大
、小写英文字母混用)
    Windows Sockets API
有适于Windows 3.x和适于Windows NT的两
种版本。两者均含有上述两类函数,并均通过Windows系统中的Messag
e
消息予以驱动。两者不同之处在于:前者是1 6,单进程;而后者是3
2
,可在多线程视窗(Multithreaded Windows)中使用。
   
根据所传输数据类型的不同,Windows Sockets又可分为Stream S
ockets
Datagram So ckets两种类型。前者对应不按记录定界的数
据字节流,使用TCP对应的Internet互联网地址,双方互相连接,因而它
可保证按正确的顺序,单一和可靠地传输数据;后者对应记录型数据流
,
使用UDP对应的Internet互联网地址,双方不需直连,按固定的最大长
度进行传输,它不能保证按顺序传输数据,并可能出现数据的重复,
者丢失。附图 Windows SocketsOSI标准网络层次结构

   
二、建立与运作过程
   
在实际应用中我们至少要涉及两个应用程序的Socket(一般各自
位于连在Internet互联网上的两台微机上,分别起Server服务器和Cli
ent
客户机的作用,本文分别简称为"服务器So cket/"客户机Socket
")
相互交换信息与传输数据,因此需要在服务器与客户机的应用程序
中分别建立Socket,然后建立相互之间的连接和通信。实际上是同一
程序在服务器和客户机双方分别执行。

    1.Windows Socdet
的初始化
   
Windows环境中建立Socket的第一步是初始化应用程序中的Soc
ket,
即按给定的Socke t版本,WSAData结构体变量中各成员的值来
初始化Socket.
    WSAData
结构体含有包括Socket版本号、系统状态等信息在内的7
个成员,Windows Sock ets的初始化信息就存储在其对应的变量中。
一般可通过调用WSAStartup()函数(Socket版本号和该结构体变量
地址两个参数)来完成对Socket的初始化。
   
如上所述,我们必须对服务器Socket和客户机Socket分别进行初
始化。用户在实际编程中常采用的对Socket的初始化方法有两种:
于就用单一固定在Socket上的程序可采用在打开应用程序窗口后即自
动驱动message消息的方法;对于具有多个应用模块的应用程序最好采
用菜单命令驱动message消息的方法。笔者采用后者。
    2.Socket
的生成
   
在应用程序完成对Socdet的初始化后,即可调用Socket()函数(
有网络地址类型、传输数据类型和网络协议3个参数)生成Socket,
函数返回所生成Socket的句柄。
   
在该函数的3个参数中:
    (1)
网络地址类型可以取AF-INET(Address Family InterNET的缩
)AF-UNSPEC(Addr ess Family-UNSPECified的缩写)
    (2)
传输数据类型如前所述分别为SOCK-STREAMSOCK-DGRAM(Dat
aGRAM
的缩写),为保证数据可靠的传送,笔者采用的前一种;
    (3)
缺省的协议就是TCP/IP;对应参量值取0;如果网络地址类型取
AF-UNSPEC,
则此处必须指明相应的协议。

    3.
将服务器地址赋予服务器Socket,然后使之进入Listen等待连
接的监听状态……
   
在应用程序完成对服务器Socket的初始化和生成Socket,一般
需要用服务器的地址先对SOCKADDR-IN结构体变量赋值,然后调用bind
()
函数将服务器地址赋予服务器Socket(SO CKADDR-IN结构体变量
值转给SOCKADDR结构体变量),再调用Listen()函数让服务器Socket
Listen"等待连接"的监听状态……
    (1)
对服务器SocketSOCKADDR-IN结构体变量赋值
    SOCKADDR-IN(SOCKet ADDRess-InterNet
的缩写)只适用于Intern
et
地址类型,是一种特殊的Socket地址结构体,它含有Internet Socke
t
地址类型、IP端口号、IP地址、填补字节( 以保证与SOCKADDR结构
体总长度相同)4个成员,它用于还没有被赋予相应主机地址的Socket
;
由于它与下面要介绍的SOCKADDR结构体具有相同的总长度,因此SOCK
ADDR-IN
结构体变量的值可通过bind()connect()accept()函数直
接转给对应SocketSOCKADDR结构体变量。
    SOCKADDR-IN
结构体变量的第一个参量对于Internet互联网可取
定为AF-INET;第二个参量可由SocKet的最终用户通过对话框输入,
12;第三个参量对于Server服务器一方可取一待定值INADDR-ANY;
四个参量无需赋值。
    (2)
将服务器地址赋予服务器Socket
   
调到bind()函数(含服务器Socket句柄、服务器的SOCKADDR结构
体变量及其长度第三个参量)将服务器对应的SOCKADDR-IN结构体变量
值直接转给服务器的SOCKADDR结构体变量,从而将服务器地址赋予其S
ocket.
    SOCKADDR
结构体是Socket的一般地址结构,它用于存储参与Windo
ws Sockets
通信的计算机的IP地址,它含有Socket采用的地址类型和
具体地址两个成员。如上所述,它与SOCKADDR- IN结构体具有相同的
总长度,SOCKADDR-IN结构体变量的地址值可由bind()connect()a
c cept()
函数直接转给对应SocketSOCKADDR结构体变量,从而实现
将地址赋予Socket.
    (3)
服务器Socket进入Listen"等待连接"的监听状态
   
调用Lister()函数(含服务器Socket句柄和最大监听态值两个参
),让服务器Socket进入"等待连接"的监听状态:等待来自客户机Soc
ket
connect"要求连接"信号。
    (4)
服务器Socket在收到客户机Socket发来的connect"要求连接"
信号后,发回accept"接受连接"信号。
   
处于监听状态的服务器Socket一旦收到客户机Socket发来的conn
ect"
要求连接"信号后,立即调用accept()函数(含处于监听态的服务
Socket句柄、发出conncet"要求连接"信号的客户机的SOCKADDR
构体变量地址及其长度等3个参量)将客户机对应的SOCKADDR-IN结构
体变量值转给服务器的SOCKADDR结构体变量,该函数返回一个新的Soc
ket
句柄,从而在服务器应用程序中产生一个新的被赋予已连客户机地
址的Socket,同时发回accept"接受连接"的信号。
    (5)
连接实现
   
一旦客户机Socket收到服务器Socket发来的accept"接受连接"
号后,连接实现。
    4.
将服务器地址赋予客户机Socket,然后使之发出connect"要求
连接"信号,在接到服务器Socketaccept"接受连接"的信号后,连接
实现。在应用程序完成对客户机Socket的初始化和生成客户机Socket
,一般则需要用欲连服务器的地址先对SOCKADDR-IN结构体变量赋值
,
然后调用connect()函数将服务器地址赋于客户机Socket(SOCKADD
R-IN
结构体变量转给S OCKADDR结构体变量),之后由客户机Socket
服务器Socket发出connect"要求连接"信号,在客户机Socket接到由服
务器Socket发回的accept"接受连接"的信号后,即双方实现连接。
    (1)
对客户机SocketSOCKADDR-IN结构体变量赋值
    SOCKADDR-IN
结构体变量的第一个参量对于Internet互联网仍可
取定为AF-INET;第二个参量仍由Socket的最终用户通过对话框输入(
应同于服务器Socket,例如12);第三个参量则先由Socket的最终用户
通过对话框输欲连服务器的名字或地址(显然名字较为方便)然后利用
g ethostbyname()
gethostbyaddr()函然将名字或地址转换为指向h
ostent
结构体变量的指针(hostent结构体含有主机名、替换名、地址
类型、地址长度、地址5个成员),再将hostent结构体变量的地址成员
值复制到SOCKADDR-IN结构体变量上;第四个参量仍无需赋值。
    (2)
将服务器地址赋予客户机Socket,然后使之发出connect"要求
连接"信号
   
调用connect()函数(含申请连接的客户机Socket句柄、欲连服务
器的SOCKADDR结构体变量地址及其长度等3个参量)将服务器对应的SO
CKADDR-IN
结构体变量值转给客户机的SOCKAD DR结构体变量,从而将
服务器地址赋予客户机Socket;之后由客户机Socket向服务器Socket
发出connect"要求连接"信号。
    (3)
实现连接
   
一旦客户机Socket收到来自服务器Socket发回的accept"接受连
"的信号,则表示服务器与客户机双方的Sockets已经通过Internet
互联网实现连接。
    5.
已连通双方Sockets之间的数据通信
   
当服务器与客户机双方的Sockets通过Internet网实现连接后,
一方均可通过互联网向对方发送,也可以接收对方发来的数据。
    (1)
数据的发送
   
相互连接的Sockets任一方均可调用send()函数(含发送目标方的
Socket
句柄、要传输数据所在缓冲区地址、数据长度、调用标志等4
个参量)向对方发送各种类型的数据,发送成功后返回所发送的字符数

    (2)
数据的接收
   
相互连接的Sockets双方均应可调用WSASSyncSelect()函数等待
来自网络的FD-READ事件通知,然后驱动message消息接收对方Socket
发来的数据。
    (1)
调用WSASSyncSelect()函数(含应收到事件通知的Socket句柄
、应收到message自己的窗口句柄、应收到的message消息名、事件通
知类型等4个参量)等待来自网络的FD-READ事件通知,驱动相应的mesa
age
消息。
    (2)
在被驱动的message消息中调用recv()函数(含接收方的Socke
t
句柄、放置所接收数据的缓冲区地址、数据长度、调用标志等4个参
)接收对方Socket传来的数据。
    6.Socket
的关闭
   
相互连接的Sockets任一方均可调用WSASSyncSelect()函数(将后
两个参量置0)来中止S ocket等待网络事件通知,再调用无参WSACIean
up()
函数关闭Socket.而相互连接的Sockets任一方关闭的Socket,
均会向对方发出FD-CLOSE事件通知,并驱动message消息通知用户。
   
三、编程特点

    1.message
消息驱动
    Windows
视窗系统采用meassge消息驱动的工作方式,Windows Soc
kets
除了采用命令菜单驱动message消息外,还需采用专门用于接收网
络事件通知与驱动message消息的函数WSASSy ncSelect()
   
上述Windows Sockets的建立、互连与数据发送过程均可按模块
进行组合,然后分别放在相应的命令菜单驱动的message消息中,而互
连后接收数据的过程则应放在由WSASSyncSelec t()函数驱动的messa
ge
消息中。一般在WM-COMMAND所属的菜单驱动的message中至少应含
IDM-LTSTEN(等待连接)IDM-CONNECT(要求连接)IDM-SEND(发送
数据)IDM-CLOSE(关闭Socket)这几个基本消息;WSASSyncSelect(
)
函数驱动的message中至少应含有WM-READ(接收数据)消息。这些消
息的名字可由用户自己确定。
   
上述互连过程采用的是Blocking模式,即服务器在调用Listen()
函数后陷入"死等"来自客户机Socketconnect"请求连接"信号的Blo
king
状态(此时用户不能激活相应应用程序窗口的命令菜单)
   
鉴于WSASSyncSelect()函数可以接收除FD-READFD-CLOSE以外
的其它事件通知,:FD -ACCEPT("要求连接"的事件通知)FD-CONNE
CT("
接受连接"的事件通知),因此我们也可以在服务器Socket和客
户机Socket的互连过程中,在服务器一方进入监听状态后,调用该函数
来等待FD-ACCEPT"要求连接"的事件通知,并驱动WM-ACCEPT"接受连接
,
准备通信……"的消息; 同样,我们也可以客户机一方在发出connect
"
要求连接"信号后,调用此函数来等待FD-CONNE CT"接受连接"的事件
通知,并驱动WM-CONNECTED"连接成功,准备通信……"的消息。
   
在服务器与客户机的Sockets互连过程中调用WSASSyncSelect()
函数还可以避免服务器在调用Listen()函数后的Bloking状态转为Non
-Blocking
状态,而让用户可以在相应窗口中进行其它操作;但它将增
加程序中的message消息数量,不利于独立的模块化DLL动态连接库的
建立。

    2.DLL
动态连接库文件的建立与应用
   
考虑到Socket经常是作为Windows视窗应用程序中的一个功能模
,因此应尽可能将上述Socket的建立与运作过程函数化,并作为主程
序文件的DDL动态连接库予以使用。
   
DLL动态连接库文件的生成过程中,首先应正确处理主程序与DL
L
DLL内部各函数之间的参数传递;其次是应将命令菜单、人机对话
框等资源放在主程序中;由函数WSASSyncSelec t()驱动的message
息不能放到DLL,而应放到主程序中(但可将该消息的具体内容函数
,放到DLL)

    3.
多线程视窗(Multithreaded Windows Processes)
   
Windows  NT视窗系统中可以实现多线程,例如,我们可以在服
务器一方进入监听状态后,通过调用beginthread()函数来生成新的线
,在此线程中调用指定的自定义函数,而在该函数中调用accept()
recv()
函数分别实现接收来自客户机Socketconnect"要求连接"
,发回accept"接受连接"信号,和接收客户机发来的数据。
   
四、对环境的要求与调试

    1.
对运行环境的要求
    Windows Sockets
对运行环境的要求不是很高,一般宜采用Pentiu
m
微机、Windows NT视窗系统,此外系统还应装有下列软硬件。
    (1)Windows Socket
    Windows NT
视窗系统已含有Windows Sockets软件系统,无须再进
行安装;对于Windows 3.X版则需要单独进行安装。
    (2)
网卡
   
由于TCP/IP可以工作在任何网络上,Windows Sockets是在TCP/
IP
的上层,因此它也可以用在各种不同的网络上,即它对具体采用哪一
种网卡没有特殊的要求,当然在可能的条件下应在同一网络中采用传
输速率较高的网卡。
   
笔者采用了使用PCI局域总线的CWL9510 PCI Ethernet网卡,其速
率为20/10Mbps.在安装网卡前应从网络管理员处取得分配给该微机的
名字、IP地址、Subnet maskGatewayDom ain Suffix等参数。在
主板上插入网卡后即可启动视窗,依次揿击MainControl PanelN
etwork
图标打开Network安装窗口,再揿击Add Adapter按钮添入所用
的网卡,再调用随卡带来的安装程序进行安装。安装过程中按屏幕提
示在对话框中正确填入上述参数即可。
    (3)HOSTS
文件
   
为了帮助用户记住在Windows Sockets正常工作时所需要的主机
名与IP地址,用户可以在硬盘C的指定目录中装入供TCP/TP使用的文件
名为HOSTS的文本文件。笔者采用了Windows N T(V3.51)系统,该文件
放于C:/WINNT35/SYSTEM32/DRIVERS/ETC子目录中。文件的每一行由
用空格分开的3列栏目组成,依次给出Windows Sockets可能涉及的主
IP地址、主机名和由符号#引导的注释。
   
一个典型的例子如下:
    127.0.0.1
    Localhost#Local host
    128.146.155.114 robin.eng.ohio-state.edu#Server host
    128.146.155.112 gull.eng.ohio-state.edu#Client host
    2.
调试
   
笔者在MS Visual C++V4.0 MS Developer Studio环境中对Win
dows Sockets DLL
及应用主程序进行编辑和Build装配(含编译和联接
)

   
在应用程序Sockets的调试与实际应用过程中,均可根据需要在程
序中添加必要的人机交互对话框或信息框,以直观得到Sockets运行过
程中各阶段的结果。
   
在对DLL进行Build,应在缺省的库文件基础上增加wsock32.lib
libcmtd.liblibc d.lib三个库文件模块;而在对主程序进行Buil
d
,还应增加所生成的相应DLL*.obj目标文件模块,以及设备相应
模块文件的搜索路径。
   
Windows Sockets的调试阶段,可在一台计算机上同时打开两个
Windows Socket
应用程序窗口进行试运行,待正常后再在两台不同机
器上进行实验。即使计算机没有入网,也可以采用localhost的名字和
127.0.0.1
IP地址进行应用程序Sockets的单机试调。
   
五、在Internet网络中的实际应用
   
虽然目前已有WWW浏览器、FTPInternet互联网的应用工具,
以下装网上的信息,或实现网上工作站间的数据与文件传输,但是Wind
ows Sockets
则可方便地在用户自己设计的Win dwos视窗应用程序中
通过Internet互联网传输数据,由于互联网的传输速度可以高达数十
兆到数百兆bps,因此除了可以传递一般的文字、图形、声音等数据文
件外,还可以用来传递实时的图像数据。
    send()
函数可由用户给定所发送数据祯(Frame)的长度,如果数据
祯较长(KB以上),在实际传输前,Socket要先将数据祯重新分成若干
个数据包(Packets),再分别顺序传输,也就是说只要该祯数据没有接
收完,接收一方Socket将不断驱动WM-READ消息直到接收完该祯数据。
因此,应根据这一特点对所接收的数据进行相应处理。在实时传输时,
还应由接收一方对传输过程控制……
   
:作者简介
   
裴纯礼,北京师范大学计算中心副主任、副教授,同时兼任国家教
委高教司"全国普通高校文科专业计算机基础教育指导组"副组长、国
家教委师范司"全国高等师范学校计算机教育指导组"委员、北京市教
委大学处"北京地区普通高校计算机基础教育评价与指导委员会"委员
等职,多年从事计算机基础教学工作,已出版有关计算机基础教材、著
200余万字,正式发表十余篇论文。19965月赴美进修,从事计算机
网络通信与Wavelet的研究工作,现为美国俄亥俄州立大学电气工程系
高级访问学者。热点技术

 

你可能感兴趣的:(brew,buiw,uiOne,bmp,嵌入式开发,browser,windows,platform)