IO完成端口入门级详细注释代码
2011-09-25 19:48
399 查看
#include "StdAfx.h" #include "MyServer.h" #include <WinSock2.h> #pragma comment(lib, "Ws2_32.lib")//windows socket库
typedef struct __ARG { HANDLE hComplete; SOCKET server; }__ARG; typedef struct CompleteKey { SOCKET socket; }CompleteKey; //overlap一定要放在第一位置 typedef struct { OVERLAPPED overlap; //重叠io必须的结构体 WSABUF buf; //系统缓冲区指针 char data[1024];//数据缓存区 DWORD NumberOfBytesRecvd;//发送或者接收的数据字节数 DWORD Flags; int OperationType;//操作类型 }IO_DATA; //定义一个结构体保存IO数据 void initIoData(IO_DATA* ioData)//初始化io数据包 { memset(ioData,0,sizeof(IO_DATA)); ioData->buf.buf=ioData->data; ioData->buf.len=100; ioData->Flags=0; ioData->NumberOfBytesRecvd=100; } //弹出对话框 void myBox(char* format,...) { char buf[100]={0}; va_list ap; va_start(ap, format); sprintf_s(buf,format, ap); va_end(ap); MessageBoxA(0,buf,"",MB_OK); } //测试用函数 void test(SOCKET socket) { char buf[100]={0}; recv(socket,buf,100,0); myBox(buf); } //创建一个IO完成端口 HANDLE CreateNewCompletionPort(DWORD dwNumberOfConcurrentThreads) { return( CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, NULL, dwNumberOfConcurrentThreads)); } //将设备与完成端口管理起来 BOOL AssociateDeviceWithCompletionPort(HANDLE hCompletionPort, HANDLE hDevice, DWORD dwCompletionKey) { HANDLE h = CreateIoCompletionPort(hDevice, hCompletionPort, dwCompletionKey, 0); return(h == hCompletionPort); } //初始化winsock环境 void initSocket() { WORD wVersionRequested; WSADATA wsaData; int err; wVersionRequested = MAKEWORD(2, 2); err = WSAStartup(wVersionRequested, &wsaData); if (err != 0) { printf("WSAStartup failed with error: %d\n", err); return ; } if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2) { printf("Could not find a usable version of Winsock.dll\n"); WSACleanup(); return ; } } MyServer::MyServer(void) { //跟客户端端一样 初始化windows socket环境 initSocket(); //创建socket句柄 socksrv = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if(socksrv==INVALID_SOCKET) { myBox("create socket server error!"); } //地址设定 addrsrv.sin_addr.S_un.S_addr = htonl(INADDR_ANY); addrsrv.sin_family = AF_INET; //端口设定 addrsrv.sin_port = htons(9999); //绑定地址和端口 bind(socksrv,(sockaddr*)&addrsrv,sizeof(sockaddr)); //监听客户端请求 listen(socksrv,5); } MyServer::~MyServer(void) { } //服务器工作线程 DWORD WINAPI ServerWorkerThread(LPVOID arg) { // myBox("working\n"); IO_DATA *data=0; CompleteKey *key=0; DWORD recved; initSocket(); while(1) { //异步接收的时候,传的是结构体中overlap的地址,这个地址和io_data结构体的地址是一致的 正是利用了这点,才巧妙的实现了异步获取数据 //data返回的指针即为异步接收的时候传入的指针 //key返回的指针即为绑定设备时候传入的指针 GetQueuedCompletionStatus((HANDLE)arg,&recved,(LPDWORD)&key,(LPOVERLAPPED*)&data,WSA_INFINITE); //接收数据为0 说明客户端关闭连接 if(recved==0) { closesocket(key->socket); delete key; GlobalFree(data); continue; } data->data[data->NumberOfBytesRecvd]=0; //讲数据不改动的发送给客户端 send(key->socket,data->data,data->NumberOfBytesRecvd,0); initIoData(data);//初始化IO数据包 //处理完数据后再次触发一次异步接收 WSARecv(key->socket,&data->buf,1, &data->NumberOfBytesRecvd, &data->Flags,&data->overlap, NULL) ; } return 0; } //接收请求的线程 DWORD WINAPI MainThread(LPVOID arg) { __ARG *args=(__ARG*)arg; SOCKET client; initSocket(); while(1) { SOCKADDR_IN saRemote; int nRemoteLen = sizeof(saRemote); //接受一个连接请求 client= accept(args->server, (sockaddr*)&saRemote, &nRemoteLen); if(client==SOCKET_ERROR) { myBox("client error!\n"); break; } //创建一个完成键 CompleteKey* key=new CompleteKey(); key->socket=client; //把接收到的客户socket当成设备管理到完成端口 //key 标识这个设备的一些数据 if(AssociateDeviceWithCompletionPort(args->hComplete,(HANDLE)client,(DWORD)key)==FALSE)//关联设备 myBox("设备关联失败!"); IO_DATA *ioData = (IO_DATA *)GlobalAlloc(GPTR,sizeof(IO_DATA));//初始化一个io完成数据 initIoData(ioData); //test(client); //触发一个异步接收请求 该函数调用后立马返回 int ret=WSARecv(client,&ioData->buf,1, &ioData->NumberOfBytesRecvd, &ioData->Flags,&ioData->overlap, NULL) ; //注意多判断一个错误码~ 如果错误码是WSA_IO_PENDING 其实也是正常状态,因为 //该错误码表明异步操作成功,等待指示。(客户端调用connect后被阻塞了,就会出现这种情况) if(ret==SOCKET_ERROR && WSAGetLastError()!=WSA_IO_PENDING) { myBox("wsaRecv error :%d \n",WSAGetLastError()); } } return 0; } void MyServer::begin() { int threads=2; HANDLE hCompletion = CreateNewCompletionPort(threads);//创建两个工作线程 if(hCompletion==0) { myBox("端口创建失败!"); return; } int i=0; DWORD threadId; for(i=0;i<threads;i++) { CreateThread(0,0,ServerWorkerThread,hCompletion,0,&threadId); } __ARG *arg=new __ARG(); arg->hComplete=hCompletion; arg->server=socksrv; CreateThread(0,0,MainThread,arg,0,&threadId); }
相关文章推荐
- HDOJ1175 宽搜BFS基础入门题(有详细注释的代码)
- Shellcode和Payload入门102-代码中的加密-一如既往地源码和超详细注释
- JAVA连接Oracle数据库实代码+详细注释
- 异步IO、APC、IO完成端口、线程池与高性能服务器 (四)
- 新浪微博自动转发评论 源码 按键精灵实现 详细注释 几十行代码实现 涉及图像识别模拟键盘鼠标
- 异步IO、APC、IO完成端口、线程池与高性能服务器
- 异步IO、APC、IO完成端口、线程池与高性能服务器
- 《Windows核心编程系列》十异步IO之IO完成端口
- iOS 3D Touch超详细入门(附带demo示例代码)
- Windows网络编程-(完成端口及网络编程)详细介绍2
- Prototype 1.4.0源码详细解释--脚本代码全文注释
- C#制作鹰眼的详细全过程(带注释)实例代码
- 菜鸟之[C#WinForm传值(方法一)(详细代码及注释)]
- openCV实现多人脸检测,多眼部检测,完整代码和详细注释
- POJ 1035 代码+详细注释
- Android项目 手机安全卫士(代码最全,注释最详细)之九 两种上下文的区别
- Chapter10-IO完成端口
- BP神经网络以及在手写数字分类中python代码的详细注释
- (转载)异步IO、APC、IO完成端口、线程池与高性能服务器 (四)
- 异步IO、APC、IO完成端口、线程池与高性能服务器 (五)