【Windows网络编程】EventSelect网络模型
2017-10-19 12:58
417 查看
//解决select模型工作者线程时间片未充分利用的问题 #include <winsock2.h> #include <stdio.h> #define PORT 6000 #pragma comment (lib,"Ws2_32.lib") SOCKET ArrSocket[1024] = { 0 }; WSAEVENT ArrEvent[1024] = { 0 }; DWORD dwTotal = 0; DWORD dwIndex = 0; int ClientNums = 0; //标记已经链接了多少个客户端 BOOL WinSockInit() { WSADATA data = { 0 }; if (WSAStartup(MAKEWORD(2, 2), &data)) return FALSE; if (LOBYTE(data.wVersion) != 2 || HIBYTE(data.wVersion) != 2){ WSACleanup(); return FALSE; } return TRUE; } //工作者线程 怎么实现 将监听的socket以及客户端通信的socket 同时进行监控? //怎么来节省时间的?(相对select) DWORD WINAPI ListentThreadProc(LPARAM lparam) { char buf[1024] = { 0 }; SOCKET sockClient = INVALID_SOCKET; //用于accept临时使用的socket WSANETWORKEVENTS NetWorkEvent = { 0 }; while (true){ //ArrSocket[1]; //数组内任意一个wsaevent有信号了,api就返回。。 dwIndex = WSAWaitForMultipleEvents(dwTotal, ArrEvent, FALSE, 100, FALSE); if (dwIndex == WSA_WAIT_TIMEOUT){ continue; } //如何知道是哪个socket出现了网络事件,deindex发生网络事件的socket数组下标 WSAEnumNetworkEvents(ArrSocket[dwIndex - WSA_WAIT_EVENT_0], ArrEvent[dwIndex - WSA_WAIT_EVENT_0], &NetWorkEvent); if (NetWorkEvent.lNetworkEvents&FD_ACCEPT){//如果第三位数据是1,代表有客户端进行连接 if (NetWorkEvent.iErrorCode[FD_ACCEPT_BIT] != 0) { continue; } sockClient = accept(ArrSocket[dwIndex - WSA_WAIT_EVENT_0], NULL, NULL); if (sockClient == INVALID_SOCKET) continue; //连接完成后,立即将客户端的socket保存到数据,同时新建event与socket建立关系 WSAEVENT newEvent = WSACreateEvent(); WSAEventSelect(sockClient, newEvent, FD_READ | FD_WRITE | FD_CLOSE); for (;;);//检查数组内是否有空值,如果有就保存。。 ArrSocket[dwTotal] = sockClient; ArrEvent[dwTotal] = newEvent; ++dwTotal; ++ClientNums; } if (NetWorkEvent.lNetworkEvents&FD_READ) //说明有客户端向服务器发送数据 但这个数据还只在网卡上 没有到达程序buffer { if (NetWorkEvent.iErrorCode[FD_READ_BIT] != 0) { continue; } recv(ArrSocket[dwIndex - WSA_WAIT_EVENT_0], buf, sizeof(buf), 0); printf("Recv:%s\n", buf); send(ArrSocket[dwIndex - WSA_WAIT_EVENT_0], buf, strlen(buf), 0); } if (NetWorkEvent.lNetworkEvents&FD_WRITE) //说明程序-服务器准备向客户端发送信息了、、 { if (NetWorkEvent.iErrorCode[FD_WRITE_BIT] != 0) { continue; } printf("Send somthing\n"); } if (NetWorkEvent.lNetworkEvents&FD_CLOSE) //表示有一个socket关闭了 是监听的还是通信的 不需要关心。。 { if (NetWorkEvent.iErrorCode[FD_CLOSE_BIT] != 0) { continue; } closesocket(ArrSocket[dwIndex - WSA_WAIT_EVENT_0]); ArrSocket[dwIndex - WSA_WAIT_EVENT_0] = 0; } } } int main() { WinSockInit(); SOCKET sockListen = INVALID_SOCKET;//服务器监听的socket sockListen = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (sockListen == INVALID_SOCKET) { printf("Creat Socket Error"); return -1; } sockaddr_in service; service.sin_family = AF_INET; service.sin_addr.S_un.S_addr = INADDR_ANY; service.sin_port = htons(PORT); if (bind(sockListen, (sockaddr*)&service, sizeof(service)) == SOCKET_ERROR) { printf("Bind Failed\n"); return -1; } //进行event select特有的操作 WSAEVENT ListenEvent = WSACreateEvent(); //把WSAEVENT与一个socket进行绑定没 告诉绑定的对象需要关注的事件有哪些 WSAEventSelect(sockListen, ListenEvent, FD_ACCEPT | FD_CLOSE);//仅关注两个事件,有客户端进行连接,需要关闭服务器监听的socket CreateThread(NULL, NULL, (LPTHREAD_START_ROUTINE)ListentThreadProc, NULL, NULL, NULL);//创建一个子进程,用子进程来处理所有的socket上的事件 if (listen(sockListen, SOMAXCONN) == SOCKET_ERROR){ printf("Listen Error\n"); return -1; } ArrSocket[dwTotal] = sockListen; ArrEvent[dwTotal] = ListenEvent; ++dwTotal;//标识总共有多少个用户已经连接 到这里数组保存的socket只有一个 system("pause"); if (sockListen != INVALID_SOCKET) { closesocket(sockListen); } WSACleanup(); return 0; }
相关文章推荐
- windows网络编程之select模型(改进)
- 【Windows网络编程】Select网络模型
- windows下的网络编程——Select模型实例,一款ECHO服务的实现代码
- windows 网络编程 几种套接字模型
- windows网络编程之重叠模型(OVERLAPPED I/O)基础知识
- [Windows]7种网络编程I/O模型代码实现实例
- windows下的网络编程——Select模型实例,一款ECHO服务的实现代码
- windows网络编程通讯模型
- Windows网络编程之Select模型学习笔记
- Windows的网络编程-之四-套接字模型
- windows下的网络编程——Select模型实例,一款ECHO服务的实现代码
- 操作系统,windows编程,网络,socket
- Windows Embedded Compact 7网络编程概述(下)
- Windows网络编程经验小结
- 网络编程基础:使用SELECT模型
- 关于网络编程五种IO模型的形象比喻
- 网络编程---IO复用之epoll模型
- JavaScript---网络编程(6)-Dom和Bom模型概念讲解(节点获取,window对象)
- Windows网络编程基础知识
- IOCP模型与网络编程