务器发送服务请求报文,等待并接收应答;继续提出请求......
3、请求结束后关闭通信通道并终止。
2.4 WINDOWS SOCKETS程序设计
2.4.1 WINDOWS SOCKETS API简介
VC++对网络编程的支持有socket支持,
WinInet支持MAPI和ISAPI支持等。
其中,Windows Sockets API是TCP/IP网络环境里,
也是Internet上进行开发最为通用的API。
最早美国加州Berkeley分校在UNIX下为TCP/IP协议开发了一个API,
这个API就是著名的Berkeley Socket接口(套接字)。
在桌面操作系统进入Windows时代后,仍然继承了Socket方法。
在TCP/IP网络通信环境下,Socket数据传输是特殊的I/O,
它也相当于文件描述符具有一个类似于打开文件的函数调用-socket()。
可以这样理解:
Socket实际上是一个通信端点,
通过它用户的Socket程序可以通过网络和其他的Socket应用程序通信。
Socket存在于一个"通信域"(为描述一般的线程如何通过Socket进行通信而引入的抽象概念)里,
并且与另一个域的Socket交换数据。
Socket有三类。
第是SOCK_STREAM(流式),提供面向连接的可靠的通信服务,
比如telnet,http。
第二种是SOCK_DGRAM(数据报),提供无连接不可靠的通信,
比如UDP。
第三种是SOCK_RAW(原始),主要用于协议的开发和测试,
支持通信底层操作比如对IP和ICMP的直接访问。
2.4.1 WINDOWS SOCKETS机制
1、异步选择机制:
WINDOWS SOCKETS 的异步选择函数提供了消息机制的网络事件选择,
当使用它登记网络事件发生时应用程序相应窗口函数将收到一个消息
消息中指示了发生的网络事件以及与事件相关的一些信息。
WINDOWS SOCKETS 提供了一个异步选择函数 WSAAsyncSelect(),
用它来注册应用程序感兴趣的网络事件当这些事件发生时
应用程序相应的窗口函数将收到一个消息。
函数结构如下:
int PASCAL FAR WSAAsyncSelect(SOCKET s,HWND hWnd,unsigned int wMsg,long
lEvent);
参数说明:
hWnd:
窗口句柄
wMsg:
需要发送的消息
lEvent:
事件(以下为事件的内容)
值:
含义:
FD_READ 期望在套接字上收到数据(即读准备好)时接到通知
FD_WRITE 期望在套接字上可发送数据(即写准备好)时接到通知
FD_OOB 期望在套接字上有带外数据到达时接到通知
FD_ACCEPT 期望在套接字上有外来连接时接到通知
FD_CONNECT 期望在套接字连接建立完成时接到通知
FD_CLOSE 期望在套接字关闭时接到通知
例如:
我们要在套接字读准备好或写准备好时接到通知,
语句如下:
rc=WSAAsyncSelect(s,hWnd,wMsg,FD_READ|FD_WRITE);
如果我们需要注销对套接字网络事件的消息发送
只要将 lEvent 设置为0。
2、异步请求函数
在 Berkeley Sockets 中请求服务是阻塞的,
WINDOWS SICKETS 除了支持这一类函数外还增加了相应的异步请求函数(WSAAsyncGetXByY();)。
3、阻塞处理方法
WINDOWS SOCKETS 为了设计当一个应用程序的套接字调用处于阻塞时,
能够放弃CPU让其它应用程序运行它在调用处于阻塞时便进入一个叫"HOOK"的例程
此例程负责接收和分配WINDOWS消息使得其它应用程序仍然能够接收到自己的消息并取得控制权。
WINDOWS 是非抢先的多任务环境,即若一个程序不主动放弃其控制权,
别的程序就不能执行。
因此在设计 WINDOWS SOCKETS 程序时,尽管系统支持阻塞操作,
但还是反对程序员使用该操作。
但由于 SUN 公司下的 Berkeley Sockets 的套接字默认操作是阻塞的,
WINDOWS 作为移植的 SOCKETS 也不可避免对这个操作支持。
在 WINDOWS SOCKETS 设计中,
对于不能立即完成的阻塞操作做如下处理:
DLL初始化→循环操作。
在循环中,它发送任何 WINDOWS 消息,并检查这个 WINDOWS SOCKETS 调用是否完成,
在必要时它可以放弃CPU让其它应用程序执行(当然使用超线程的CPU就不会有这个麻烦了)。
我们可以调用 WSACancelBlockingCall() 函数取消此阻塞操作。
在 WINDOWS SOCKETS 中,有一个默认的阻塞处理例程 BlockingHook() 简单地获取并发送 WINDOWS 消息。
如果要对复杂程序进行处理,WINDOWS SOCKETS 中还有WSASetBlockingHook() 提供用户安装自己的阻塞处理例程能力;与该函数相对应的则是 SWAUnhookBlockingHook(),
它用于删除先前安装的任何阻塞处理例程并重新安装默认的处理例程。
请注意,设计自己的阻塞处理例程时,除了函数WSACancelBlockingHook() 之外,
它不能使用其它的 WINDOWS SOCKETS API 函数。
在处理例程中调用 WSACancelBlockingHook()函数将取消处于阻塞的操作,
它将结束阻塞循环。
4、出错处理
WINDOWS SOCKETS 为了和以后多线程环境(WINDOWS/UNIX)兼容,
它提供了两个出错处理函数来获取和设置当前线程的最近错误号。
(WSAGetLastEror()和WSASetLastError())
5、启动与终止
使用函数 WSAStartup() 和 WSACleanup() 启动和终止套接字。
第三章、网络通信模块分析
3.1网络通信程序设计过程
在调用了Windows sockets 的启动函数WSACleanup()之后才能进行其他的Socket系统调用,
但启动函数WSAStartup()是为了建立与Windows Sockets DLL的连接
因此在VC++6.0所建立工程的工程设置中的连接的库模块必须进行设置
在其中的link栏内的对象/库模块中加入"Ws2_32.lib"
才能真正建立建立与Windows Sockets DLL的连接。
其他的Socket系统调用包括创建Socket、将创建的Socket与本地端口绑定、建立Socket连接服务器、监听是否有连接、请求数据的可控缓冲发送和可控缓冲接收,
到最后关闭Socket。
具体流程图如1所示。
首先在服务器方,利用socket()函数建立流式套接字,
返回套接字号s,接着利用bind()函数将套接字s与本地地址绑定
紧接着利用listen(0函数通知TCP,监听客户方
服务器准备接收连接没有连接的话
服务器方通过closesocket()关闭套接字s,服务结束。
有连接的话,在客户方,通过socket()函数建立流式套接字s,此时在服务器方,
建立连接通过accept()返回得到新的套接字ns,客户方通过connect()将套接字s与远程地址连接,此时服务器方/客户方在ns/s上读/写数据
直到交换完成。
交换完成后,服务器方/客户方关闭套接字ns/s,最后服务器方通过closesocket()关闭最初套接字s,服务结束。
具体设计过程如图1所示,
具体设计代码将会在下面介绍:
图1 面向连接的套接字的系统调用流程图
3.2网络通信程序设计核心代码分析
3.2.1通信设计代码分析
先分析服务器端。
首先定义初始化网络函数,也就是WINDOWS SOCKETS的启动
在所有 WINDOWS SOCKETS 函数中,
只有启动函数 WSAStartup() 和终止函数 WSACleanup() 是必须使用的。
启动函数必须是第一个使用的函数,而且它允许指定 WINDOWS SOCKETS API 的版本,
并获得 SOCKETS的特定的一些技术细节。
本结构如下:
int PASCAL FAR WSAStartup(WORD wVersionRequested, LPWSADATA lpWSAData);
其中 wVersionRequested 保证 SOCKETS 可正常运行的 DLL 版本,
如果不支持则返回错误信息。
设计代码如下,主要是进行 WSAStartup()函数 的调用
WORD wVersionRequested;// 定义版本信息变量
WSADATA wsaData;//定义数据信息变量
int err;//定义错误号变量
wVersionRequested = MAKEWORD(1,1);//给版本信息赋值
err = WSAStartup(wVersionRequested, &wsaData);//给错误信息赋值
if(err!=0)
{
return;//告诉用户找不到合适的版本
}
//确认 WINDOWS SOCKETS DLL 支持 1.1 版本
//DLL 版本可以高于 1.1
//系统返回的版本号始终是最低要求的 1.1,
即应用程序与DLL 中可支持的最低版本号
if(LOBYTE(wsaData.wVersion)!= 1|| HIBYTE(wsaData.wVersion)!=1)
{
WSACleanup();//告诉用户找不到合适的版本
return;
}
//WINDOWS SOCKET
上一篇:
基于VC聊天室的论文
下一篇:
近三年来思想工作小结(德能勤绩廉)