iocp详解_iocp是异步io吗

iocp详解_iocp是异步io吗#include”SOCKET.h”#includeDWORDWINAPIThreadProc(LPVOIDpvParam);#definePORT8080#defineLISTEN_QUEUE200//AcceptEx和GetAcceptExSockaddrs的函数指针,用于调用这两个扩展函数LPFN_ACCEPTEX       

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全系列IDE稳定放心使用
#include “SOCKET.h”

#include <Windows.h>

DWORD WINAPI ThreadProc(LPVOID pvParam);

#define PORT
8080

#define LISTEN_QUEUE
200

// AcceptEx 和 GetAcceptExSockaddrs 的函数指针,用于调用这两个扩展函数

LPFN_ACCEPTEX                lpfnAcceptEx;                

LPFN_GETACCEPTEXSOCKADDRS
lpfnGetAcceptExSockAddrs; 

void PostAcceptEx(IOCPHandle_s & listenHandle)

{


IO_DATA_s * p_io_data = new IO_DATA_s;


p_io_data->socket = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);


listenHandle.Push(p_io_data);


p_io_data->type = ACCEPT;


lpfnAcceptEx(listenHandle.socket, p_io_data->socket, &p_io_data->addr, 0, 0, sizeof(SOCKADDR_IN) + 16, &p_io_data->len, &p_io_data->ol);

}

int main()

{


SocketInit();


IOCPHandle_s
listenHandle;


listenHandle.socket = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);


listenHandle.addr.sin_family = AF_INET;


listenHandle.addr.sin_addr.S_un.S_addr = htonl(INADDR_ANY);


listenHandle.addr.sin_port = htons(PORT);


HANDLE
IOCPhandle;


IOCPhandle = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 0 );


::CreateThread(0, 0, ThreadProc, (void *)IOCPhandle, 0, 0);


::bind(listenHandle.socket, (SOCKADDR *)&listenHandle.addr, sizeof(SOCKADDR));


::listen(listenHandle.socket, LISTEN_QUEUE);


CreateIoCompletionPort((HANDLE)listenHandle.socket, IOCPhandle, (unsigned long)&listenHandle, 0);


// 使用AcceptEx函数,因为这个是属于WinSock2规范之外的微软另外提供的扩展函数


// 所以需要额外获取一下函数的指针,


// 获取AcceptEx函数指针


GUID GuidAcceptEx = WSAID_ACCEPTEX;  


GUID GuidGetAcceptExSockAddrs = WSAID_GETACCEPTEXSOCKADDRS; 


DWORD dwBytes = 0;  


WSAIoctl(


listenHandle.socket, 


SIO_GET_EXTENSION_FUNCTION_POINTER, 


&GuidAcceptEx, 


sizeof(GuidAcceptEx), 


&lpfnAcceptEx, 


sizeof(lpfnAcceptEx), 


&dwBytes, 


NULL, 


NULL);


// 获取GetAcceptExSockAddrs函数指针,也是同理


WSAIoctl(


listenHandle.socket, 


SIO_GET_EXTENSION_FUNCTION_POINTER, 


&GuidGetAcceptExSockAddrs,


sizeof(GuidGetAcceptExSockAddrs), 


&lpfnGetAcceptExSockAddrs, 


sizeof(lpfnGetAcceptExSockAddrs),   


&dwBytes, 


NULL, 


NULL);


for(i32 i = 0 ; i < 50 ; ++i)


PostAcceptEx(listenHandle);


printf(“主线程阻塞\n”);


Sleep(INFINITE);


SocketUnInit();


getchar();


return 0;

}

DWORD WINAPI ThreadProc(LPVOID pvParam)

