热爱测试,主要研究性能测试和自动化测试方面的技术,希望与同样对测试有热情的你一同进步成长

Winsocket原理(转)

上一篇 / 下一篇  2007-12-17 14:31:06 / 个人分类:网络知识

51Testing软件测试网q8Id+I6r Q.}c5ITX

 转自:http://www.sswowo.com/article.asp?id=612

8B}#|2_gdB rA g0

2M^am1p.\3G f{0作者:冰点工作小鹰51Testing软件测试网IZj'I+D

C:OA{+z2SM0一、客户机/服务器模式51Testing软件测试网;@&N_ {w@6isQ
在TCP/IP网络中两个进程间的相互作用的主机模式是客户机/服务器模式(Client/Server model)。该模式的建立基于以下两点:1、非对等作用;2、通信完全是异步的。客户机/服务器模式在操作过程中采取的是主动请示方式:51Testing软件测试网,aUsEB3zY]jp*w
51Testing软件测试网"]0t\5_*UMEY
首先服务器方要先启动,并根据请示提供相应服务:(过程如下)
| H ]*L`oAPW01、打开一通信通道并告知本地主机,它愿意在某一个公认地址上接收客户请求。51Testing软件测试网1J/J,{/UK
2、等待客户请求到达该端口。
g l{7N:?7I;t(eme03、接收到重复服务请求,处理该请求并发送应答信号。
J1o fsv cpp:G0b04、返回第二步,等待另一客户请求
eT~|i ?QeQKP05、关闭服务器。51Testing软件测试网 CitANu6P
客户方:51Testing软件测试网3bBcF.a)B-VZ
1、打开一通信通道,并连接到服务器所在主机的特定端口。
il*B9qK'J-m02、向服务器发送服务请求报文,等待并接收应答;继续提出请求……
K0V*u'sf03、请求结束后关闭通信通道并终止。51Testing软件测试网7H&_ yRG/`'wn

+|/}p"J{'i0二、基本套接字51Testing软件测试网/o'P H8J @lF2h$Eh
为了更好说明套接字编程原理,给出几个基本的套接字,在以后的篇幅中会给出更详细的使用说明。
*P*t#h#[D0h)o8~2M01、创建套接字——socket()
m_v-H3O%s3BND L0功能:使用前创建一个新的套接字51Testing软件测试网7t?ln3l,L1~B1~cov
格式:SOCKET PASCAL FAR socket(int af,int type,int procotol);
E y+\)oO2d*Qc0参数:af: 通信发生的区域51Testing软件测试网S{O U:Oy+^]/zS
type: 要建立的套接字类型
@h)K.k2Oi/H/tP"@0procotol: 使用的特定协议51Testing软件测试网hgz n:Nb,PIG

