IOCP模型TCP服务器
时间:2022-04-22
本文章向大家介绍IOCP模型TCP服务器,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
主线程创建监听套接字,创建额外工作线程,关联IOCP,负责等待和接受到来的连接。
调用GetQueuedCompletionStatus函数,函数返回:
1 调用失败
2 套接字被对方关闭
3 请求成功完成
程序首先定义per-handle per-IO的操作数据的结构类型
#define BUFFER_SIZE 1024
typedef struct _PER_HANDLE_DATA{
SOCKET s;
sockaddr_in addr;
}PER_HANDLE_DATA,*PPER_HANDLE_DATA;
typedef struct _PER_IO_DATA{
OVERLAPPED ol;
char buf[BUFFER_SIZE];
int nOperationType;
#define OP_READ 1
#define OP_WRITE 2
#define OP_ACCEPT 3
}PER_IO_DATA,*PPER_IO_DATA;
主要过程:
1 主线程创建完成端口对象,创建工作线程处理完成端口对象中的事件
2 创建监听套接字,开始监听服务器端口
3 进入无限循环,处理到来的请求
1)调用accept函数等待接受未决的连接请求 2)创建一个per-handle数据 3)投递一个接收请求
实现代码:
void main()
{
int nPort = 4567;
HANDLE hCompletion = ::CreateIoCompletionPort(INVALID_HANDLE_VALUE,0,0,0);
::CreateThread(NULL,0,ServerThread,(LPVOID)hCompletion,0,0);
SOCKET sListen = ::socket(AF_INET,SOCK_STREAM,0);
SOCKADDR_IN si;
si.sin_family = AF_INET;
si.sin_port = htons(nPort);
si.sin_addr.S_un.S_addr = INADDR_ANY;
::bind(sListen,(sockaddr*)&si,sizeof(si));
::listen(sListen,5);
while(TRUE){
//等待接收未决的请求
SOCKADDR_IN saRemote;
int nRemoteLen = sizeof(saRemote);
SOCKET sNew = ::accept(sListen,(sockaddr*)&saRemote,&nRemoteLen);
//创建per-handle
PPER_HANDLE_DATA pPerHandle = (PPER_HANDLE_DATA)::GlobalAlloc(GPTR,sizeof(PER_HANDLE_DATA));
pPerHandle->s = sNew;
memcpy(&pPerHandle->addr,&saRemote,nRemoteLen);
::CreateIoCompletionPort((HANDLE)pPerHandle->s,hCompletion,(DWORD)pPerHandle,0);
//投递一个接收请求
PPER_IO_DATA pPerIO = (PPER_IO_DATA)::GlobalAlloc(GPTR,sizeof(PER_IO_DATA));
pPerIO->nOperationType = OP_READ;
WSABUF buf;
buf.buf = pPerIO->buf;
buf.len = BUFFER_SIZE;
DWORD dwRecv;
DWORD dwFlags = 0;
::WSARecv(pPerHandle->s,&buf,1,&dwRecv,&dwFlags,&pPerIO->ol,NULL);//接收投递求
}
}
DWORD WINAPI ServerThread(LPVOID lpParam{
HANDLE hCompletion = (HANDLE)lpParam;
DWORD dwTrans;
PPER_HANDLE_DATA pPerHandle;
PPER_IO_DATA pPerIO;
while(TRUE){
BOOL bOK = ::GetQueuedCompletionStatus(hCompletion,&dwTrans,(LPDWORD)&pPerHandle,(LPOVERLAPPED*)&pPerIO,WSA_INFINITE);
if(!bOK)
{
::closesocket(pPerHandle->s);
::GlobalFree(pPerHandle);
::GlobalFree(pPerIO);
continue;
}
if(dwTrans == 0 && (pPerIO->nOperationType==OP_READ||pPerIO->nOperationType==OP_WRITE))
{
::closesocket(pPerHandle->s);
::GlobalFree(pPerHandle);
::GlobalFree(pPerIO);
continue;
}
switch(pPerIO->nOperationType)
{
case OP_READ:
{
pPerIO->buf[dwTrans] = ' ';
printf(pPerIO->buf);
WSABUF buf;
buf.buf = pPerIO->buf;
buf.len = BUFFER_SIZE;
pPerIO->nOperationType = OP_READ;
DWORD nFlags = 0;
::WSARecv(pPerHandle->s,&buf,1,&dwTrans,&nFlags,&pPerIO->ol,NULL);
}
break;
case OP_WRITE:
case OP_ACCEPT:
break;
}
}
return 0;
}
- Silverlight:分包下载及SEO优化方案
- jQuery调用RESTful WCF示例(GET方法/POST方法)
- "RDLC"报表-参数传递及主从报表
- 初探小程序之运营及未来方向
- 微信小程序深夜开放NFC等连接能力,未来可直接刷公交?
- Silverlight:获取ContentTemplate中的命名控件
- silverlight向wcf传递大于8192字节(8k)的字符串
- vim使用笔记
- "RDLC报表"速成指南
- Silverlight:双向绑定综合应用-自动更新集合汇总字段
- Silverlight:双向绑定综合应用-多集合的依赖绑定
- python sorted排序用法详解
- Silverlight:MouseDragElementBehavior无法应用于ListBox的变相解决办法
- Silverlight:xap包(或本地缓存)下载版本更新的解决思路
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 原创 | 险些翻车,差一点没做出来的基础算法题
- 原创 | 你追我,如果你追到我……那就算你赢了
- 原创 | 详解gitignore的使用方法,让你尽情使用git add .
- 第31天:面试比 KMP 还容易被问到的匹配算法!
- 原创 | 深度学习开篇,来聊聊感知机的原理
- 算法题:输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字
- 使用Java和Python解题:定义栈的数据结构,请在该类型中实现一个能够得到栈中所含最小元素的min函数(时间复杂度应为O(1))。
- R语言中%||%是什么意思?
- 原创 | 你会用缓存吗?详解LRU缓存淘汰算法
- 用Java实现:输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否可能为该栈的弹出顺序。假设压入栈的所有数字均不相等。
- Hacking with iOS: SwiftUI Edition - Hot Prospects项目(一)
- 原创 | 详解command设计模式,解耦操作和回滚
- 第32天:图解大数打印,这道题如此经典!
- Mac终端配置好的环境变量在关闭终端后失效怎么办
- R中的stack和unstack函数