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 ...
随机推荐
- 如何使用eclipse生成javadoc帮助文档
---恢复内容开始--- 如果你已经能制造轮子了,你想让其他人使用你的轮子,那你就得告诉他们你的轮子都是由什么构成的.这样他们才能更好的使用你制造的轮子.然而,很多开发者都不想写长篇大论的帮助文档,这 ...
- utf8+bom格式保存php curl乱码问题
今天开发遇到一个php curl取数据乱码问题 不是gzip也不是编码设置问题 最后有一同事判断为utf8+bom保存数据原因,懒得深入了解utf8+bom,仅做记录 [root@centos5 ~] ...
- 第七课 GC资源管理器实验
<GC资源管理器> 要求: 1.定义2个资源消耗组(OLTP事务处理资源消耗组和DSS数据仓库资源消耗组) 2.创建一个日程计划schedule 3.对于OLTP资源消耗组,我们最多不 ...
- 动态Script标签 解决跨域问题
动态Script 解决跨域问题 1.动态创建scriptcreateScript : function(src){ var varScript = document.createElement(&q ...
- stackoverflow收藏
Make a video using several .png images http://stackoverflow.com/q/13590976/5624248 Specifying and sa ...
- Mocha 从0开始
Mocha Mocha 是具有丰富特性的 JavaScript 测试框架,可以运行在 Node.js 和浏览器中,使得异步测试更简单更有趣.Mocha 可以持续运行测试,支持灵活又准确的报告,当映射到 ...
- EditText无法失去焦点、失去焦点隐藏软键盘
很奇怪,我在给EditText设置setOnFocusChangeListener()监听,但是始终未能成功,焦点一直存在,不知其原因,,代码如下: et_username.setOnFocusCha ...
- Javascript 装载和执行
http://coolshell.cn/articles/9749.html http://www.cnblogs.com/cheche/archive/2011/03/06/1971955.html
- IOS深入学习(1)之图标文件(icon files)
1 前言 我相信大家在做IOS一定经常会跟图标文件(icon files)打交道,今天我们就来简单的学习一下iPhone和iPad程序中的icon files. 2 详述 除了iTunesArtwor ...
- poj1552---枚举
#include <stdio.h> #include <stdlib.h> int main() { ],th=,i,j; while(scanf("%d" ...