-ld MAzI02、指定本地地址——bind()51Testing软件测试网n.Dm-Bi*J
功能:将套接字地址与所创建的套接字号联系起来。51Testing软件测试网F/p1c V ^
格式:int PASCAL FAR bind(SOCKET s,const struct sockaddr FAR * name,int namelen);
z*Y5^(nH5| G0参数:s: 是由socket()调用返回的并且未作连接的套接字描述符(套接字号)。51Testing软件测试网:^S],YnO}a#xzgL
其它:没有错误,bind()返回0,否则SOCKET_ERROR51Testing软件测试网`4a,zVg1rs
地址结构说明:51Testing软件测试网2^s2T|b"?'o:l\0i
struct sockaddr_in51Testing软件测试网[U"[2S;q!rbt
{
HV q%g FK,sSG)w0short sin_family;//AF_INET51Testing软件测试网 PqU:\'k#nR6nG
u_short sin_port;//16位端口号,网络字节顺序51Testing软件测试网mY:aPX
struct in_addr sin_addr;//32位IP地址,网络字节顺序
4bO'~+O@+gN,F I0char sin_zero[8];//保留
'QAI1^`U1l_)f0}
u8N?.?%c~n n0
"Tl S waE03、建立套接字连接——connect()和accept()
{ \f&y HV hAi?;f0功能:共同完成连接工作51Testing软件测试网w6BJ$Y&n7s%\:ad B6{
格式:int PASCAL FAR connect(SOCKET s,const struct sockaddr FAR * name,int namelen);
$s ?/k/^&is0SOCKET PASCAL FAR accept(SOCKET s,struct sockaddr FAR * name,int FAR * addrlen);
Q0s$pSO{6}5Dk%M0参数:同上51Testing软件测试网!_Bk%u%g|s
51Testing软件测试网s0x1RaU^/~c
4、监听连接——listen()51Testing软件测试网.miHkoz
功能:用于面向连接服务器,表明它愿意接收连接。51Testing软件测试网] f{ _,W
格式:int PASCAL FAR listen(SOCKET s, int backlog);51Testing软件测试网&Z3_7|r*K
51Testing软件测试网D G@(Ef)Ya
5、数据传输——send()与recv()51Testing软件测试网7xv9zk4I.U!{%`+u
功能:数据的发送与接收
Q'y*u&WL6^0格式:int PASCAL FAR send(SOCKET s,const char FAR * buf,int len,int flags);51Testing软件测试网lS$x[h&O
int PASCAL FAR recv(SOCKET s,const char FAR * buf,int len,int flags);
S-o'A(k_ Z0o%@0参数:buf:指向存有传输数据的缓冲区的指针。

cXM c-|?c051Testing软件测试网z!qL!bk _0na;{cq

6、多路复用——select()51Testing软件测试网 DQt1u8Gi%V1r
功能:用来检测一个或多个套接字状态。
;lK h&b W4z6} _#bd0格式:int PASCAL FAR select(int nfds,fd_set FAR * readfds,fd_set FAR * writefds,
k1gU%p6Wn#c&h K0fd_set FAR * exceptfds,const struct timeval FAR * timeout);51Testing软件测试网.Mb3Kb\M
参数:readfds:指向要做读检测的指针
&e d NzWh2P.e0writefds:指向要做写检测的指针51Testing软件测试网`_F~-r0V V Fzo
exceptfds:指向要检测是否出错的指针
(`A#HC3t'PX f/?6Vi0timeout:最大等待时间51Testing软件测试网 ~)b+n$v/t J)a

51Testing软件测试网3L9ih'YTl*E

7、关闭套接字——closesocket()
V(k1pH}3h6j*x;E!Ev0功能:关闭套接字s51Testing软件测试网]'d*g9B!`+ga
格式:BOOL PASCAL FAR closesocket(SOCKET s);

d |0yS,I A Y051Testing软件测试网/v6V!v~0t l0T7HE/M

51Testing软件测试网 MQ+Wg*Wz!G1C.v
三、典型过程图51Testing软件测试网 n\)`J!v7VE N|V7}
2.1 面向连接的套接字的系统调用时序图
hKY,|$Qs0V%]0
,C{Jz#k:L8RzuJ CJHF051Testing软件测试网"w,y%w@h!vz~:QC
51Testing软件测试网*jmHF2nJ;^!]6F
2.2 无连接协议的套接字调用时序图
.E;N P-vOXk051Testing软件测试网Ak)p4@x7_
51Testing软件测试网FSAh'b
51Testing软件测试网:C:k8ICL!zc[D
2.3 面向连接的应用程序流程图
j+z N+M$OlW9e5n+lJ0 
)Q,[H2f1Rn0补充,转自:http://blog.csdn.net/lost_hunter/archive/2007/04/03/1551055.aspx

2Aw8V8O ~0

四、WinSock简介51Testing软件测试网'Y$d1vi.tX{gy5[dc

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

Windows Sockets由两部分组成:开发组件和运行组件。51Testing软件测试网D:yh*Q%\ iS4X

开发组件:Windows Sockets实现文档、应用程序接口(API)引入库和一些头文件。51Testing软件测试网k+xS.C/Y/E

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

6O!L%Z)PN.H!G0

 51Testing软件测试网@m$N BeoK{

五、WinSock主要扩充说明51Testing软件测试网uaZ*ID7rsRle$g

  1、异步选择机制:51Testing软件测试网Fn c.d @,J9{

  Windows Sockets的异步选择函数提供了消息机制的网络事件选择,当使用它登记网络事件发生时,应用程序相应窗口函数将收到一个消息,消息中指示了发生的网络事件,以及与事件相关的一些信息。51Testing软件测试网XK2N#k1O$I

  Windows Sockets提供了一个异步选择函数WSAAsyncSelect(),用它来注册应用程序感兴趣的网络事件,当这些事件发生时,应用程序相应的窗口函数将收到一个消息。

w%|j!X/mB'X0

  函数结构如下:51Testing软件测试网x0S$t3i.L\Y~

  int PASCAL FAR WSAAsyncSelect(SOCKET s,HWND hWnd,unsigned int wMsg,51Testing软件测试网m3U$ZJ~h J(eQ

    long lEvent);

o| g:XT-m0

  参数说明:51Testing软件测试网{6eX6bWs

  hWnd:窗口句柄51Testing软件测试网Q8VY j q:h _%n+VE

  wMsg:需要发送的消息51Testing软件测试网gg+tYakK xB

lEvent:事件(以下为事件的内容)

m {!v,~@Q9s;D5WI051Testing软件测试网x y6G-PP0xt7_$D.|/a

值:

} p&{` qO0

含义:

r7t\'\-K0

FD_READ51Testing软件测试网5i CjX3q h A/G4p

期望在套接字上收到数据(即读准备好)时接到通知

+Z&W}(m O`}Fc0

FD_WRITE

\W o/sD}&bL*z0

期望在套接字上可发送数据(即写准备好)时接到通知

4K,VptD W-] \KU3^0

FD_OOB51Testing软件测试网&a6Cy Kvw

期望在套接字上有带外数据到达时接到通知51Testing软件测试网Zjrn8\yT8g V

FD_ACCEPT

,cJ(L'ExV:v hG0

期望在套接字上有外来连接时接到通知51Testing软件测试网 K.oml5o f)[@

FD_CONNECT

5\ mA2hxE4K0

期望在套接字连接建立完成时接到通知51Testing软件测试网fB(l~fOhV1m

FD_CLOSE

qV HY6M^;j4x'I0

期望在套接字关闭时接到通知51Testing软件测试网/Atz[4W&mZ U$M

51Testing软件测试网r$vCV5L

例如:我们要在套接字读准备好或写准备好时接到通知,语句如下:51Testing软件测试网&[;b;l a%}[y ? \F

rc=WSAAsyncSelect(s,hWnd,wMsg,FD_READ|FD_WRITE);

Tu?[JQ%b0

  如果我们需要注销对套接字网络事件的消息发送,只要将lEvent设置为051Testing软件测试网^(q$gc~:v y P

2、异步请求函数51Testing软件测试网6V't3[Wy+r?.i(ah5qv

Berkeley Sockets中请求服务是阻塞的,WINDOWS SICKETS除了支持这一类函数外,还增加了相应的异步请求函数(WSAAsyncGetXByY();)

/B\v%n&G `j%\ya0

3、阻塞处理方法51Testing软件测试网"],W,Vgq

Windows Sockets为了实现当一个应用程序的套接字调用处于阻塞时,能够放弃CPU让其它应用程序运行,它在调用处于阻塞时便进入一个叫“HOOK”的例程,此例程负责接收和分配WINDOWS消息,使得其它应用程序仍然能够接收到自己的消息并取得控制权。

Lx&vO7s4wvKb$w+[0

WINDOWS是非抢先的多任务环境,即若一个程序不主动放弃其控制权,别的程序就不能执行。因此在设计Windows Sockets程序时,尽管系统支持阻塞操作,但还是反对程序员使用该操作。但由于SUN公司下的Berkeley Sockets的套接字默认操作是阻塞的,WINDOWS作为移植的SOCKETS也不可避免对这个操作支持。

f7IS6d;d0

Windows Sockets实现中,对于不能立即完成的阻塞操作做如下处理:DLL初始化→循环操作。在循环中,它发送任何WINDOWS消息,并检查这个Windows Sockets调用是否完成,在必要时,它可以放弃CPU让其它应用程序执行(当然使用超线程的CPU就不会有这个麻烦了^_^)。我们可以调用WSACancelBlockingCall()函数取消此阻塞操作。51Testing软件测试网x s)B2Z-ir

Windows Sockets中,有一个默认的阻塞处理例程BlockingHook()简单地获取并发送WINDOWS消息。如果要对复杂程序进行处理,Windows Sockets中还有WSASetBlockingHook()提供用户安装自己的阻塞处理例程能力;与该函数相对应的则是WSAUnhookBlockingHook(),它用于删除先前安装的任何阻塞处理例程,并重新安装默认的处理例程。请注意,设计自己的阻塞处理例程时,除了函数WSACancelBlockingHook()之外,它不能使用其它的Windows Sockets API函数。在处理例程中调用WSACancelBlockingHook()函数将取消处于阻塞的操作,它将结束阻塞循环。51Testing软件测试网_-l,odxF'iQ~1J

4、出错处理

[W0B2YYy)]:`^-[ Ed0

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

5、启动与终止

^'ao mCc0

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

"t)sH o;d ?.y0

 

oq K~4k0

六、Windows Sockets网络程序设计核心51Testing软件测试网5y%]FOu{5R w

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

{3Lr[N5d0

1、启动与终止

pm T]q B0

在所有Windows Sockets函数中,只有启动函数WSAStartup()和终止函数WSACleanup()是必须使用的。51Testing软件测试网 wmRo M,l,w}by

启动函数必须是第一个使用的函数,而且它允许指定Windows Sockets API的版本,并获得SOCKETS的特定的一些技术细节。本结构如下:51Testing软件测试网6m$D%J,q/}u

int PASCAL FAR WSAStartup(WORD wVersionRequested, LPWSADATA lpWSAData);

2I;?s~h(HN2~}^0

其中wVersionRequested保证SOCKETS可正常运行的DLL版本,如果不支持,则返回错误信息。51Testing软件测试网0m/mJb7b&m7kjN$vn

我们看一下下面这段代码,看一下如何进行WSAStartup()的调用

ge.nU {*yq z051Testing软件测试网l8fhzp]ip)Jk*p

WORD wVersionRequested;//定义版本信息变量51Testing软件测试网3yF:PN6g4JH

WSADATA wsaData;//定义数据信息变量51Testing软件测试网6UYLr,S9~CI(}

int err;//定义错误号变量

;V8r0dv&`y0

wVersionRequested = MAKEWORD(1,1);//给版本信息赋值51Testing软件测试网:|B)Fn8R?

err = WSAStartup(wVersionRequested, &wsaData);//给错误信息赋值

0CaNR7N3Q.M"D2km0

if(err!=0)51Testing软件测试网toIGJ(M GL^M

{

#dU f9iF\0

  return;//告诉用户找不到合适的版本51Testing软件测试网xbl9N1TW

}

1{7p T-\%J2F@0x0

//确认Windows Sockets DLL支持1.1版本51Testing软件测试网4p0L oqc5BC"yC

//DLL版本可以高于1.1

#jI'}l](m c0

//系统返回的版本号始终是最低要求的1.1,即应用程序与DLL中可支持的最低版本号51Testing软件测试网SX o?iF@ HJ Q

if(LOBYTE(wsaData.wVersion)!= 1|| HIBYTE(wsaData.wVersion)!=1)

:u'j:z0A+h/t0

{51Testing软件测试网9TM%I9w)Q/K

  WSACleanup();//告诉用户找不到合适的版本51Testing软件测试网4x)G,B&dn&S6F2\

  return;51Testing软件测试网} NG |c1F7Kj

}

s|?'q#c h0

//Windows Sockets DLL被进程接受,可以进入下一步操作51Testing软件测试网/CyD O#v od

[jn0V7f!D%P'c0

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

UD'LAj/k'DN'orzP0

2、异步请求服务

'eg U.BmA!G|c0

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

HANDLE taskHnd;51Testing软件测试网G4C/Qf9v[CO%k

char hostname="rs6000";

+V4VP.QuK;L0

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

m;_+D7N&LY0

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

!jeW9\/Q0

3、异步数据传输

:v `c@-W/F Ly0

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

wi,i:a0N7_g8ELg0

假设套接字s在连接建立后,已经使用了函数WSAAsyncSelect()在其上注册了网络事件FD_READFD_WRITE,并且wMsg值为UM_SOCK,那么我们可以在Windows消息循环中增加如下的分支语句:51Testing软件测试网7G y$g?[E}0n*Oc

51Testing软件测试网%^?0L*J3X

case UM_SOCK:

NH+}4zWX[X lbd0

  switch(lParam)

Q2t[#M%];G0

  {51Testing软件测试网 e(S:L4|A:U

  case FD_READ:

&jT AZ s0

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

8}a%~DG c,^6l#K l0

    break;51Testing软件测试网Uv6G)t7}j

  case FD_WRITE:

GP Ns~Jn^0

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

-q0XX2~2yj i/e0

    break;

5_V&AY8P#tC"f4A0

  }

0E9y0^`z z7} I;Qr,M0

break;51Testing软件测试网`y~Caqp

7m|2u:[(Hna*o0

4、出错处理51Testing软件测试网7}5X-{3Ynm/yH

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

;@;HEq7^7THI0

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

] QLv6UL0

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

~,k-Al$K-?+i051Testing软件测试网:icIHv1jI

51Testing软件测试网2NkJ'j8]x qZ0F.S
 

}:jn)r/{S5N0

TAG: 网络知识

 

评分:0

我来说两句

Open Toolbar