{


HANDLE
IOCPhandle = pvParam;


DWORD   dwBytesTransfered = 0;


IOCPHandle_s * p_IOCPhandle;


IO_DATA_s * p_IOdata;


BOOL bReturn;


while(true)


{



//实际操作字节数


bReturn = GetQueuedCompletionStatus(IOCPhandle,&dwBytesTransfered,(unsigned long *)&p_IOCPhandle,(OVERLAPPED **)&p_IOdata,INFINITE);


if(!bReturn)


{


printf(“出错\n”);


closesocket(p_IOCPhandle->socket);


delete p_IOCPhandle;


delete p_IOdata;


continue;


}


else if(dwBytesTransfered == 0 && (p_IOdata->type == RECV || p_IOdata->type == SEND))


{


printf(“客户端关闭了连接!\n”);


closesocket(p_IOCPhandle->socket);


delete p_IOCPhandle;


delete p_IOdata;


}


else


{


printf(“处理IO服务\n”);


switch(p_IOdata->type)


{


case RECV:


{


printf(“RECV\n”);


p_IOdata->buf.buf[dwBytesTransfered] = ‘\0’;


printf(“数据:%s 长度:%d\n”,p_IOdata->buf.buf,dwBytesTransfered);


p_IOdata->SetZero();


p_IOdata->type = RECV;


p_IOdata->buf.buf = p_IOCPhandle->recv_buff;


p_IOdata->buf.len = BUFF_SIZE;


p_IOdata->flags = 0;


int nBytesRecv = WSARecv(p_IOCPhandle->socket, &p_IOdata->buf, 1, &p_IOdata->len, &p_IOdata->flags, &p_IOdata->ol, 0);


int ret = WSAGetLastError();


if ((SOCKET_ERROR == nBytesRecv) && (WSA_IO_PENDING != ret))


{


printf(“投递RECV失败\n”);


}


}


break;


case SEND:


{





}


break;


case ACCEPT:


{


printf(“ACCEPT\n”);


IOCPHandle_s * p_accepthandle = new IOCPHandle_s;


p_accepthandle->socket = p_IOdata->socket;


//赋值SOCKET的属性与LISTENSOCKET的属性一样


setsockopt( p_accepthandle->socket,


SOL_SOCKET,


SO_UPDATE_ACCEPT_CONTEXT,


(char*)&p_IOCPhandle->socket,


sizeof(p_IOCPhandle->socket) ) ;


//lpfnGetAcceptExSockAddrs(&p_IOdata->buf.buf,0, 0, sizeof(SOCKADDR_IN) + 16, 0, 0, (LPSOCKADDR*)&p_addr, &remoteLen);


//memcpy(&p_accepthandle->addr, &p_IOdata->addr, sizeof(SOCKADDR_IN) + 16);


//printf(“IP:%s 端口:%d\n”,inet_ntoa(p_accepthandle->addr.sin_addr),ntohs(p_accepthandle->addr.sin_port));


IO_DATA_s * p_iodata = new IO_DATA_s;


p_accepthandle->Push(p_iodata);


CreateIoCompletionPort((HANDLE)p_accepthandle->socket, IOCPhandle, (unsigned long)p_accepthandle, 0);


p_iodata->type = RECV;


p_iodata->buf.buf = p_accepthandle->recv_buff;


p_iodata->buf.len = BUFF_SIZE;


p_iodata->flags = 0;


int nBytesRecv = WSARecv(p_accepthandle->socket, &p_iodata->buf, 1, &p_iodata->len, &p_iodata->flags, &p_iodata->ol, 0);


if ((SOCKET_ERROR == nBytesRecv) && (WSA_IO_PENDING != WSAGetLastError()))


{


printf(“投递RECV失败\n”);


return false;


}


p_IOdata->SetZero();


p_IOdata->socket = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);


p_IOdata->type = ACCEPT;


lpfnAcceptEx(p_IOCPhandle->socket, p_IOdata->socket, &p_IOdata->addr, 0, 0, sizeof(SOCKADDR_IN) + 16, &p_IOdata->len, &p_IOdata->ol);


}


break;


default:


break;


}


}


 


}


return 0;

}

/*******************************************************SOCKET.h************************************************/

#include <winsock2.h>
#include <ws2tcpip.h>
#include <fcntl.h>
#include <MSWSock.h>
#include <vector>
#include <string.h>
#pragma comment(lib ,”ws2_32″)
void SocketInit()
{

WSADATA wsaData;// 库
WSAStartup(MAKEWORD(2,2),&wsaData); //初始化
}
void SocketUnInit()
{

WSACleanup();//关闭
}
#define BUFF_SIZE 120
enum TYPE {SEND,RECV,ACCEPT,INIT};
typedef int i32;
typedef char i8;
typedef unsigned int u32;
typedef unsigned char u8;

