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,由于操作系统的原因,相关的开源产品也 ...
随机推荐
- 融云通信云发力教育行业 助在线教育"风口"继续腾云
4 月 16 日,2019 年AI 在线教育大会在北京站圆满落幕,会上云集超过500位资深教育从业者.200 家机构,共同就 AI 教育落地.在线教育应用经验等主题开展深入探讨.云通信领域的领导企业融 ...
- keras用法
关于Keras的“层”(Layer) 所有的Keras层对象都有如下方法: layer.get_weights():返回层的权重(numpy array) layer.set_weights(weig ...
- MTK(android init.rc) 写一个开机启动的服务
在开机往往我们想要做一些初始化的操作,这时候可以使用init.rc文件来实现,当然书写一个开机启动的服务也需要规范的. 假设是C程序,则需要准备C程序的源码,在我的例程中是一个在开机完成(androi ...
- hiho一下 第206周
题目1 : Guess Number with Lower or Higher Hints 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 There is a game ...
- fang
如果一件事情,大家都希望它发生,并对大家都有利益. 那么它必定会发生.
- List、Set、Map的区别
(图一) 1.面试题:你说说collection里面有什么子类. (其实面试的时候听到这个问题的时候,你要知道,面试官是想考察List,Set) 正如图一,list和set是实现了collection ...
- centos 时钟配置
centos 7 时钟配置: timedatectl 命令: [root@localhost ~]# timedatectl --help timedatectl [OPTIONS...] COMMA ...
- Excel 如何判断某列哪些单元格包含某些字符
“条件格式”,公式: =IF(COUNTIF($A2,,,) 然后根据需要设置格式
- day 05
今天学习了数据类型的操作 首先需要知道 数据类型有哪些 1.数字类型 2.字符串类型 3.布尔类型 4.列表类型 5.字典类型 6.元组类型 7.集合类型类型 1.1数字类型里面有分 为整型(int) ...
- Centos7通过SSH使用密钥实现免密登录
日常开发中,难免会有登录服务器的操作,而通过ssh方式登录无疑是比较方便的一种方式. 如果登录较频繁,使用密钥实现免密登录无疑更是方便中的方便.因此本文就简单说一说如何实现免密登录. 一.安装配置ss ...