windows—IOCP
一、重叠I/O回声服务器端
服务端:
#include <stdio.h>
#include <stdlib.h>
#include <WinSock2.h> #define BUF_SIZE 1024
void ErrorHandling(char *message);
void CALLBACK ReadCompRoutine(DWORD, DWORD, LPWSAOVERLAPPED, DWORD);
void CALLBACK WriteCompRoutine(DWORD, DWORD, LPWSAOVERLAPPED, DWORD); typedef struct
{
SOCKET hClntSock;
char buf[BUF_SIZE];
WSABUF wsaBuf;
}PER_IO_DATA, *LPPER_IO_DATA; int main(int argc, char *argv[])
{
if (argc != ) {
printf("Usage : %s <port>\n", argv[]);
exit();
} WSADATA wsaData;
SOCKET hLinSock, hRecvSock;
SOCKADDR_IN lisnAdr, recvAdr;
LPWSAOVERLAPPED lpOvLp;
DWORD recvBytes;
LPPER_IO_DATA hbInfo;
int mode = , recvAdrSz, flagInfo = ; if (WSAStartup(MAKEWORD(, ), &wsaData) != )
ErrorHandling("WSAStartup() error."); hLinSock = WSASocket(PF_INET, SOCK_STREAM, , NULL, , WSA_FLAG_OVERLAPPED);
ioctlsocket(hLinSock, FIONBIO, (u_long*)&mode); // 套接字改成非阻塞的 memset(&lisnAdr, , sizeof(lisnAdr));
lisnAdr.sin_family = AF_INET;
lisnAdr.sin_addr.s_addr = htonl(INADDR_ANY);
lisnAdr.sin_port = htons(atoi(argv[])); if (bind(hLinSock, (SOCKADDR*)&lisnAdr, sizeof(lisnAdr)) == SOCKET_ERROR)
ErrorHandling("bind() error.");
if (listen(hLinSock, ) == SOCKET_ERROR)
ErrorHandling("listen() error.");
printf("Server start...\n");
recvAdrSz = sizeof(recvAdr);
while ()
{
SleepEx(, TRUE); // 让线程处于等待接收操作系统消息的线程状态
hRecvSock = accept(hLinSock, (SOCKADDR*)&recvAdr, &recvAdrSz);
if (hRecvSock == INVALID_SOCKET){
if (WSAGetLastError() == WSAEWOULDBLOCK)
continue;
else
ErrorHandling("accept() error");
}
puts("Client connected..."); lpOvLp = (LPWSAOVERLAPPED)malloc(sizeof(WSAOVERLAPPED));
memset(lpOvLp, , sizeof(lpOvLp)); hbInfo = (LPPER_IO_DATA)malloc(sizeof(PER_IO_DATA));
hbInfo->hClntSock = (DWORD)hRecvSock;
(hbInfo->wsaBuf).buf = hbInfo->buf;
(hbInfo->wsaBuf).len = BUF_SIZE; lpOvLp->hEvent = (HANDLE)hbInfo;
WSARecv(hRecvSock, &(hbInfo->wsaBuf), , &recvBytes, (LPDWORD)&flagInfo, lpOvLp, ReadCompRoutine);
}
closesocket(hRecvSock);
closesocket(hLinSock);
WSACleanup();
return ;
} void CALLBACK ReadCompRoutine(DWORD dwError, DWORD szRecvBytes, LPWSAOVERLAPPED lpOverlapped, DWORD flags)
{
LPPER_IO_DATA hbInfo = (LPPER_IO_DATA)(lpOverlapped->hEvent);
SOCKET hSock = hbInfo->hClntSock;
LPWSABUF bufInfo = &(hbInfo->wsaBuf);
DWORD sentBytes; if (szRecvBytes == )
{
closesocket(hSock);
free(hbInfo);
free(lpOverlapped);
puts("Client disconnected...");
}
else
{
bufInfo->len = szRecvBytes;
WSASend(hSock, bufInfo, , &sentBytes, , lpOverlapped, WriteCompRoutine);
}
} void CALLBACK WriteCompRoutine(DWORD dwError, DWORD szSendBytes, LPWSAOVERLAPPED lpOverlapped, DWORD flags)
{
LPPER_IO_DATA hbInfo = (LPPER_IO_DATA)(lpOverlapped->hEvent);
SOCKET hSock = hbInfo->hClntSock;
LPWSABUF bufInfo = &(hbInfo->wsaBuf);
DWORD recvBytes;
int flagInfo = ;
WSARecv(hSock, bufInfo, , &recvBytes, (LPDWORD)&flagInfo, lpOverlapped, ReadCompRoutine);
} void ErrorHandling(char *message) {
fputs(message, stderr);
fputc('\n', stderr);
}
二、IOCP回声服务端
服务端:
#include <stdio.h>
#include <stdlib.h>
#include <process.h>
#include <WinSock2.h>
#include <windows.h> #define BUF_SIZE 128
#define READ 3
#define WRITE 5
void ErrorHandling(char *message);
unsigned int WINAPI EchoThreadMain(LPVOID pComPort); typedef struct // socket info
{
SOCKET hClntSock;
SOCKADDR_IN clntAdr;
}PER_HANDLE_DATA, *LPPER_HANDLE_DATA; typedef struct // buffer info
{
OVERLAPPED overlapped;
WSABUF wsaBuf;
char buffer[BUF_SIZE];
int rwMode; // read or write
}PER_IO_DATA, *LPPER_IO_DATA; int main(int argc, char *argv[])
{
if (argc != ) {
printf("Usage : %s <port>\n", argv[]);
exit();
} WSADATA wsaData;
HANDLE hComPort;
SYSTEM_INFO sysInfo;
LPPER_IO_DATA ioInfo;
LPPER_HANDLE_DATA handleInfo; SOCKET hServSock;
SOCKADDR_IN servAdr;
int recvBytes, i, flags = ; if (WSAStartup(MAKEWORD(, ), &wsaData) != )
ErrorHandling("WSAStartup() error."); hComPort = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, , );
GetSystemInfo(&sysInfo);
for (int i = ; i < (int)sysInfo.dwNumberOfProcessors; i++)
_beginthreadex(NULL, , EchoThreadMain, (LPVOID)hComPort, , NULL); hServSock = WSASocket(AF_INET, SOCK_STREAM, , NULL, , WSA_FLAG_OVERLAPPED);
memset(&servAdr, , sizeof(servAdr));
servAdr.sin_family = AF_INET;
servAdr.sin_addr.s_addr = htonl(INADDR_ANY);
servAdr.sin_port = htons(atoi(argv[])); bind(hServSock, (SOCKADDR*)&servAdr, sizeof(servAdr));
listen(hServSock, ); puts("Server start...");
while (){
SOCKET hClntSock;
SOCKADDR_IN clntAdr;
int addrLen = sizeof(clntAdr); hClntSock = accept(hServSock, (SOCKADDR*)&clntAdr, &addrLen);
handleInfo = (LPPER_HANDLE_DATA)malloc(sizeof(PER_HANDLE_DATA));
handleInfo->hClntSock = hClntSock;
memcpy(&(handleInfo->clntAdr), &clntAdr, addrLen); CreateIoCompletionPort((HANDLE)hClntSock, hComPort, (DWORD)handleInfo, ); ioInfo = (LPPER_IO_DATA)malloc(sizeof(PER_IO_DATA));
memset(&(ioInfo->overlapped), , sizeof(OVERLAPPED));
ioInfo->wsaBuf.len = BUF_SIZE;
ioInfo->wsaBuf.buf = ioInfo->buffer;
ioInfo->rwMode = READ;
WSARecv(handleInfo->hClntSock, &(ioInfo->wsaBuf), , (LPDWORD)&recvBytes, (LPDWORD)&flags, &(ioInfo->overlapped), NULL);
} WSACleanup();
return ;
} unsigned int WINAPI EchoThreadMain(LPVOID pComPort)
{
HANDLE hComPort = (HANDLE)pComPort;
SOCKET sock;
DWORD bytesTrans;
LPPER_HANDLE_DATA handleInfo;
LPPER_IO_DATA ioInfo;
DWORD flags = ;
while ()
{
GetQueuedCompletionStatus(hComPort, &bytesTrans, (LPDWORD)&handleInfo, (LPOVERLAPPED*)&ioInfo, INFINITE);
sock = handleInfo->hClntSock;
if (ioInfo->rwMode == READ)
{
puts("message received!");
if (bytesTrans == ) // 传输EOF
{
closesocket(sock);
free(handleInfo);
free(ioInfo);
continue;
}
memset(&(ioInfo->overlapped), , sizeof(OVERLAPPED));
ioInfo->wsaBuf.len = bytesTrans;
ioInfo->rwMode = WRITE;
WSASend(sock, &(ioInfo->wsaBuf), , NULL, , &(ioInfo->overlapped), NULL);
ioInfo = (LPPER_IO_DATA)malloc(sizeof(PER_IO_DATA));
memset(&(ioInfo->overlapped), , sizeof(OVERLAPPED));
ioInfo->wsaBuf.len = BUF_SIZE;
ioInfo->wsaBuf.buf = ioInfo->buffer;
ioInfo->rwMode = READ;
WSARecv(sock, &(ioInfo->wsaBuf), , NULL, &flags, &(ioInfo->overlapped), NULL);
}
else{
puts("message sent");
free(ioInfo);
}
}
} void ErrorHandling(char *message) {
fputs(message, stderr);
fputc('\n', stderr);
}
windows—IOCP的更多相关文章
- windows IOCP 实践
关于 windows IOCP 有人说 windows IOCP 是 windows 上最好的东西. IOCP 是真正的异步 IO,意味着每次发起一个 IO 请求,该调用本身则立即返回, 而包括 IO ...
- windows IOCP入门的一些资料
最近需要看一个中间件的IOCP处理模块,需要了解这方面的知识 https://www.codeproject.com/articles/13382/a-simple-application-using ...
- 再次写给VC++ Windows开发者
距离我的上一篇文章--写给VC++ Windows开发的初学者已经4年多时间过去了,感慨于时光如梭之余,更感慨于这么多年来(从1998年我初学VC 算起吧)到如今其实我仍然还只是个初学者而已.看看之前 ...
- EQueue - 一个纯C#写的分布式消息队列介绍2
一年前,当我第一次开发完EQueue后,写过一篇文章介绍了其整体架构,做这个框架的背景,以及架构中的所有基本概念.通过那篇文章,大家可以对EQueue有一个基本的了解.经过了1年多的完善,EQueue ...
- [原创]直播服务器简单实现 http_flv和hls 内网直播桌面
直播都不陌生了,如今主流的协议分析的对比图,个人见解. 协议 httpflv rtmp hls dash 传输层 http流 tcp流 http http 视频格式 flv flv tag Ts文件 ...
- libeventReferenceManual阅读笔记
一.01_intro.html Example:A low-level ROT13 server with Libevent 这是一个利用event实现的server实例 Example:A simp ...
- 系统间通信(5)——IO通信模型和JAVA实践 下篇
7.异步IO 上面两篇文章中,我们分别讲解了阻塞式同步IO.非阻塞式同步IO.多路复用IO 这三种IO模型,以及JAVA对于这三种IO模型的支持.重点说明了IO模型是由操作系统提供支持,且这三种IO模 ...
- Linux Native Aio 异步AIO的研究
Linux Native Aio 异步AIO的研究 http://rango.swoole.com/archives/282 首先声明一下epoll+nonblock从宏观角度可以叫做全异步,但从微观 ...
- IO设计模式:Reactor和Proactor对比
IO设计模式:Reactor和Proactor对比 平时接触的开源产品如Redis.ACE,事件模型都使用的Reactor模式:而同样做事件处理的Proactor,由于操作系统的原因,相关的开源产品也 ...
随机推荐
- 【vue】清理代码
// 一次性将这个日期选择器附加到一个输入框上 // 它会被挂载到 DOM 上. mounted: function () { // Pikaday 是一个第三方日期选择器的库 this.picker ...
- PLS-00357: Table,View Or Sequence reference 'SEQ_TRADE_RECODE.NEXTVAL' not allowed in this context
oracle数据库: 为了使ID自增,建了序列后,创建触发器: create or replace TRIGGER TRIG_INSERT_TRADE_RECODE BEFORE INSERT ON ...
- Java运行环境
Java 开发环境配置 在本章节中我们将为大家介绍如何搭建Java开发环境. Windows 上安装开发环境 Linux 上安装开发环境 安装 Eclipse 运行 Java Cloud Studio ...
- datasnap 的HTTP 调用返回JSON
datasnap 相关设置,就不细说了,直接上函数 uses System.JSON function TServerMethods.Updatehello: Tjsonobject; var tem ...
- centos6.9系列LNMP环境的安装
一.Nginx 1.先解决Nginx的依赖关系: yum install -y pcre-devel openssl-devel 2.安装wget:sudo yum -y install wget 3 ...
- React Native之常用组件(View)
一. JSX和组件的概念 React的核心机制之一就是虚拟DOM:可以在内存中创建的虚拟DOM元素.React利用虚拟DOM来减少对实际DOM的操作从而提升性能.传统的创建方式是: 但这样的代码可读性 ...
- 如何在Qt中使用自定义数据类型
这里我们使用下面这个struct来做说明(这里不管是struct还是class都一样): struct Player { int number; QString firstName; QString ...
- Prometheus监控学习笔记之Prometheus 2.0 告警规则介绍
0x00 变化 Prometheus 2.0 已经发布一段时间了,从今天开始我将分几篇文章为大家介绍其中的一些变化. 此篇文章主要介绍 2.0 的告警规则声明的新写法. 从 1.x 到 2.0 规则声 ...
- 获取占用fd最大的前20个进程
for x in `ps -eF| awk '{ print $2 }'`;do echo `ls /proc/$x/fd 2> /dev/null | wc -l` $x `cat /proc ...
- java中Map集合的常用方法 (转)
原文地址:https://www.cnblogs.com/xiaostudy/p/9510763.html Map集合和Collection集合的区别 Map集合是有Key和Value的,Collec ...