C语言实的串行通信接口程序
摘 要 该文介绍了Sockets通信原理,从程序员角度着重讨论了Windows Sockets为支持异步通信对Sockets的功能扩充,并给出了应用Windows Sockets实现网络实时通信的一个程序实例。关
IBM公司于1994年4月推出的TCP/IP for DOS V2.1.1所提供的开发软件包Programmers Tool Kit不仅带有DOS下网络编程接口,而且提供了Windows下网络异步通信接口WINSOCK。
一、Socket网络编程原理Socket是BSD UNIX提供的网络应用编程接口,它采用客户机/服务器的通信机制,使网络客户机方和服务器方通过Socket实现网络之间的连接和数据交换。Socket提供了一系列的系统调用,使用这些系统调用可以实现TCP、UDP、ICMP和IP等多种网络协议之间的通信。
Socket有三种主要类型:stream sockets,datagram sockets和raw sockets。Streamsocket接口定义了一种可靠的面向连接的服务,它实现了无差错无重复的顺序数据传输。它通过内置的流量控制解决了数据的拥塞,应用程序可以发送任意长度的数据,将数据当作字节流。Datagram socket接口定义了一种无连接的服务,数据通过相互独立的包进行传输,包的传输是无序的,并且不保证是否出错、丢失和重复。包长度是有限的(隐含长度为8192字节,最大长度可设为32768字节)。Raw socket接口允许对低层协议如IP和ICMP的直接存取,它主要用于新的网络协议实现的测试等。
下面我们通过一个面向连接的传输发生的典型情况来说明socket网络通信的实现。
由图我们可以看出,客户机和服务器的关系不是对称的。服务器首先启动,然后在某一时间启动客户机与服务器建立连接。服务器和客户机开始都必须用调用socket ()建立一个套接字(socket),然后服务器调用bind()将套接字与一个本地网络地址捆扎在一起,再用调用listen()使套接字处于一种被动的准备接收状态,同时规定它的请求队列长度,之后服务器就可以调用accept()来接收连接了。客户机在建立套接字之后,便可以通过调用connect()和服务器建立连接。连接建立后,客户机和服务器之间就可以通过连接发送和接收数据(调用read()和write())。最后,待数据传送结束,双方调用close()关闭套接字。
@@T8S10700.GIF;面向连接的协议实现的Socket调用图@@
二、WINSOCK对Socket的扩充
BSD Socket支持阻塞(blocking)和非阻塞(non-blocking)两种工作方式。在阻塞方式下,connect()、accept()、read()和recv()等调用在执行时都处于阻塞状态直到它成功或出错返回。在非阻塞方式下,这些调用是立即返回的,但是它们是否完成得靠查询才能知道。对于Windows这种非抢先多任务操作系统来说,这两种工作方式都是难以接受的,为此,WINSOCK在尽量与BSD Socket保持一致的前提下,又对它作了必要的扩充。
WINSOCK对BSD Socket的扩充主要是在基于消息、对网络事件的异步存取接口上。表1列出了WINSOCK扩充的函数功能。
从表1可以看出,WINSOCK的扩充功能可以分为如下几类。
(1)异步选择机制
异步选择函数WSAAsyncSelect()允许应用程序提名一个或多个感兴趣的网络事件,所有非阻塞的网络I/O例程(如send()和resv()),不管它是已经使用还是即将使用,都可作为WSAAsyncSelect()函数选择的候选。当被提名的网络事件发生时,Windows应用程序的窗口函数将收到一个消息,消息附带的参数指示被提名过的某一网络事件。
@@T8S10701.GIF;表1 WINSOCK扩充函数功能@@
(2)异步请求例程
异步请求例程允许应用程序用异步方式获取请求的信息,如WSAAsyncGetXByY()类函数允许用户请求异步服务,这些功能在使用标准Berkeley函数时是阻塞的。函数WSACancelAsyncRequest()允许用户终止一个正在执行的异步请求。
(3)阻塞处理方法
WINSOCK在调用处于阻塞时进入一个叫“Hook”的例程,它负责处理Windows消息,使得Windows的消息循环能够继续。WINSOCK还提供了两个函数(WSASetBlockingHook()和WSAUnhookBlockingHook())让用户能够设置和取消自己的阻塞处理例程。另外,函数WSAIsBlocking()可以检测调用是否阻塞,函数WSACancelBlockingCall()可以取消一个阻塞的调用。
(4)出错处理
为了和以后的多线索环境(如Windows NT)兼容,WINSOCK提供了两个出错处理函数WSAGetLastError()和WSASetLastError()来获取和设置本线索的最近错误号。
(5)启动与终止
WINSOCK的应用程序在使用上述WINSOCK函数前,必须先调用WSAStartup()函数对Windows Sockets DLL进行初始化,以协商WINSOCK的版本支持,并分配必要的资源。在应用程序退出之前,应该先调用函数WSACleanup()终止对Windows Sockets DLL的使用,并释放资源,以利下一次使用。
在这些函数中,实现Windows网络实时通信的关键是异步选择函数WSAAsyncSelect()的使用,其原型如下:int PASCAL FAR WSAAsyncSelect(SOCKET s,HWND hWnd, unsigned intwMsg, long lEvent);它请求Windows Sockets DLL在检测到在套接字s上发生的lEvent事件时,向窗口hWnd发送一个消息wMsg。它自动地设置套接字s处于非阻塞工作方式。参数lEvent由表2所列事件的一个或多个组成。
@@T8S10702.GIF;表2 异步选择网络事件@@
例如,我们要在套接字s读准备好或写准备好时接到通知,可以使
Tags:
作者:佚名评论内容只代表网友观点,与本站立场无关!
评论摘要(共 0 条,得分 0 分,平均 0 分)
查看完整评论