C iOcp
#include <winsock2.h>
//#include <windows.h>
#include <stdio.h> #define PORT 5150
#define DATA_BUFSIZE 8192 typedef struct
{
OVERLAPPED Overlapped;
WSABUF DataBuf;
CHAR Buffer[DATA_BUFSIZE];
DWORD BytesSEND;
DWORD BytesRECV;
} PER_IO_OPERATION_DATA, * LPPER_IO_OPERATION_DATA; typedef struct
{
SOCKET Socket;
} PER_HANDLE_DATA, * LPPER_HANDLE_DATA; DWORD WINAPI ServerWorkerThread(LPVOID CompletionPortID); int main(void)
{
SOCKADDR_IN InternetAddr;
SOCKET Listen;
SOCKET Accept;
HANDLE CompletionPort;
SYSTEM_INFO SystemInfo;
LPPER_HANDLE_DATA PerHandleData;
LPPER_IO_OPERATION_DATA PerIoData;
int i;
DWORD RecvBytes;
DWORD Flags;
DWORD ThreadID;
WSADATA wsaData;
DWORD Ret; if ((Ret = WSAStartup(0x0202, &wsaData)) != )
{
printf("WSAStartup失败了,错误信息如下: %d\n", Ret);
return;
} // 设置一个I/O完成端口. if ((CompletionPort = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, , )) == NULL)
{
printf( "CreateIoCompletionPort 失败了,错误信息如下: %d\n", GetLastError());
return;
} // 测试系统中有多少cpu处理器 GetSystemInfo(&SystemInfo); // 基于系统可用的处理器创建工作线程,为每个处理器创建连个线程 for(i = ; i < SystemInfo.dwNumberOfProcessors * ; i++)
{
HANDLE ThreadHandle; // 创建一个服务端线程并且传递一个完成端口给这个线程. if ((ThreadHandle = CreateThread(NULL, , ServerWorkerThread, CompletionPort,
, &ThreadID)) == NULL)
{
printf("CreateThread()发生了如下错误: %d\n", GetLastError());
return;
}
else
{printf("创建了一个完成端口.\n");
}
// 关闭 thread句柄
CloseHandle(ThreadHandle);
} // 创建一个监听套接字 if ((Listen =WSASocket(AF_INET, SOCK_STREAM, , NULL,,WSA_FLAG_OVERLAPPED)) == INVALID_SOCKET)
{
printf("WSASocket() 发生了如下错误: %d\n", WSAGetLastError());
return;
}
else
{printf("创建监听套接字成功\n");}
InternetAddr.sin_family = AF_INET;
InternetAddr.sin_addr.s_addr = htonl(INADDR_ANY);
InternetAddr.sin_port = htons(PORT); if (bind(Listen, (PSOCKADDR) &InternetAddr, sizeof(InternetAddr)) == SOCKET_ERROR)
{
printf("bind()端口或IP时发生了如下错误: %d\n", WSAGetLastError());
return;
}
else
{printf("绑定端口%d成功\n",PORT);}
// 准备socket 用来监听 if (listen(Listen, ) == SOCKET_ERROR)
{
printf("listen() 发生了如下错误 %d\n", WSAGetLastError());
return;
}
else
{printf("预处理成功,开始在端口 %d 处监听...\n",PORT);}
//接受连接并且交给完成端口处理 while(TRUE)
{
if ((Accept = WSAAccept(Listen, NULL, NULL, NULL, )) == SOCKET_ERROR)
{
printf("WSAAccept() 发生了如下错误: %d\n", WSAGetLastError());
return;
} // 创建一个套接字信息结构体去联系起来socket
if ((PerHandleData = (LPPER_HANDLE_DATA) GlobalAlloc(GPTR,
sizeof(PER_HANDLE_DATA))) == NULL)
{
printf("GlobalAlloc() 发生了如下错误: %d\n", GetLastError());
return;
} // 将接受到的套接字与原始的完成端口联系起来. printf("号码为 %d 的socket连接上了\n", Accept);
PerHandleData->Socket = Accept; if (CreateIoCompletionPort((HANDLE) Accept, CompletionPort, (DWORD) PerHandleData,
) == NULL)
{
printf("CreateIoCompletionPort 发生了如下错误: %d\n", GetLastError());
return;
} // 创建每一个I/O 套接字信息结构体去和下面被调用的 to associate with the
// WSARecv 连接. if ((PerIoData = (LPPER_IO_OPERATION_DATA) GlobalAlloc(GPTR, sizeof(PER_IO_OPERATION_DATA))) == NULL)
{
printf("GlobalAlloc() 发生了如下错误: %d\n", GetLastError());
return;
}
else{printf("接收了一个连接\n");}
ZeroMemory(&(PerIoData->Overlapped), sizeof(OVERLAPPED));
PerIoData->BytesSEND = ;
PerIoData->BytesRECV = ;
PerIoData->DataBuf.len = DATA_BUFSIZE;
PerIoData->DataBuf.buf = PerIoData->Buffer; Flags = ;
if (WSARecv(Accept, &(PerIoData->DataBuf), , &RecvBytes, &Flags,
&(PerIoData->Overlapped), NULL) == SOCKET_ERROR)
{
if (WSAGetLastError() != ERROR_IO_PENDING)
{
printf("WSARecv() 发生了如下错误: %d\n", WSAGetLastError());
return;
}
}
}
} DWORD WINAPI ServerWorkerThread(LPVOID CompletionPortID)
{
HANDLE CompletionPort = (HANDLE) CompletionPortID;
DWORD BytesTransferred;
LPOVERLAPPED Overlapped;
LPPER_HANDLE_DATA PerHandleData;
LPPER_IO_OPERATION_DATA PerIoData;
DWORD SendBytes, RecvBytes;
DWORD Flags; while(TRUE)
{ if (GetQueuedCompletionStatus(CompletionPort, &BytesTransferred,
(LPDWORD)&PerHandleData, (LPOVERLAPPED *) &PerIoData, INFINITE) == )
{
printf("GetQueuedCompletionStatus 发生了如下错误: %d\n", GetLastError());
return ;
} //首先检查一下去套接字看是否在上发生了错误并且如果发生了错误就关闭套接
//字并且清除与套接字连接的 SOCKET_INFORMATION结构信息体
if (BytesTransferred == )
{
printf("正在关闭socket %d\n", PerHandleData->Socket); if (closesocket(PerHandleData->Socket) == SOCKET_ERROR)
{
printf("closesocket() 发生了如下错误: %d\n", WSAGetLastError());
return ;
} GlobalFree(PerHandleData);
GlobalFree(PerIoData);
continue;
}
//检查如果 BytesRECV字段等于0,这就意味着一个 WSARecv调用刚刚完成了所以从完成的WSARecv()调用中
//用BytesTransferred值更新 BytesRECV字段
if (PerIoData->BytesRECV == )
{
PerIoData->BytesRECV = BytesTransferred;
PerIoData->BytesSEND = ;
}
else
{
PerIoData->BytesSEND += BytesTransferred;
} if (PerIoData->BytesRECV > PerIoData->BytesSEND)
{
//发布另外一个 WSASend()请求
//既然WSASend()不是 gauranteed去发送所有字节的请求
//继续调用 WSASend()发送直到所有收到的字节被发送 ZeroMemory(&(PerIoData->Overlapped), sizeof(OVERLAPPED)); PerIoData->DataBuf.buf = PerIoData->Buffer + PerIoData->BytesSEND;
PerIoData->DataBuf.len = PerIoData->BytesRECV - PerIoData->BytesSEND; if (WSASend(PerHandleData->Socket, &(PerIoData->DataBuf), , &SendBytes, ,
&(PerIoData->Overlapped), NULL) == SOCKET_ERROR)
{
if (WSAGetLastError() != ERROR_IO_PENDING)
{
printf("WSASend() 发生了如下错误: %d\n", WSAGetLastError());
return ;
}
}
}
else
{
PerIoData->BytesRECV = ;
//现在没有更多的字节发送过去用来post另外一个WSARecv()请求 Flags = ;
ZeroMemory(&(PerIoData->Overlapped), sizeof(OVERLAPPED)); PerIoData->DataBuf.len = DATA_BUFSIZE;
PerIoData->DataBuf.buf = PerIoData->Buffer; if (WSARecv(PerHandleData->Socket, &(PerIoData->DataBuf), , &RecvBytes, &Flags,
&(PerIoData->Overlapped), NULL) == SOCKET_ERROR)
{
if (WSAGetLastError() != ERROR_IO_PENDING)
{
printf("WSARecv() 发生了如下错误: %d\n", WSAGetLastError());
return ;
}
}
}
}
}
C iOcp的更多相关文章
- IOCP Internals
Buffer Type Buffer I/O 针对Buffer I/O的请求,系统会为其分配一个非换页内存作为缓存区,其大小等同于I/O请求的缓存区大小.对于写操作,I/O管理器在创建IRP时,将请求 ...
- iocp 小例子
2016-08-3116:44:09 server 端 /******************************************************************* aut ...
- 简单说一个IOCP不好的地方
感谢rulary的指正!博文中我对IOCP的理解是有误的,正确的方式请见评论区rulary的回复! 由于项目实际设计的需要,最终IO事件处理没有采用IOCP,而是采用了NT6.0引入的WSAPoll, ...
- IOCP和WSA异步协同客户端版
有些小伙伴看了之前发的WIN平台下IOCP和WSA异步协同处理SOCKET后有些疑惑,所以就画了个简易流程图+架构图发上来给小伙伴参考 简单说,WSA异步控制CONNECT,IOCP控制WSASend ...
- windows WSABUF 结构在IOCP 中应用时两个成员变量的意义
WSABUF 结构的原型如下: typedef struct __WSABUF { u_long len; char FAR *buf; } WSABUF, *LPWSABUF; 该结构在IOCP 中 ...
- IOCP入门
完成端口(Completion Port)详解 此文讲解最好,也很全面一下其他文章看看就行,也可不看. 单句柄数据,单IO数据 此文讲述比较清晰,可以辅助理解上文. IOCP编程之基本原理:http: ...
- iocp还是select
上一个项目libevent应该是select,现在libuv是iocp,都知道Windows下iocp比select效率高,boost asio 也是iocp,但具体使用select和iocp发现没有 ...
- 再谈select, iocp, epoll,kqueue及各种I/O复用机制
原文:http://blog.csdn.net/shallwake/article/details/5265287 首先,介绍几种常见的I/O模型及其区别,如下: blocking I/O nonbl ...
- TCP协议下大数据传输IOCP乱序问题
毕业后稀里糊涂的闭门造车了两年,自己的独立博客也写了两年,各种乱七八糟,最近准备把自己博客废了,现在来看了下这两年写的对我来说略微有点意义的文章只此一篇,转载过来以作留念. 写的很肤浅且凌乱,请见谅. ...
- 高性能完成端口socket服务(IOCP)
1. Winsock IO模型之IOCP模型 来自csdn blog,版权声明:本文为博主原创文章,未经博主允许不得转载. 我这里记录下,不算转载吧 http://blog.csdn.net/lost ...
随机推荐
- 自学SQL语言的例子(使用MySQL实现)
SQL语言作为一种数据库管理的标准语言有着极为广泛的应用场景,菜鸟入门选用的数据库软件是轻量级的免费(这个极为重要)的MySQL,下载链接如下:http://www.mysql.com/downloa ...
- WebView缓存
文章从:http://www.360doc.com/content/14/0611/13/15210553_385676271.shtml 摘录而来 当webview加载html页面时,会在/dat ...
- JS函数作用域及作用域链理解
从事web开发工作,尤其主要是做服务器端开发的,难免会对客户端语言JavaScript一些概念有些似懂非懂的,甚至仅停留在实现功能的层面上,接下来的文章,是记录我对JavaScript的一些概念的理解 ...
- How to Use the UTL_MAIL Package
APPLIES TO: PL/SQL - Version 10.1.0.2 and laterInformation in this document applies to any platform. ...
- CSS3中新增的内容
(整理中······) 一.选择器 新增的伪类 1.p:first-of-type 选择属于其父元素的首个 <p> 元素的每个 <p> 元素. 2.p:last-of-ty ...
- 异常 ORA-00257: archiver error. Connect internal only, until freed
我oracle 是安装在linux 下. ORA-00257: archiver error. Connect internal only, until freed 得知是错误是由于归档日志(arch ...
- Fast InvSqrt()(平方根倒数速算法)
浮点数的平方根倒数常用于计算正规化矢量.3D图形程序需要使用正规化矢量来实现光照和投影效果,因此每秒都需要做上百万次平方根倒数运算,而在处理坐标转换与光源的专用硬件设备出现前,这些计算都由软件完成,计 ...
- Java提高学习之Object(4)
哈希码 问: hashCode()方法是用来做什么的? 答: hashCode()方法返回给调用者此对象的哈希码(其值由一个hash函数计算得来).这个方法通常用在基于hash的集合类中,像java. ...
- 关于ThreadAbortExcption异常处理
之前程序中,使用Thread.Abort()方法来终止线程的运行,但它是抛出ThreadAbortException异常来终止线程. 异常信息摘要: Unhandled Exception:Threa ...
- jira 解决结果配置
jira 的配置比较繁琐,有很多的小细节,使用中出现了各种小问题,总结梳理下 1.解决结果 问题1:编辑了任务后,解决结果变成了已解决 找到编辑任务所对应的界面方案,将解决结果字段从界面配置里移除 问 ...