个人专长: 胡扯,瞎掰,软件测试稍微靠谱 (空间无原创东西,全部来源网络,如有侵权请联系本人)

Winsocket原理

上一篇 / 下一篇  2008-06-05 17:11:04 / 个人分类:loadrunner

 

一、客户机/服务器模式
TCP/IP网络中两个进程间的相互作用的主机模式是客户机/服务器模式(Client/Server model)。该模式的建立基于以下两点:1、非对等作用;2、通信完全是异步的。客户机/服务器模式在操作过程中采取的是主动请示方式:

首先服务器方要先启动,并根据请示提供相应服务:(过程如下)
1
、打开一通信通道并告知本地主机,它愿意在某一个公认地址上接收客户请求。
2
、等待客户请求到达该端口。
3
、接收到重复服务请求,处理该请求并发送应答信号。
4
、返回第二步,等待另一客户请求
5
、关闭服务器。
客户方:
1
、打开一通信通道,并连接到服务器所在主机的特定端口。
2
、向服务器发送服务请求报文,等待并接收应答;继续提出请求……
3
、请求结束后关闭通信通道并终止。

二、基本套接字
为了更好说明套接字编程原理,给出几个基本的套接字,在以后的篇幅中会给出更详细的使用说明。
1
、创建套接字——socket()
功能:使用前创建一个新的套接字
格式:SOCKET PASCAL FAR socket(int af,int type,int procotol);
参数:af:通信发生的区域
type:
要建立的套接字类型
procotol:
使用的特定协议

2
、指定本地地址——bind()
功能:将套接字地址与所创建的套接字号联系起来。
格式:int PASCAL FAR bind(SOCKET s,const struct sockaddr FAR * name,int namelen);
参数:s:是由socket()调用返回的并且未作连接的套接字描述符(套接字号)。
其它:没有错误,bind()返回0,否则SOCKET_ERROR
地址结构说明:
struct sockaddr_in
{
short sin_family;//AF_INET
u_short sin_port;//16
位端口号,网络字节顺序
struct in_addr sin_addr;//32
IP地址,网络字节顺序
char sin_zero[8];//
保留
}

3
、建立套接字连接——connect()accept()
功能:共同完成连接工作
格式:int PASCAL FAR connect(SOCKET s,const struct sockaddr FAR * name,int namelen);
SOCKET PASCAL FAR accept(SOCKET s,struct sockaddr FAR * name,int FAR * addrlen);
参数:同上

4
、监听连接——listen()
功能:用于面向连接服务器,表明它愿意接收连接。
格式:int PASCAL FAR listen(SOCKET s, int backlog);

5
、数据传输——send()recv()
功能:数据的发送与接收
格式:int PASCAL FAR send(SOCKET s,const char FAR * buf,int len,int flags);
int PASCAL FAR recv(SOCKET s,const char FAR * buf,int len,int flags);
参数:buf:指向存有传输数据的缓冲区的指针。

6、多路复用——select()
功能:用来检测一个或多个套接字状态。
格式:int PASCAL FAR select(int nfds,fd_set FAR * readfds,fd_set FAR * writefds,
fd_set FAR * exceptfds,const struct timeval FAR * timeout);
参数:readfds:指向要做读检测的指针
writefds:
指向要做写检测的指针
exceptfds:
指向要检测是否出错的指针
timeout:
最大等待时间

7、关闭套接字——closesocket()
功能:关闭套接字s
格式:BOOL PASCAL FAR closesocket(SOCKET s);


三、典型过程图
2.1
面向连接的套接字的系统调用时序图



2.2无连接协议的套接字调用时序图



2.3
面向连接的应用程序流程图

 

四、WinSock简介

WindowsSockets是从Berkeley Sockets扩展而来的,其在继承Berkeley Sockets的基础上,又进行了新的扩充。这些扩充主要是提供了一些异步函数,并增加了符合WINDOWS消息驱动特性的网络事件异步选择机制。

