基于WSAEventSelect模型的TCP服务器实现
2009-04-10 17:24
656 查看
怎么感觉标题很学术的样子。。。上次那个重叠IO的事件模型搞完之后,就觉得TCP是很不错的协议,可以将重点转移到对客户端的管理之上,而不必为了数据报的丢失和客户端keepalive的问题而绞尽脑汁(之前我做了个简单的聊天软件,面对的就是这种问题)。
WSAEventSelect是基于事件通知的,我觉得没有比这个模型更加简单实用了,编译环境:vc++ 6.0,代码如下:
WSAEventSelect是基于事件通知的,我觉得没有比这个模型更加简单实用了,编译环境:vc++ 6.0,代码如下:
#include <tchar.h> #include <iostream> #include <algorithm> #include <winsock2.h> #include <crtdbg.h> #include <cstring> #include <iomanip> #include <list> #pragma comment(lib, "ws2_32.lib") using namespace std; #define LOC_PORT 5678 #define LOC_ADDR "127.0.0.1" class CSocketObject { public: CSocketObject(){WSAStartup(MAKEWORD(2,2), &m_wsaData);} virtual ~CSocketObject(){WSACleanup();} public: virtual void Run() = 0; protected: WSADATA m_wsaData; }; class CTcpServer : public CSocketObject { public: virtual void Run(); private: typedef struct { WSAEVENT event; SOCKET sock; }EVENT_T; list<EVENT_T> m_listClient; static WSAEVENT& DoGetEvent(EVENT_T& ev){return ev.event;} }; void CTcpServer::Run() { SOCKET tSock = socket(AF_INET, SOCK_STREAM, 0); char cBuf[1024]; SOCKADDR_IN tAddr, tComeinAddr; tAddr.sin_family = AF_INET; tAddr.sin_port = htons(LOC_PORT); tAddr.sin_addr.s_addr = inet_addr(LOC_ADDR); _ASSERT(bind(tSock,(SOCKADDR*)&tAddr, sizeof(tAddr)) == 0); WSAEVENT hWSAEvent = WSACreateEvent(); WSAEventSelect(tSock, hWSAEvent, FD_ACCEPT); _ASSERT(listen(tSock, 5) == 0); EVENT_T ev = {hWSAEvent, tSock}; m_listClient.push_back(ev); WSAEVENT events[64]; for (;;) { transform(m_listClient.begin(), m_listClient.end(), events, DoGetEvent); int dwIndex = WSAWaitForMultipleEvents(m_listClient.size(), events, false, WSA_INFINITE, false); list<EVENT_T>::iterator iter = m_listClient.begin(); int iPos = 0; while (iPos++ != dwIndex - WSA_WAIT_EVENT_0)++iter; WSANETWORKEVENTS tNetEvents; WSAEnumNetworkEvents(iter->sock, iter->event, &tNetEvents); if (FD_ACCEPT & tNetEvents.lNetworkEvents) { if (0 != tNetEvents.iErrorCode[FD_ACCEPT_BIT]) { std::cout<<"accept error occured/n"; continue; } else { int dwAddrLen = sizeof(tComeinAddr); SOCKET tSockIn = accept(tSock, (sockaddr*)&tComeinAddr, &dwAddrLen); ev.event = WSACreateEvent(); WSAEventSelect(tSockIn, ev.event, FD_READ | FD_CLOSE); ev.sock = tSockIn; m_listClient.push_back(ev); cout << "new come in..." << inet_ntoa(tComeinAddr.sin_addr) << "/n"; send(tSockIn, "You are welcome", strlen("You are welcome"), 0); } } else if (FD_READ & tNetEvents.lNetworkEvents) { if (0 != tNetEvents.iErrorCode[FD_READ_BIT]) { std::cout<<"read error occured/n"; continue; } else { int dwRet = recv(iter->sock, cBuf, 1024, 0); if (SOCKET_ERROR == dwRet) { } else { cout << "client...data: "; for (int n = 0; n != dwRet; ++n) { cout << "0x" << hex << (int)cBuf << " "; } cout << endl; } } } else if (FD_CLOSE & tNetEvents.lNetworkEvents) { int dwNameLen = sizeof(tComeinAddr); getpeername(iter->sock, (sockaddr*)&tComeinAddr, &dwNameLen); closesocket(iter->sock); WSACloseEvent(iter->event); m_listClient.erase(iter); cout << "client..." << inet_ntoa(tComeinAddr.sin_addr) << " quit/n"; } } } int _tmain(int argc, TCHAR *argv[]) { CSocketObject *poSockServer = new CTcpServer; poSockServer->Run(); delete poSockServer; return 0; }
相关文章推荐
- WSAEventSelect模型 ---应用实例,重写TCP服务器实例
- 基于WSAEventSelect模型的服务器设计
- 一个基于线程池的WSAEventSelect模型服务器设计
- 基于WSAEventSelect模型的服务器设计
- 一个基于线程池的WSAEventSelect模型服务器设计
- 使用Select I/O模型来实现一个并发处理多个客户端的TCP服务器
- WSAEventSelect模型基于TCP协议的控制台网络通信程序
- WSAEventSelect编程模型实现
- 基于select模型的TCP服务器
- 基于select模型tcp服务器的掉线处理
- WSAEventSelect服务器模型
- 基于select模型的tcp服务器------一个服务器如何与多个客户端进行通信?
- 基于事件的select:WSAEventSelect模型
- 基于WSAAsyncSelect实现的服务器
- Select I/O模型来实现一个并发处理多个客户端的TCP服务器 <转>
- WSAEventSelect多线程服务器实现示例
- Select I/O模型来实现一个并发处理多个客户端的TCP服务器
- 基于select模型的TCP服务器
- Windows平台下 WSAEventSelect模型 服务器
- WSAEventSelect模型编程