WSAEventSelect模型
2017-04-07 00:19
375 查看
vs2013:肯定可用,但完全没有注释
WSAEventSelect模型在等待时不占用cpu时间,所以比阻塞的socket通信要效率高
为了纪念自己这个东西搞不懂,事件本来也是不懂,花了一天基本明白,但是还是有许多细节扣不了,感觉,如果要定时发送还是在FD_WRITE下直接开线程循环吧,WSAEventSelect模型你无法像用FD_READ一样用FD_WRITE
FD_WRITE事件只有在以下三种情况下才会触发
①client 通过connect(WSAConnect)首次和server建立连接时,在client端会触发FD_WRITE事件
②server通过accept(WSAAccept)接受client连接请求时,在server端会触发FD_WRITE事件
③send(WSASend)/sendto(WSASendTo)发送失败返回WSAEWOULDBLOCK,并且当缓冲区有可用空间时,则会触发FD_WRITE事件
①②其实是同一种情况,在第一次建立连接时,C/S端都会触发一个FD_WRITE事件。
主要是③这种情况:send出去的数据其实都先存在winsock的发送缓冲区中,然后才发送出去,如果缓冲区满了,那么再调用send(WSASend,sendto,WSASendTo)的话,就会返回一个 WSAEWOULDBLOCK的错误码,接下来随着发送缓冲区中的数据被发送出去,缓冲区中出现可用空间时,一个 FD_WRITE 事件才会被触发,这里比较容易混淆的是 FD_WRITE 触发的前提是缓冲区要先被充满然后随着数据的发送又出现可用空间,而不是缓冲区中有可用空间,
此处照搬,原因是这个是我找了一天中说的最清楚的,没有绕来绕去把他们自己都给绕晕的(有的看着真的蛮恶心,他们自己肯定也看不懂)
WSAEventSelect模型在等待时不占用cpu时间,所以比阻塞的socket通信要效率高
#include "stdafx.h" #include<iostream> #include"winsock2.h" #pragma comment(lib,"WS2_32.lib") int main(int argc, char**argv) { SOCKET sockets[20]; WSAEVENT events[20]; int num = 0; WSAData wsa; WSAStartup(MAKEWORD(2, 2), &wsa); SOCKET server = socket(AF_INET, SOCK_STREAM, 0); sockaddr_in serverAddr; serverAddr.sin_port = htons(3000); serverAddr.sin_family = AF_INET; serverAddr.sin_addr.S_un.S_addr = htonl(INADDR_ANY); ::bind(server, (sockaddr*)&serverAddr, sizeof(sockaddr)); listen(server, 10); WSAEVENT serverEvent = WSACreateEvent(); WSAEventSelect(server, serverEvent, FD_ACCEPT | FD_CLOSE); sockets[num] = server; events[num] = serverEvent; num++; while (true) { int rec = ::WSAWaitForMultipleEvents(num, events, false, WSA_INFINITE, false); rec = rec - WSA_WAIT_EVENT_0; WSANETWORKEVENTS evt; ::WSAEnumNetworkEvents(sockets[rec], events[rec], &evt); if (evt.lNetworkEvents & FD_ACCEPT) { if (evt.iErrorCode[FD_ACCEPT_BIT] == 0) { SOCKET client = accept(sockets[rec], NULL, NULL); WSAEVENT clientEvent = WSACreateEvent(); WSAEventSelect(client, clientEvent, FD_WRITE | FD_READ | FD_CLOSE);//accept接收的与其父套接字的网络事件相同并且使用同一个时间对象 sockets[num] = client; events[num] = clientEvent; num++; } } else if (evt.lNetworkEvents & FD_READ) { if (evt.iErrorCode[FD_READ_BIT] == 0) { char buf[100] = { 0 }; recv(sockets[rec], buf, 99, 0); buf[99] = '\0'; printf("%s\n", buf); } } else if (evt.lNetworkEvents & FD_WRITE) { if (evt.iErrorCode[FD_WRITE_BIT] == 0) { char buf[100] = "server:server"; send(sockets[rec], buf, strlen(buf) + 1, 0); printf("%s\n", buf); } } else if (evt.lNetworkEvents & FD_CLOSE) { if (evt.iErrorCode[FD_CLOSE_BIT] == 0) { ::closesocket(sockets[rec]); for (size_t i = rec; i < num - 1; i++) { sockets[i] = sockets[i - 1]; events[i] = events[i - 1]; } num--; } } } WSACleanup(); return 0; }
为了纪念自己这个东西搞不懂,事件本来也是不懂,花了一天基本明白,但是还是有许多细节扣不了,感觉,如果要定时发送还是在FD_WRITE下直接开线程循环吧,WSAEventSelect模型你无法像用FD_READ一样用FD_WRITE
FD_WRITE事件只有在以下三种情况下才会触发
①client 通过connect(WSAConnect)首次和server建立连接时,在client端会触发FD_WRITE事件
②server通过accept(WSAAccept)接受client连接请求时,在server端会触发FD_WRITE事件
③send(WSASend)/sendto(WSASendTo)发送失败返回WSAEWOULDBLOCK,并且当缓冲区有可用空间时,则会触发FD_WRITE事件
①②其实是同一种情况,在第一次建立连接时,C/S端都会触发一个FD_WRITE事件。
主要是③这种情况:send出去的数据其实都先存在winsock的发送缓冲区中,然后才发送出去,如果缓冲区满了,那么再调用send(WSASend,sendto,WSASendTo)的话,就会返回一个 WSAEWOULDBLOCK的错误码,接下来随着发送缓冲区中的数据被发送出去,缓冲区中出现可用空间时,一个 FD_WRITE 事件才会被触发,这里比较容易混淆的是 FD_WRITE 触发的前提是缓冲区要先被充满然后随着数据的发送又出现可用空间,而不是缓冲区中有可用空间,
此处照搬,原因是这个是我找了一天中说的最清楚的,没有绕来绕去把他们自己都给绕晕的(有的看着真的蛮恶心,他们自己肯定也看不懂)
相关文章推荐
- WSAEventSelect服务器模型
- vc++ windows socket I/O模型 WSAeventSelect 模型例子
- WSAEventSelect模型详解
- WSAEventSelect模型2
- WSAEventSelect模型
- IO模型(二)WSAEventSelect--事件选择机制
- (转)套接字IO模型(三) WSAEventSelect模型
- Socket I/O模型之事件选择(WSAEventSelect)
- WSAEventSelect模型学习
- Winsock的事件I/O异步模型——WSAEventSelect
- Windows操作系统I/O模型—笔记3(事件选择(WSAEventSelect)模型)
- WSAEventSelect模型例子
- WSAEventSelect模型基于TCP协议的控制台网络通信程序
- 套接字I/O模型之WSAEventSelect
- WSAEventSelect IO复用模型
- winsock IO模型 WSAEventSelect
- WSAEventSelect模型编程 详解
- 多种SOKECT通讯模型的理解(select,WSAAsyncSelect,WSAEventSelect,Overlapped I/O 事件通知,Overlapped I/O 完成例程,IOCP)
- 4:WSAEventSelect模型
- WinSock IO模型 -- WSAEventSelect模型事件触发条件说明