struct IO_DATA_s
{

IO_DATA_s()
{

type = INIT;
SetZero();
}
WSAOVERLAPPED ol;
SOCKET socket; //操作的SOCKET
SOCKADDR_IN addr; //地址
DWORD len; //操作长度
DWORD flags; //标志
TYPE type; //操作类型
WSABUF buf; //WindowBUF
void SetZero()
{

memset(this, 0, sizeof(IO_DATA_s));
}
};
struct IOCPHandle_s
{

SOCKET socket; //套接字
SOCKADDR_IN addr; //地址
std::vector<IO_DATA_s *> io_array; //IO操作的地址
i8 send_buff[BUFF_SIZE]; //发送缓存
DWORD send_len;
char recv_buff[BUFF_SIZE]; //接收缓存
DWORD recv_len;
void Push(IO_DATA_s * v)
{

io_array.push_back(v);
}
};

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/187962.html原文链接:https://javaforall.net

(0)
上一篇 2026年4月17日 下午11:49
下一篇 2026年4月17日 下午11:55


相关推荐

  • 什么是SPU和SKU

    什么是SPU和SKUSPU StandardProd nbsp 标准产品单位 nbsp 概念 SPU 是商品信息聚合的最小单位 是一组可复用 易检索的标准化信息的集合 该集合描述了一个产品的特性 nbsp 通俗点讲 属性值 特性相同的货品就可以称为一个 SPU nbsp 例如 iphone7 就是一个 SPU 与商家 与颜色 款式 套餐都无关 nbsp nbsp nbsp nbsp nbsp nbsp nbsp nbsp nbsp nbsp nbsp nbsp nbsp nbsp nbsp nbsp nbsp

    2026年3月26日
    2
  • 数组和链表的区别以及应用场景

    数组和链表的区别以及应用场景数组和链表的区别以及应用场景首先我们要先理解什么是数组和链表在计算机中要对给定的数据集进行若干处理 首要任务是把数据集的一部分 当数据量非常大时 可能只能一部分一部分地读取数据到内存中来处理 或全部存储到内存中 然后再对内存中的数据进行各种处理 例如 对于数据集 S 1 2 3 4 5 6 要求 S 中元素的和 首先要把数据存储到内存中 然后再将内存中的数据相加 当内存空间中有足够大的

    2026年3月17日
    2
  • Maven中央仓库地址大全,Maven中央仓库配置示例

    Maven中央仓库地址大全,Maven中央仓库配置示例nbsp nbsp nbsp nbsp nbsp nbsp nbsp nbsp nbsp nbsp nbsp nbsp nbsp nbsp nbsp nbsp nbsp nbsp nbsp Maven 中央仓库地址大全 在上一篇文章中完成了 nbsp Maven 镜像地址大全 后来又花了时间又去收集并整理了关于 maven 远程仓库地址 并整理于此 关于 Maven 远程仓库地址的配置方式有两种 第一种 直接在项目的 pom xml 文件中进行修改 不推荐 尤其是在多人协助的开发过程中非常的费事费

    2026年3月16日
    2
  • Gherkin简单使用

    Gherkin简单使用Gherkin 简单使用 1 Gherkin 简介 Cucumber 是一个解释程序 就像 ruby 命令执行解释 rb 文件里的 Ruby 代码一样 Cucumber 用来执行解释 feature 文件里的 Gehrkin 代码 2 关键字 当你编写一个 feature 文件的时候 会用到很多 Gherkin 语言里特定的关键字 主要包括下这面些 Feature Background Scenari

    2026年3月20日
    2
  • ActivityManager解析及使用

    ActivityManager解析及使用前言 Activity 可以获取运行中的应用信息 可以获取到 servcie process app memory 信息等 获取信息 ActivityMana MemoryInfoMe 中重要的字段 availMem 系统可用内存 totalMem 总内存 threshold 低内存阈值 即低内存的临界线 lowMemory 是否为低内存状态 Debug M

    2025年8月7日
    27
  • 腾讯元宝电脑版更新!支持大字体、拖拽上传文件图片

    腾讯元宝电脑版更新!支持大字体、拖拽上传文件图片

    2026年3月13日
    2

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号