socket io管理模型总结(Linux、Windows)

--------------------------select:-----------------------------------
select所检查的所有fd,必须是关联于同一个服务提供者(listen fd)上。
select中的exceptfds也可用于检测OOB数据情况。(exceptfds可以标示OOB data is available for reading (only if SO_OOBINLINE is disabled). )
exceptfds: 1、连接失败;2、oob数据可读。


select的几大缺点:
(1)每次调用select,都需要把fd集合从用户态拷贝到内核态,这个开销在fd很多时会很大
(2)同时每次调用select都需要在内核遍历传递进来的所有fd,这个开销在fd很多时也很大。(遍历每个fd,调用其poll方法(sock_poll),获得读写就绪的mask,修改fd_set。)
(3)select支持的文件描述符数量太小了,默认是1024


schedule_timeout


select(nfds, rfds, wfds, efds, timeval *timeout);
windows上nfds被忽略。仅为保持和Berkeley socket程序的兼容。
如果timeout指针为空,则阻塞。如果timeout的时间为0,则立即返回。




--------------------------------poll----------------------------------
poll的实现和select非常相似,只是描述fd集合的方式不同,poll使用pollfd结构而不是select的fd_set结构。其他的都差不多。




----------------------------------epoll--------------------------------


1、fd从用户空间向内核空间的拷贝在整个过程中只需做一次。只要被侦听的fd关闭(close),它会自动从被侦听的集合删除。
2、只在epoll_ctl时把当前线程挂到fd对应的设备等待队列中,并为每个fd注册回调函数,回调函数把fd加入就绪链表。
3、epoll_wait时只需扫描就绪队列,效率比select/poll高。
4、尽量减少epoll_ctl的调用,其有一定开销。


epoll LT:
只要缓冲区中有数据,每次epoll_wait都通知。
为默认模式,没有相对应的宏。
可以支持block和non-block socket。
select/poll都是这种模式。


epoll ET:
只支持non-block socket。
只有缓冲区中来了新数据,epoll_wait才通知。所以收到通知应该持续读空缓冲区。
此时listen fd 的backlog中有三个连接,accept时,需要多次accept吗???????




EPOLLONESHOT:
并不是在一次事件后就被删除出epfd,只要EPOLL_CTL_MOD它的事件mask,就可以继续被监听。




select是对每一个的就绪进行等待,而epoll是对就绪队列进行等待。






------------------WSAAsyncSelect-------------
Winsock1.1
可以处理一个或多个套接口。
int WSAAsyncSelect(SOCKET s, HWND hWnd, unsigned int uMsg, long lEvent);
使用自定义的消息,注册预定义的事件。


使用步骤:
1、CreateWindow;
2、WinProc()/DlgProc();//wParam为socket;lParam的高字节为错误码,低字节为网络事件。
3、WSAAsyncSelect;//一次注册一个socket的事件,但可以注册多次以便对对多个socket注册事件。
4、通过closesocket()/WSAAsyncSelect(s,hwnd,umsg,0);//lEvent为0;来取消对这个s注册的事件。




-----------------WSAEventSelect-----------------
可以处理一个或多个套接口。每个socket关联一个事件对象句柄。
网络事件投递到事件对象句柄,而不是投递到一个窗口proc。
WSAEVENT WSACreateEvent(void);//无信号,手动reset。


int WSAEventSelect(SOCKET s, WSAEVENT hEventObject, long lNetworkEvent);


DWORD WSAWaitForMultipleEvents(DWORD cEvents, const WSAEVENT FAR * lphEvents, BOOL fWaitAll, DWORD dwTimeout, BOOL fAlertable);
cEvents为lphEvents数组中event个数。
如果fWaitAll=FALSE,则返回值Index,Index-WSA_WAIT_EVENT_0为事件对象数组的下标,指明有信号的事件。
WSA_MAXIMU_WAIT_EVENTS=64。相当于最多只能管理64个socket。但可以创建更多的工作线程,来关联n*64个socket。
fAlertable必须设置为FALSE。


int WSAEnumNetworkEvents(SOCKET s, WSAEVENT hEventObject, LPWSANETWORKEVENTS lpNetworkEvents);
用于查明发生了什么网络事件(lpNetworkEvents)。








------------------overlapped io----------------
winsock1.1\2.x
一次投递一个或多个winsock io请求。
以Win32重叠IO为基础。


使用WSASocket()创建socket时,必须指明WSA_FLAG_OVERLAPPED。
使用socket()创建socket时,默认设置WSA_FLAG_OVERLAPPED。


无论socket是否阻塞(锁定)模式,调用WSA*函数(overlapped sock IO相关函数)都会立即返回。

你可能感兴趣的:(TCPIP)