windows异步通知I/O模型
回声服务器端:
#include <stdio.h>
#include <stdlib.h>
#include <WinSock2.h> #define BUF_SIZE 1024
void ErrorHandling(char *message);
void CompressSockets(SOCKET hSockArr[], int idx, int total);
void CompressEvents(WSAEVENT hEventArr[], int idx, int total); int main(int argc, char *argv[])
{
if (argc != ) {
printf("Usage : %s <port>\n", argv[]);
exit();
} WSADATA wsaData;
SOCKET hServSock, hClntSock;
SOCKADDR_IN servAdr, clntAdr; SOCKET hSockArr[WSA_MAXIMUM_WAIT_EVENTS];
WSAEVENT hEventArr[WSA_MAXIMUM_WAIT_EVENTS];
WSAEVENT newEvent;
WSANETWORKEVENTS netEvents; int numOfClntSock = ;
int strLen;
int posInfo, startIdx;
int clntAdrLen;
char msg[BUF_SIZE]; if (WSAStartup(MAKEWORD(, ), &wsaData) != )
ErrorHandling("WSAStartup() error."); hServSock = socket(PF_INET, SOCK_STREAM, );
if (hServSock == INVALID_SOCKET)
ErrorHandling("socket() error."); memset(&servAdr, , sizeof(servAdr));
servAdr.sin_family = AF_INET;
servAdr.sin_addr.s_addr = htonl(INADDR_ANY);
servAdr.sin_port = htons(atoi(argv[])); if (bind(hServSock, (SOCKADDR*)&servAdr, sizeof(servAdr)) == SOCKET_ERROR)
ErrorHandling("bind() error.");
if (listen(hServSock, ) == SOCKET_ERROR)
ErrorHandling("listen() error."); newEvent = WSACreateEvent();
if (WSAEventSelect(hServSock, newEvent, FD_ACCEPT) == SOCKET_ERROR)
ErrorHandling("WSAEventSelect() error."); hSockArr[numOfClntSock] = hServSock;
hEventArr[numOfClntSock] = newEvent;
numOfClntSock++;
printf("Server start...\n");
while ()
{
posInfo = WSAWaitForMultipleEvents(numOfClntSock, hEventArr, FALSE, WSA_INFINITE, FALSE);
startIdx = posInfo - WSA_WAIT_EVENT_0;
for (int i = startIdx; i < numOfClntSock; i++){
int sigEventIdx = WSAWaitForMultipleEvents(, &hEventArr[i], TRUE, , FALSE);
if (sigEventIdx == WSA_WAIT_FAILED || sigEventIdx == WSA_WAIT_TIMEOUT){
continue;
}
else{
sigEventIdx = i;
WSAEnumNetworkEvents(hSockArr[sigEventIdx], hEventArr[sigEventIdx], &netEvents);
if (netEvents.lNetworkEvents & FD_ACCEPT){ // 客户端请求连接
if (netEvents.iErrorCode[FD_ACCEPT_BIT] != )
{
printf("Accept error.\n");
break;
}
clntAdrLen = sizeof(clntAdr);
hClntSock = accept(hSockArr[sigEventIdx], (SOCKADDR*)&clntAdr, &clntAdrLen);
newEvent = WSACreateEvent();
WSAEventSelect(hClntSock, newEvent, FD_READ | FD_CLOSE); hEventArr[numOfClntSock] = newEvent;
hSockArr[numOfClntSock] = hClntSock;
numOfClntSock++;
printf("connected new client...\n");
}
if (netEvents.lNetworkEvents & FD_READ){ // 接收数据
if (netEvents.iErrorCode[FD_READ_BIT] != )
{
printf("Read error\n");
break;
}
strLen = recv(hSockArr[sigEventIdx], msg, sizeof(msg), );
send(hSockArr[sigEventIdx], msg, strLen, );
}
if (netEvents.lNetworkEvents & FD_CLOSE){ // 断开连接
if (netEvents.iErrorCode[FD_CLOSE_BIT] != )
{
printf("Close Error.\n");
break;
}
WSACloseEvent(hEventArr[sigEventIdx]);
closesocket(hSockArr[sigEventIdx]); numOfClntSock--;
CompressSockets(hSockArr, sigEventIdx, numOfClntSock);
CompressEvents(hEventArr, sigEventIdx, numOfClntSock);
}
}
}
}
WSACleanup();
return ;
} void ErrorHandling(char *message) {
fputs(message, stderr);
fputc('\n', stderr);
} void CompressSockets(SOCKET hSockArr[], int idx, int total){
for (int i = idx; i < total; i++)
hSockArr[i] = hSockArr[i + ];
} void CompressEvents(WSAEVENT hEventArr[], int idx, int total){
for (int i = idx; i < total; i++)
hEventArr[i] = hEventArr[i + ];
}
客户端:
#pragma warning(disable:4996)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <winsock2.h> #define BUF_SIZE 1024
void ErrorHandling(char *message); int main(int argc, char* argv[]) {
if (argc != ) {
printf("Usage : %s <IP> <port>\n", argv[]);
exit();
} WSADATA wsaData;
SOCKET sock;
SOCKADDR_IN serverAddr;
char message[BUF_SIZE];
int sLen, recvLen; if (WSAStartup(MAKEWORD(, ), &wsaData) != )
ErrorHandling("WSAStartup() error"); sock = socket(PF_INET, SOCK_STREAM, );
if (sock == INVALID_SOCKET)
ErrorHandling("socket() error"); memset(&serverAddr, , sizeof(serverAddr));
serverAddr.sin_family = AF_INET;
serverAddr.sin_addr.s_addr = inet_addr(argv[]);
serverAddr.sin_port = htons(atoi(argv[])); if (connect(sock, (SOCKADDR*)&serverAddr, sizeof(serverAddr)) == SOCKET_ERROR)
ErrorHandling("connect() error");
else
printf("Connected.......\n");
while ()
{
fputs("Input message(Q to quit):", stdout);
fgets(message, BUF_SIZE, stdin);
if (!strcmp(message, "q\n") || !strcmp(message, "Q\n"))
break;
sLen = send(sock, message, strlen(message), );
recvLen = ;
while (recvLen < sLen) {
int cnt = recv(sock, message, BUF_SIZE - , );
if (cnt == -)
ErrorHandling("ercv() error");
recvLen += cnt;
}
message[recvLen] = ;
printf("Message from server: %s\n", message);
}
closesocket(sock);
WSACleanup();
return ;
} void ErrorHandling(char *message) {
fputs(message, stderr);
fputc('\n', stderr);
}
windows异步通知I/O模型的更多相关文章
- c++ 网络编程(十) LINUX/windows 异步通知I/O模型与重叠I/O模型 附带示例代码
原文作者:aircraft 原文链接:https://www.cnblogs.com/DOMLX/p/9662931.html 一.异步IO模型(asynchronous IO) (1)什么是异步I/ ...
- windows 异步通知I/O模型与重叠I/O模型
一.异步IO模型(asynchronous IO) (1)什么是异步I/O 异步I/O(asynchronous I/O)由POSIX规范定义.演变成当前POSIX规范的各种早起标准所定义的实时函数中 ...
- 第三十四篇:在SOUI中使用异步通知
概述 异步通知是客户端开发中常见的需求,比如在一个网络处理线程中要通知UI线程更新等等. 通常在Windows编程中,为了方便,我们一般会向UI线程的窗口句柄Post/Send一个窗口消息从而达到将非 ...
- Linux的fasync驱动异步通知详解【转】
本文转载自:http://blog.csdn.net/coding__madman/article/details/51851338 版权声明:本文为博主原创文章,未经博主允许不得转载. 工作项目用有 ...
- Paip.Php Java 异步编程。推模型与拉模型。响应式(Reactive)”编程FutureData总结... 1
Paip.Php Java 异步编程.推模型与拉模型.响应式(Reactive)"编程FutureData总结... 1.1.1 异步调用的实现以及角色(:调用者 提货单) F ...
- 蜕变成蝶~Linux设备驱动之异步通知和异步I/O
在设备驱动中使用异步通知可以使得对设备的访问可进行时,由驱动主动通知应用程序进行访问.因此,使用无阻塞I/O的应用程序无需轮询设备是否可访问,而阻塞访问也可以被类似“中断”的异步通知所取代.异步通知类 ...
- OS信号实现Java异步通知
OS信号实现Java异步通知本文将结合操作系统的信号机制,来尝试实现一个简单的,不依赖功能环境的Java异步通知功能.没有特殊说明,本文所有的示例,都是基于Linux.信号简介信号是在软件层次上对中断 ...
- 嵌入式Linux驱动学习之路(十三)按键驱动-异步通知
之前的按键方式: 查询: 极度占用CPU资源 中断: 在读的时候产生休眠,在没有信号的时候永远不会返回. poll机制: 在中断的基础上加上超时时间. 异步通知就是通过信号来传送. 首先在应用程序中有 ...
- Linux学习 :按键信号 之 异步通知
一.异步通知概念: 异步通知是指:一旦设备就绪,则主动通知应用程序,应用程序根本就不需要查询设备状态,类似于中断的概念,一个进程收到一个信号与处理器收到一个中断请求可以说是一样的.信号是异步的,一个进 ...
随机推荐
- CCF CSP 201604-1 折点计数
题目链接:http://118.190.20.162/view.page?gpid=T42 问题描述 试题编号: 201604-1 试题名称: 折点计数 时间限制: 1.0s 内存限制: 256.0M ...
- python中的列表
1. 列表是什么,他可以用来做什么呢?当你存在这样的疑问,就往下看吧:) 列表是由一系列按特定顺序排列的元素组成的.在Python中,用[]来表示列表,并用逗号来分隔其中的元素. 我们可以创建包含字 ...
- Flutter 数据存储 加权限 sharedpreference, sqflite, file
要访问SD卡,首先读取权限肯定是要有的,不然写再多代码都是无用功.在AndroidManifest.xml文件中添加 <uses-permission android:name="an ...
- Bugku-CTF之速度要快
Day21 速度要快 速度要快!!!!!! http://123.206.87.240:8002/web6/
- Guitar Pro中如何添加与删除音轨
Guitar Pro是一款专业的吉他打谱作曲软件,适合每一位热爱吉他并想进一步学习的大家.今天,我们一起来看看Guitar Pro软件写谱时音轨如何添加与删除. Guitar Pro能够同时支持虚拟音 ...
- net应用程序池自动关闭的解决方法
while (true) { using (ServerManager sm = ServerManager.OpenRemote("localhost")) { string p ...
- Vue小项目二手书商城:(四)详情页和购物车(emit、prop、computed)
实现效果: 点击对应商品,对应的商品详情页出现,详情页里面还有“Add to cart”按钮和“×”退出按钮. 点击“Add to cart”可以将商品加入购物车,每件商品只能添加一次,如果把购物车的 ...
- Hadoop之HDFS概述
一.HDFS产生背景及定义 1.HDFS产生背景 随着数据量越来越大,在一个操作系统存不下所有的数据,那么就分配到更多的操作系统管理的磁盘中,但是不方便管理和维护,迫切需要一种系统来管理多台机器上的文 ...
- python2和python3的range(100)的区别
python2返回列表,python3返回迭代器,节约内存
- js 延时等待
//延时器,2秒后执行函数 function test(){ alert("aaaa"); } setTimeout(function () { test(); }, ); //或 ...