网站建设中 html5 模板下载推广引流的方法
web/
2025/9/26 13:59:43/
文章来源:
网站建设中 html5 模板下载,推广引流的方法,网站建设服务 百度,手机网站 app1.什么是IOCP
IOCP#xff08;Input Output Completion Port#xff09;输入输出完成端口。其实就是基于重叠I/O的一种改进的模型。
重叠I/O具有缺点#xff1a;重复调用非阻塞模式的accpet函数和以进入alertablewait状态为目的的SleepEx函数会影响程序性能。
而IOCP提供…1.什么是IOCP
IOCPInput Output Completion Port输入输出完成端口。其实就是基于重叠I/O的一种改进的模型。
重叠I/O具有缺点重复调用非阻塞模式的accpet函数和以进入alertablewait状态为目的的SleepEx函数会影响程序性能。
而IOCP提供的解决方案便是让主线程调用accept函数单独创建至少一个线程来负责所有I/O的前后处理。 但请不要过分关注在线程上主要还是如下问题 1.I/O是否以非阻塞模式工作 2.如何确定非阻塞模式的I/O是否完成 2.分阶段实现IOCP程序
2.1 实现原理
IOCP会将已完成的I/O信息注册到CP对象Completion Port完成端口而我们就可以通过CP对象来获取I/O是否完成的信息所以有下面两项工作
创建完成端口对象建立完成端口对象和套接字之间的联系
此时的套接字必须赋予重叠属性。
2.2 创建CP对象
#includewindows.hHANDLE CreateIoCompletionPort(
HANDLE fileHandle, //创建CP对象时传递INVALID_HANDLE_VALUE
HANDLE ExistingCompletionPort, //创建CP对象时传递NULL
ULONG_PTR CompletionKey, //创建CP对象时传递0
DWORD NumberOfConcurrentThreads //分配给CP对象的用于处理I/O的线程数。//例如该参数为2时说明分配给CP对象的可以同时运行的线程数最多为2个//如果为0时那么系统中CPU的个数就是可同时运行的最大线程数
);
成功返回CP对象句柄
失败返回NULL
2.3 创建和套接字连接完成的端口对象
#includewindows.hHANDLE CreateIoCompletionPort(
HANDLE FileHandle, //要连接到CP对象的套接字句柄
HANDLE ExistingCompletionPort, //要连接套接字的CP对象句柄
ULONG_PTR CompletionKey, //传递已完成I/O相关信息
DWORD NumberOfConcurrentThreads //无论传递何值只要第二个参数非NULL就会被忽略
);
成功返回CP对象句柄
失败返回NULL
函数功能将FileHandle句柄指向的套接字和ExistingCompletionPort指向的CP对象相连。
调用此函数后只要针对FileHandle的I/O完成相关信息就会注册到ExistingCompletionPort里。
注意第三个参数“传递已完成I/O相关信息”的意思是你可以像重叠I/O里使用Complition routine来确认I/O方式里把相关信息填写到hEvent里的那样写入其他信息这样当I/O完成就可以获取了。
2.4 确认完成端口已完成的I/O和线程I/O处理
#includewindows.hBOOL GetQueuedCompletionStatus(
HANDLE CompletionPort, //注册有已完成I/O信息的CP对象句柄
LPDWORD lpNumberOfBytes, //保存I/O过程中传输的数据大小的变量地址值
PULONG_PTR lpCompletionKey, //保存CreateIoCompleytionPort函数第三个参数值得变量地址值
LPOVERLAPPED* lpOverlapped, //保存调用WSASend、WSARecv函数时传递的OVERLAPPED结构体地址的变量地址值
DWORD dwMilliseconds //超时信息超过该指定时间后将返回FALSE并跳出函数。//传递INFINITE时程序将阻塞直到已完成I/O信息写入CP对象
);
成功返回TRUE
失败返回FALSE
注意
调用此函数的线程数量不能超过CreateIoCompletionPort时指定的线程数。此函数并不知道当前是输入信息状态还是输出信息状态需要自行判断。
3. 实现IOCP模型的回声服务器端
思路每连接一个客户端就创建一个线程然后主线程里先接收一次数据在子线程里通过GetQueuedCompletionStatus函数阻塞住线程判断I/O状态接着把接收的数据发送给客户端再次进入接收状态如此循环通信。
变量
struct ClientInfo结构体存有套接字和套接字地址族信息在CreateIoCompletionPort函数里建立套接字和CP的连接的时候当做第三参数传入
struct CPInfo结构体存有一个OVERLAPPED、WSABUF信息以及还有一个int型用来判断当前是RECV还是SEND在执行WSARecv函数时当做第六个参数进行传入。运用下面的知识点所以可以在子线程执行GetQueuedCompletionStatus函数时取得的第一个成员的地址也就是这整个结构体的地址。 知识点结构体变量地址值与结构体第一个成员的地址值相同。 struct CPInfo
{OVERLAPPED overlapped;WSABUF wsabuf;int mode; //0:RECV 1:SEND
};
CPInfo data;
if(datadata.overlapped)
{std::coutTRUEstd::endl;
}
else
{std::coutFALSEstd::endl;
}
输出TRUE #define _WINSOCK_DEPRECATED_NO_WARNINGS
#includeiostream
#includeWinSock2.h
#includeprocess.h
#includeWindows.h
#includemalloc.h
#includestringstruct ClientInfo
{SOCKET socket;sockaddr_in socketAddr;
};struct CPInfo
{OVERLAPPED overlapped;WSABUF wsabuf;int mode; //0:RECV 1:SEND
};unsigned WINAPI threadClient(void* arg);int main()
{WSADATA wsaData;if (0 ! WSAStartup(MAKEWORD(2, 2), wsaData)){std::cout start up fail! std::endl;return 0;}SOCKET server WSASocket(PF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, WSA_FLAG_OVERLAPPED);if (server INVALID_SOCKET){std::cout socket fail! std::endl;return 0;}int mode 1;ioctlsocket(server, FIONBIO, (u_long*)mode);sockaddr_in serverAddr;memset(serverAddr, 0, sizeof(serverAddr));serverAddr.sin_family AF_INET;serverAddr.sin_addr.s_addr htonl(INADDR_ANY);serverAddr.sin_port htons(9130);if (SOCKET_ERROR bind(server, (sockaddr*)serverAddr, sizeof(serverAddr))){std::cout bind fail! std::endl;return 0;}if (SOCKET_ERROR listen(server, 2)){std::cout listen fail! std::endl;return 0;}while (true){sockaddr_in clientAddr;memset(clientAddr, 0, sizeof(clientAddr));int clientAddrLen sizeof(clientAddr);SOCKET client accept(server, (sockaddr*)clientAddr, clientAddrLen);if (client SOCKET_ERROR){if (WSAGetLastError() WSAEWOULDBLOCK) //说明此时没有客户端连接{continue;}std::cout accept fail! std::endl;}else{HANDLE cpObject CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 0);if (cpObject NULL){std::cout Create CP fail! std::endl;continue;}ClientInfo* clientinfo new ClientInfo();clientinfo-socket client;clientinfo-socketAddr clientAddr;CreateIoCompletionPort((HANDLE)client, cpObject, (ULONG_PTR)clientinfo, 0);unsigned threadId;if (0 _beginthreadex(NULL, 0, threadClient, (void*)cpObject, 0, threadId)) //创建一个线程{std::cout thread create fail! std::endl;continue;}CPInfo* cpinfo new CPInfo();cpinfo-mode 0;memset(cpinfo-overlapped, 0, sizeof(cpinfo-overlapped));char buff[1024];cpinfo-wsabuf.buf buff;cpinfo-wsabuf.len sizeof(buff);DWORD readLen;DWORD flag 0;WSARecv(client, cpinfo-wsabuf, 1, readLen, flag, cpinfo-overlapped, NULL);}}closesocket(server);WSACleanup();
}unsigned WINAPI threadClient(void* arg)
{HANDLE cpObject *(HANDLE*)arg;CPInfo* cpinfo;ClientInfo* clientinfo;while (true){DWORD readLen;GetQueuedCompletionStatus(cpObject, readLen, (PULONG_PTR)clientinfo, (LPOVERLAPPED*)cpinfo, INFINITE);if (readLen 0){std::cout 客户端: inet_ntoa(clientinfo-socketAddr.sin_addr) 断开连接! std::endl;break;}if (cpinfo-mode 0) //recv{std::cout 客户端发来的消息: cpinfo-wsabuf.buf std::endl;DWORD flag 0;cpinfo-mode 1;WSASend(clientinfo-socket, cpinfo-wsabuf, 1, readLen, flag, cpinfo-overlapped, NULL);CPInfo* cpinfo2 new CPInfo();cpinfo2-mode 0;memset(cpinfo2-overlapped, 0, sizeof(cpinfo2-overlapped));char buff[1024];cpinfo2-wsabuf.buf buff;cpinfo2-wsabuf.len sizeof(buff);DWORD readLen2;WSARecv(clientinfo-socket, cpinfo2-wsabuf, 1, readLen2, flag, cpinfo2-overlapped, NULL);}else //send{delete cpinfo;}}CloseHandle(cpObject);closesocket(clientinfo-socket);return 0;
}
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/81213.shtml
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!