I/O完成端口(IOCP)
服务器:
#include "stdafx.h"
#include <winsock2.h>
#pragma comment(lib, "ws2_32.lib")
#include <iostream>
using namespace std; // 单句柄数据
typedef struct tagPER_HANDLE_DATA
{
SOCKET Socket;
SOCKADDR_STORAGE ClientAddr;
// 将和这个句柄关联的其他有用信息,尽管放在这里面吧 }PER_HANDLE_DATA, *LPPER_HANDLE_DATA; // 但I/O 操作数据
typedef struct tagPER_IO_DATA
{
OVERLAPPED Overlapped;
WSABUF DataBuf;
char buffer[];
int BufferLen;
int OperationType; // 可以作为读写的标志,为简单,我忽略了
}PER_IO_DATA, *LPPER_IO_DATA; //线程函数
DWORD WINAPI ServerWorkerThread(LPVOID lpParam); DWORD WINAPI ServerWorkerThread(LPVOID lpParam)
{
HANDLE CompletionPort = (HANDLE)lpParam;
DWORD BytesTransferred;
LPOVERLAPPED lpOverlapped;
LPPER_HANDLE_DATA PerHandleData = NULL;
LPPER_IO_DATA PerIoData = NULL;
DWORD SendBytes;
DWORD RecvBytes;
DWORD Flags;
BOOL bRet = FALSE; while (TRUE) //无限循环
{
bRet = GetQueuedCompletionStatus(CompletionPort,&BytesTransferred,(PULONG_PTR)&PerHandleData,(LPOVERLAPPED*)&lpOverlapped,INFINITE); // 检查成功的返回,这儿要注意使用这个宏CONTAINING_RECORD
PerIoData = (LPPER_IO_DATA)CONTAINING_RECORD(lpOverlapped,PER_IO_DATA,Overlapped);
// 先检查一下,看看是否在套接字上已有错误发生 if ( == BytesTransferred)
{
closesocket(PerHandleData->Socket);
GlobalFree(PerHandleData);
GlobalFree(PerIoData);
continue;
} // 数据处理
char sendBuf[];
sprintf(sendBuf,"Welcome %s to %d %d \n",PerIoData->DataBuf.buf,PerHandleData->Socket,::GetCurrentThreadId());
send(PerHandleData->Socket,sendBuf,strlen(sendBuf)+,);
//WSASend()
/*DataBuf.len = DATA_BUFSIZE;
DataBuf.buf = buffer;
for(i=0; i < SEND_COUNT ;i++) {
WSASend(PerHandleData->Socket, &DataBuf, 1, &SendBytes, 0, &SendOverlapped, NULL); */ // 成功了!!!这儿就收到了来自客户端的数据
cout << PerIoData->DataBuf.buf << ::GetCurrentThreadId() << endl; Flags = ;
// 为下一个重叠调用建立单I/O 操作数据
ZeroMemory(&(PerIoData->Overlapped), sizeof(OVERLAPPED)); PerIoData->DataBuf.len = ;
PerIoData->DataBuf.buf = PerIoData->buffer;
PerIoData->OperationType = ; // read WSARecv(PerHandleData->Socket,&(PerIoData->DataBuf),,&RecvBytes,&Flags,&(PerIoData->Overlapped),NULL);
}
return ;
} int main(int argc, _TCHAR* argv[])
{
//头部申明
HANDLE CompletionPort;
WSADATA wsd;
SYSTEM_INFO SystemInfo;
SOCKADDR_IN InternetAddr;
SOCKET Listen; // 加载WinSock2.2
WSAStartup(MAKEWORD(, ), &wsd); // 1.创建一个I/O 完成端口
CompletionPort = CreateIoCompletionPort(INVALID_HANDLE_VALUE,NULL,,); // 2.确定系统中有多少个处理器
GetSystemInfo(&SystemInfo); // 3.基于系统中可用的处理器数量创建工作器线程
for (int i = ; i < int(SystemInfo.dwNumberOfProcessors * ); ++i)
{
HANDLE ThreadHandle;
// 创建一个服务器的工作器线程,并将完成端口传递到该线程
ThreadHandle = CreateThread(NULL,,ServerWorkerThread,CompletionPort,,NULL);
CloseHandle(ThreadHandle);
} // 4.创建一个监听套接字,以下的套路都是固定的。
Listen = WSASocket(AF_INET,SOCK_STREAM,,NULL,,WSA_FLAG_OVERLAPPED); //绑定和监听
InternetAddr.sin_family = PF_INET;
InternetAddr.sin_port = htons();
InternetAddr.sin_addr.s_addr = htonl(INADDR_ANY);
bind(Listen, (SOCKADDR*)&InternetAddr, sizeof(InternetAddr));
listen(Listen, ); //无限循环
BOOL b = TRUE;
while (b)
{
PER_HANDLE_DATA * PerHandleData = NULL;
SOCKADDR_IN saRemote;
SOCKET Accept;
int RemoteLen;
// 5.接收连接,并分配完成端口,这儿可以用AcceptEx 来代替,以创
// 建可伸缩的Winsock 应用程序。
RemoteLen = sizeof(saRemote);
Accept = accept(Listen, (SOCKADDR*)&saRemote, &RemoteLen); // 6.创建用来和套接字关联的单句柄数据信息结构
PerHandleData = (LPPER_HANDLE_DATA)GlobalAlloc(GPTR,sizeof(PER_HANDLE_DATA)); //cout << "Socket number " << Accept << " connected" << endl; PerHandleData->Socket = Accept;
memcpy(&PerHandleData->ClientAddr, &saRemote, RemoteLen); // 7.将接受套接字和完成端口关联起来
CreateIoCompletionPort((HANDLE)Accept,CompletionPort,(DWORD)PerHandleData,); // 开始在接受套接字上处理I/O
// 使用重叠I/O 机制,在新建的套接字上投递一个或多个异步
// WSARecv 或 WSASend 请求。这些I/O 请求完成后,工作者线程
// 会为I/O 请求提供服务,之后就可以坐享其成了
static int const DATA_BUFSIZE = ;
DWORD RecvBytes = ;
DWORD Flags = ; // 单I/O 操作数据
LPPER_IO_DATA PerIoData = NULL;
PerIoData = (LPPER_IO_DATA)GlobalAlloc(GPTR, sizeof(PER_IO_DATA));
ZeroMemory(&(PerIoData->Overlapped), sizeof(OVERLAPPED));
PerIoData->DataBuf.len = ;
PerIoData->DataBuf.buf = PerIoData->buffer;
PerIoData->OperationType = ; // read
WSARecv(PerHandleData->Socket,&(PerIoData->DataBuf),,&RecvBytes,&Flags,&(PerIoData->Overlapped),NULL);
} return ;
}
客户端:
#include "stdafx.h"
#include <Winsock2.h>
#pragma comment(lib, "ws2_32.lib")
#include <stdio.h> void main()
{
WORD wVersionRequested;
WSADATA wsaData;
int err; wVersionRequested = MAKEWORD( , ); err = WSAStartup( wVersionRequested, &wsaData );
if ( err != ) {
return;
} if ( LOBYTE( wsaData.wVersion ) != ||
HIBYTE( wsaData.wVersion ) != ) {
WSACleanup( );
return;
} while (true)
{
SOCKET sockClient=socket(AF_INET,SOCK_STREAM,); SOCKADDR_IN addrSrv;
addrSrv.sin_addr.S_un.S_addr=inet_addr("127.0.0.1");
addrSrv.sin_family=AF_INET;
addrSrv.sin_port=htons();
connect(sockClient,(SOCKADDR*)&addrSrv,sizeof(SOCKADDR)); send(sockClient,"This is lisi",strlen("This is lisi")+,); char recvBuf[];
recv(sockClient,recvBuf,,);
printf("%s\n",recvBuf); closesocket(sockClient);
} WSACleanup();
}
I/O完成端口(IOCP)的更多相关文章
- DELPHI中完成端口(IOCP)的简单分析(4)
DELPHI中完成端口(IOCP)的简单分析(4) 在我以前写的文章中,一直说的是如何接收数据.但是对于如何发送数据却一点也没有提到.因为从代码量上来说接收的代码要比发送多很多.今天我就来写一下如 ...
- DELPHI中完成端口(IOCP)的简单分析(3)
DELPHI中完成端口(IOCP)的简单分析(3) fxh7622关注4人评论7366人阅读2007-01-17 11:18:24 最近太忙,所以没有机会来写IOCP的后续文章.今天好不容易有 ...
- DELPHI中完成端口(IOCP)的简单分析(2)
DELPHI中完成端口(IOCP)的简单分析(2) 今天我写一下关于DELPHI编写完成端口(IOCP)的工作者线程中的东西.希望各位能提出批评意见.上次我写了关于常见IOCP的代码,对于IOCP ...
- DELPHI中完成端口(IOCP)的简单分析(1)
DELPHI中完成端口(IOCP)的简单分析(1) 用DELPHI开发网络代码已经有一段时间了! 我发现在网上用VC来实现完成端口(IOCP)的代码很多,但是使用DELPHI来实现的就比较少了.对 ...
- 完成端口iocp——在螺丝壳里做道场
WINDOWS 2000以后的操作系统才支持IOCP.WINSOCK2.0才支持IOCP. 首先要有一个WINSOCK2.PAS的WINSOCK2.0接口调用声明单元. WINSOCK的版本号: WI ...
- 【windows核心编程】IO完成端口(IOCP)复制文件小例前简单说明
1.关于IOCP IOCP即IO完成端口,是一种高伸缩高效率的异步IO方式,一个设备或文件与一个IO完成端口相关联,当文件或设备的异步IO操作完成的时候,去IO完成端口的[完成队列]取一项,根据完成键 ...
- 完成端口IOCP详解
修改自: http://blog.csdn.net/piggyxp/article/details/6922277 ps: 原作者很厉害了, 把一个iocp模型讲解的这么形象,不过在实践过程中发现一些 ...
- TCP服务器并发编程构架:完成端口IOCP模式
windows下socket网络编程模式:IOCP 完成端口 1)IOCP异步事件的获取放到操作系统的网络驱动层来处理,实际上反而是降低了编程难度, 2)同时对于多线程的并发调度,也放到操作系统级别来 ...
- 套接字I/O模型-完成端口IOCP
“完成端口”模型是迄今为止最为复杂的一种I/O模型.然而,假若一个应用程序同时需要管理为数众多的套接字,那么采用这种模型,往往可以达到最佳的系统性能!但不幸的是,该模型只适用于Windows NT和W ...
- 完成端口(IOCP)怎么判断某个连接是否断开
完成端口函数: BOOL GetQueuedCompletionStatus( HANDLE CompletionPort, LPDWORD lpNumberOfBytes, PULONG_PTR l ...
随机推荐
- 自学Hadoop
一.Hadoop基础设施 起源于Google的三篇论文: 1. <The Google File System > 2003年 http://static.googleuserconten ...
- Python3一些包的下载
首先在windows的Python扩展包网址:http://www.lfd.uci.edu/~gohlke/pythonlibs/ 这里举例下载opencv3.2.0的安装包 我的电脑是win10,6 ...
- SDNLAB技术分享(四):利用ODL下发流表创建VxLAN网络
邓晓涛,当前就职于江苏省未来网络创新研究院,是CDN团队的一名研发人员,主要从事SDN相关的研发相关工作.曾就职于三星电子于先行解决方案研发组任高级工程师.思科系统于云协作应用技术部(CCATG)任工 ...
- js简单工厂
我以计算器为例写一个简单工厂模式,只完成加减乘除4个计算功能,考虑到其他功能方便日后扩展,遵循开放-封闭原则. 简单工厂类图: 先看一下C#的简单工厂是如何实现的: 定义抽象类Operation,加减 ...
- hdu 1517 A Multiplication Game(必胜态,必败态)
A Multiplication Game Time Limit: 5000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Ot ...
- uva10648 概率dp
https://vjudge.net/problem/UVA-10648 将n个不同小球放入m个不同盒子,放入每个盒子的概率相同,问放完之后仍有空盒子的概率: 还是太傻- -,可以倒着计算出放完之后没 ...
- I.MX6 make menuconfig进入x86模式
/************************************************************************ * I.MX6 make menuconfig进入x ...
- 【LeetCode】005. Longest Palindromic Substring
Given a string s, find the longest palindromic substring in s. You may assume that the maximum lengt ...
- SVM模型进行分类预测时的参数调整技巧
一:如何判断调参范围是否合理 正常来说,当我们参数在合理范围时,模型在训练集和测试集的准确率都比较高:当模型在训练集上准确率比较高,而测试集上的准确率比较低时,模型处于过拟合状态:当模型训练集和测试集 ...
- Java实现Bag类
Java实现Bag类 import java.util.Iterator; import java.util.NoSuchElementException; import java.util.Scan ...