Windows Sockets 模型对比
阻塞模式的套接字用于少量数据接收和发送的简单网络程序开发;
在阻塞模式的套接字上,调用任何一个Windows Sockets API都会耗费不确定的等待时间;
套接字模式都是阻塞的;
“生产者-消费者”模型;
优势:开发简单,适合处理的套接字数量比较少的情况;
不足:在大量建立好的套接字线程之间进行通信时比较困难。
把套接字设置为非阻塞模式,即通知系统内核:在调用Windows Sockets API 时不要让线程睡眠,而应该让函数立即返回。
通过调用roctlsocket()函数讲套接字设置为非阻塞模式;
由于使用非阻塞套接字在调用函数时,会经常返回WSAEWOULDBLOCK错误,所以任何时候,都应该仔细检查返回代码,并作好“失败”准备。
使用I/O模型来判断非阻塞套接字是否可读可写。
优势:在控制建立的多个连接,在数据的收发量不均、时间不定等方面,具有优势。
不足:使用较复杂。
利用该模型可以在同一时间内管理和控制多个套接字。
核心是select()函数。
配合FD_SET,FD_ZERO,FD_ISSET,FD_CLR四个宏。
Select模型是windows sockets中最常见的I/O模型。利用select()函数实现I/O管理。
优势:可以同时等待多个套接字。同时对多个建立起来的套接字进行有序的管理。可以防止应用程序在一次I/O调用过程中,使阻塞模式套接字被迫进入阻塞状态;select函数类似一个消息中心。
不足:使用select()函数的程序可能效率会受损,每一个windows sockets I/O都会经过该函数,导致严重CPU负担。不适合高效率的程序。
WSAAsyncSelect模型是Windows Sockets的一个异步I/O模型。
可以在一个套接字上,接受以Windows消息为基础的网络事件。
WSAAsynSelect()函数注册网络事件。
WSAAsyncSelect模型是Select模型的异步版本。
此模型是非阻塞的。
与Select模型对比:
WSAAsyncSelect模型是异步的。当网络事件发生时,系统向应用程序发送消息。此模型在基于消息的Windows环境下,使用时必须创建窗口。
应用程序调用WSAAsyncSelect()函数后,自动将套接字设置为非阻塞模式。
开发人员注册哪种网络事件,取决于实际的需要。如果应用程序同时对多个网络事件感兴趣。需要对网络事件类型执行按位OR运算。
窗口例程是回调函数,当成功创建窗口后由系统调用。
注意:多次调用WSAAsyncSelect()函数注册不同的网络事件,只有最后一次函数注册的事件有效,也就是最后一次调用取消了前面注册的所有网络事件。
优势:基于windows消息机制,通过注册FD_CLOSE网络事件,可以从容关闭连接。
不足:也是因为基于windows消息机制,必须在应用程序中创建窗口。不过,可以使用CSocketWnd创建一个不显示的窗口。自动非阻塞,使用难度也较大。
也是异步I/O模型。
该模型允许在一个或者多个套接字上接收以事件为基础的网络事件通知。
WSAEventSelect()函数 将一个事件对象与网络事件集合关联在一起。当网络事件发生时,应用程序以事件的形式接收网络事件通知。
WSAEventSelect与WSAAsyncSelect模型差别:
网络事件发生时系统通知应用程序的形式不同。WSAAsyncSelect以消息的形式通知应用程序,而WSAEventSelect模型 以事件形式通知。
WSAEventSelect模型也是非阻塞的。
与其他对比:
从应用程序接收网络事件通知的方式来说,WSAEventSelect与WSAAsyncSelect模型都是被动的。当网络事件发生时,系统通知应用程序。
但是,select模型是主动的,应用程序主动调用函数查看是否发生了网络事件。
相关函数:
WSAEventSelect()
WSACreateEvent()
WSAResetEvent()
WSAWaitForMultipleEvents()
优势:可以应用在一个非窗口的Windows Sockets 程序中,实现对多个套接字的管理。
不足:每个WSAEventSelect模型最多只能管理最多64个套接字。当需要管理多于64个套接字时,需要额外创建线程。
该模型以Win32重叠I/O机制为基础。
利用此模型,应用程序能在一个重叠结构上一次投递一个或者多个I/O请求,当系统完成I/O操作后通知应用程序。
此模型才是真正意义上的异步I/O模型。
利用该模型,应用程序在调用输入或者输出函数后,只需要等待I/O操作完成的通知即可。
若从发送和接受数据操作的角度看,套接字Select模型、WSAAsyncSelect模型和WSAEventSelect模型不是异步模型,因为这3个模型的I/O操作还是同步的。
Windows Sockets应用程序在盗用WSARecv()函数后立即返回,线程继续执行。当系统中数据准备好,并且将数据复制到用户缓冲区后,向应用程序发送通知。应用程序接收到通知后,对数据进行处理。
系统向应用程序发送通知的形式有两种:一个事件通知,二是完成例程。
应用程序使用一个重叠结构,一次投递一个或者多个I/O请求。当系统完成I/O操作之后通知应用程序。该模型能是windows Socket应用程序达到更佳的性能。
完成端口是Win32一种核心对象。
利用完成端口模型,套接字应用程序能够管理数百个甚至上千个套接字。
应用程序创建一个Win32完成端口对象,通过指定一定数量的服务线程,为已经完成的重叠I/O操作提供服务。
该模型可以达到最好的系统性能。
也是以Win32的重叠I/O机制为基础。套接字应用程序发起I/O操作,该操作在后台完成,而发起操作的现成可以继续做其他的事情。当重叠I/O操作完成后,应用程序收到有关的通知。
服务器线程模型:
串行模型:单个线程等待客户端的请求,请求到来时该线程处理。应用于简单的服务器程序。
并行模型:(更高效)也是单个线程等待客户端的请求,但当请求到来时,创建新线程来处理请求。但此模型在系统内核进行线程上下文切换会花费很多时间,系统开销增大。
完成端口并行运行的线程数量和应用程序创建的线程数量是两个不同的概念。
服务器应用程序需要创建多少个服务线程,一般规律是CPU数目乘以2。
事件通知方式的不足:
使用哪个WSAWaitForMultipleEvents()函数时,最多等待WSA_MAXIMUM_WAIT_EVENTS个事件对象。
应用程序必须维护一个“事件-套接字-重叠结构”的关系表格。
完成例程的不足:
只有发起重叠I/O请求所在的线程才能提供完成例程。
优点:
1. 对发起重叠操作的数量不存在限制。
2. 允许一个线程发起重叠操作,而由另一个线程为完成的操作提供服务。
3. 支持scalable架构。