Windows Sockets由两部分组成:开发组件和运行组件。

开发组件:Windows Sockets实现文档、应用程序接口(API)引入库和一些头文件。

运行组件:Windows Sockets应用程序接口的动态链接库(WINSOCK.DLL)

 

五、WinSock主要扩充说明

  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()提供用户安装自己的阻塞处理例程能力;与该函数相对应的则是WSAUnhookBlockingHook(),它用于删除先前安装的任何阻塞处理例程,并重新安装默认的处理例程。请注意,设计自己的阻塞处理例程时,除了函数WSACancelBlockingHook()之外,它不能使用其它的Windows Sockets API函数。在处理例程中调用WSACancelBlockingHook()函数将取消处于阻塞的操作,它将结束阻塞循环。

4、出错处理

Windows Sockets为了和以后多线程环境(WINDOWS/UNIX)兼容,它提供了两个出错处理函数来获取和设置当前线程的最近错误号。(WSAGetLastEror()WSASetLastError()

5、启动与终止

使用函数WSAStartup()WSACleanup()启动和终止套接字。

 

六、Windows Sockets网络程序设计核心

我们终于可以开始真正的Windows Sockets网络程序设计了。不过我们还是先看一看每个Windows Sockets网络程序都要涉及的内容。让我们一步步慢慢走。

1、启动与终止

在所有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 Sockets DLL被进程接受,可以进入下一步操作

关闭函数使用时,任何打开并已连接的SOCK_STREAM套接字被复位,但那些已由closesocket()函数关闭的但仍有未发送数据的套接字不受影响,未发送的数据仍将被发送。程序运行时可能会多次调用WSAStartuo()函数,但必须保证每次调用时的wVersionRequested的值是相同的。

2、异步请求服务

Windows Sockets除支持Berkeley Sockets中同步请求,还增加了了一类异步请求服务函数WSAAsyncGerXByY()。该函数是阻塞请求函数的异步版本。应用程序调用它时,由Windows Sockets DLL初始化这一操作并返回调用者,此函数返回一个异步句柄,用来标识这个操作。当结果存储在调用者提供的缓冲区,并且发送一个消息到应用程序相应窗口。常用结构如下:

HANDLE taskHnd;

char hostname="rs6000";

taskHnd = WSAAsyncBetHostByName(hWnd,wMsg,hostname,buf,buflen); 

需要注意的是,由于Windows的内存对像可以设置为可移动和可丢弃,因此在操作内存对象是,必须保证WIindows Sockets DLL对象是可用的。

3、异步数据传输

使用send()sendto()函数来发送数据,使用recv()recvfrom()来接收数据。Windows Sockets不鼓励用户使用阻塞方式传输数据,因为那样可能会阻塞整个Windows环境。下面我们看一个异步数据传输实例:

假设套接字s在连接建立后,已经使用了函数WSAAsyncSelect()在其上注册了网络事件FD_READFD_WRITE,并且wMsg值为UM_SOCK,那么我们可以在Windows消息循环中增加如下的分支语句:

case UM_SOCK:

  switch(lParam)

  {

  case FD_READ:

    len = recv(wParam,lpBuffer,length,0);

    break;

  case FD_WRITE:

    while(send(wParam,lpBuffer,len,0)!=SOCKET_ERROR)

    break;

  }

break;

4、出错处理

Windows提供了一个函数来获取最近的错误码WSAGetLastError(),推荐的编写方式如下:

len = send (s,lpBuffer,len,0);

if((len==SOCKET_ERROR)&&(WSAGetLastError()==WSAWOULDBLOCK)){...}

 

 


TAG: loadrunner

 

评分:0

我来说两句

日历

« 2024-05-02  
   1234
567891011
12131415161718
19202122232425
262728293031 

数据统计

  • 访问量: 52638
  • 日志数: 84
  • 文件数: 3
  • 建立时间: 2008-04-02
  • 更新时间: 2009-03-23

RSS订阅

Open Toolbar