TCP-事件模型
#include "main.h"VOID Server_write_error()
{}/*1.打开网络库
* 2.校验网络库版本
* 3.创建SOCKET
* 4.绑定IP地址和端口
* 5.开始监听
* 6.创建客户端socket/接受链接
* 7.与客户端收发消息
* 8.(6.7)两步的函数accept,send,recv 有堵塞,可以用select解决,这种函数可以处理小型网络
*/
int create(const char* IpAdress)
{WORD wVersionRequested;WSADATA wsaData;int err;/* 使用Windef.h中声明的MAKEWORD(低字节、高字节)宏 */wVersionRequested = MAKEWORD(2, 2);/*启用网络链接库,调用的封装库命令*/err = WSAStartup(wVersionRequested, &wsaData);if (err != 0) {/* Tell the user that we could not find a usable *//* Winsock DLL. */printf("WSAStartup failed with error: %d\n", err);return -1;}/*确认WinSock DLL支持2.2*/if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2) {/* Tell the user that we could not find a usable *//* WinSock DLL. */printf("Could not find a usable version of Winsock.dll\n");//清理网络库WSACleanup();return -1;}//创建套接字。 创建网络类型 tcp或者updSOCKET socketServer = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);if (INVALID_SOCKET == socketServer){string ret = to_string(WSAGetLastError());MessageBoxA(0, "error_socket",ret.c_str(), 0);//清理网络库WSACleanup();return -1;}//设置sockaddr结构sockaddr_in saServer;saServer.sin_family = AF_INET;saServer.sin_addr.s_addr = INADDR_ANY;saServer.sin_port = htons(9999);// 绑定本机(服务器)IP和端口//sockaddr结构中的信息if (SOCKET_ERROR == bind(socketServer, (SOCKADDR*)&saServer, sizeof(saServer))){string ret = to_string(WSAGetLastError());MessageBoxA(0, "error_bind", ret.c_str(), 0);//释放stocketclosesocket(socketServer);//清理网络库WSACleanup();return -1;}/*监听本机(服务器)的套接字*/if (SOCKET_ERROR == listen(socketServer, SOMAXCONN)){string ret = to_string(WSAGetLastError());MessageBoxA(0, "error_listen", ret.c_str(), 0);//释放stocketclosesocket(socketServer);//清理网络库WSACleanup();return -1;}fd_es_set setSockets;memset(&setSockets,0,sizeof(setSockets));/*创建一个套接字 事件*/HANDLE eventSerevr = WSACreateEvent();if (WSA_INVALID_EVENT == eventSerevr){string ret = to_string(WSAGetLastError());MessageBoxA(0, "error_WSACreateEventServer", ret.c_str(), 0);//释放stocketclosesocket(socketServer);//清理网络库WSACleanup();return -1;}/*将服务器socket和事件绑定*/if (SOCKET_ERROR == WSAEventSelect(socketServer, eventSerevr, FD_ACCEPT)){string ret = to_string(WSAGetLastError());MessageBoxA(0, "error_WSAEventSelecttServer", ret.c_str(), 0);//释放stocketclosesocket(socketServer);//清理网络库WSACleanup();return -1;}/*将服务器socket和事件对象句柄写进结构体*/setSockets.sockall[setSockets.count] = socketServer;setSockets.eventall[setSockets.count] = eventSerevr;setSockets.count++;while (true){ /*为了防止一个用户死循环访问服务器,造成事件一直处理同一个客户端,进行优化,循环遍历单个数组询问是否有事件信号*//*同时WSAWaitForMultipleEvents函数参数一每次只能处理64个事件数组,而我们改成每次处理1个,循环处理变相能处理无穷多的事件了*/DWORD RET = 0;for (DWORD Index = 0; Index <setSockets.count; Index++){/*等待事件:有事件产生后返回对应事件的下标*/RET = WSAWaitForMultipleEvents(1, &setSockets.eventall[Index], false, 0, false);/*返回错误*/if (WSA_WAIT_FAILED == RET){string ret = to_string(WSAGetLastError());MessageBoxA(0, "error_WSAWaitForMultipleEvents", ret.c_str(), 0);continue;}/*等待超时检测*/if (WSA_WAIT_TIMEOUT == RET){continue;}// DWORD Index = RET - WSA_WAIT_EVENT_0;/*枚举事件:获取事件类型,并重置其的信号*/WSANETWORKEVENTS GetlpNetworkEvents;if (SOCKET_ERROR == WSAEnumNetworkEvents(setSockets.sockall[Index], setSockets.eventall[Index], &GetlpNetworkEvents)){string ret = to_string(WSAGetLastError());MessageBoxA(0, "error_WSAEnumNetworkEvents", ret.c_str(), 0);continue;}/******** FD_ACCEPT 可能是组合指令,故需要 & 判断*//*客户端connect会依次触发FD_ACCEPT 和 FD_WRITE*/if (GetlpNetworkEvents.lNetworkEvents & FD_ACCEPT){if (0 == GetlpNetworkEvents.iErrorCode[FD_ACCEPT_BIT]){//正常处理sockaddr_in clientMsg = { 0 };int clientMsg_size = sizeof(clientMsg);/*得到客户端信息并返回客户端socket*/SOCKET socketClient = accept(setSockets.sockall[Index], (sockaddr*)&clientMsg, &clientMsg_size);printf("%d.%d.%d.%d.%d \n", clientMsg.sin_addr.S_un.S_un_b.s_b1,clientMsg.sin_addr.S_un.S_un_b.s_b2,clientMsg.sin_addr.S_un.S_un_b.s_b3,clientMsg.sin_addr.S_un.S_un_b.s_b4,clientMsg.sin_port);if (INVALID_SOCKET == socketClient)continue;/*创建一个套接字 事件*/HANDLE eventClient = WSACreateEvent();if (WSA_INVALID_EVENT == eventClient){//释放stocketclosesocket(socketClient);continue;}/*将客户端socket和事件绑定*/if (SOCKET_ERROR == WSAEventSelect(socketClient, eventClient, FD_READ | FD_WRITE | FD_CLOSE)){//释放stocketclosesocket(socketClient);//关闭事件对象WSACloseEvent(eventClient);continue;}/*完成上面步骤后将这个客户端数据放入结构体*/setSockets.sockall[setSockets.count] = socketClient;setSockets.eventall[setSockets.count] = eventClient;setSockets.count++;}else{continue;}}/*********FD_WRITE 可能是组合指令,故需要 & 判断*//*客户端connect会依次触发FD_ACCEPT 和 FD_WRITE*/if (GetlpNetworkEvents.lNetworkEvents & FD_WRITE){if (0 == GetlpNetworkEvents.iErrorCode[FD_WRITE_BIT]){//正常处理//accept会触发一次,一般用于链接服务器后初始化char sendmsg[] = "connect_success";if (SOCKET_ERROR == send(setSockets.sockall[Index], sendmsg, strlen(sendmsg), 0)){continue;}}else{continue;}}/*********FD_READ 可能是组合指令,故需要 & 判断*/if (GetlpNetworkEvents.lNetworkEvents & FD_READ){if (0 == GetlpNetworkEvents.iErrorCode[FD_READ_BIT]){//正常处理char recvmsg[1024] = { 0 };if (SOCKET_ERROR == recv(setSockets.sockall[Index], recvmsg, sizeof(recvmsg), 0)){continue;}printf("read:%s\n", recvmsg);char sendmsg[] = "recv_success";if (SOCKET_ERROR == send(setSockets.sockall[Index], sendmsg, strlen(sendmsg), 0)){continue;}}else{continue;}}/*********FD_CLOSE 可能是组合指令,故需要 & 判断*/if (GetlpNetworkEvents.lNetworkEvents & FD_CLOSE){{//正常处理//sockaddr_in clientMsg = { 0 };//int clientMsg_size = sizeof(clientMsg);//getsockname(setSockets.sockall[Index], (sockaddr*)&clientMsg, &clientMsg_size);//printf("client下线:%d.%d.%d.%d.%d \n", clientMsg.sin_addr.S_un.S_un_b.s_b1,// clientMsg.sin_addr.S_un.S_un_b.s_b2,// clientMsg.sin_addr.S_un.S_un_b.s_b3,// clientMsg.sin_addr.S_un.S_un_b.s_b4,// clientMsg.sin_port);printf("client下线");//释放stocketclosesocket(setSockets.sockall[Index]);//关闭事件对象WSACloseEvent(setSockets.eventall[Index]);/*将这个事件和socket移除数组,取巧方法:由于事件是无序的,把数组最后一个数据放进移除的数据的位置,并将数组大小-1*/setSockets.sockall[Index] = setSockets.sockall[setSockets.count - 1];//数组从0开始,-1才是正确位置setSockets.eventall[Index] = setSockets.eventall[setSockets.count - 1];//数组从0开始,-1才是正确位置setSockets.count--;}}} }system("pause");/*释放整个结构体,可能有些事件和socket已经被释放过了,不影响*/for (int i = 0; i < setSockets.count; i++){//释放stocketclosesocket(setSockets.sockall[i]);//关闭事件对象WSACloseEvent(setSockets.eventall[i]);}//清理网络库WSACleanup();
}int main()
{// create("127.0.0.1");return 0;
}
利用windows的网络事件函数,系统将自动用异步的方式帮我们查看socket消息,接收到消息后,我们将无序的查看接收到的消息(比如:我们有事件[5],先后接收到45321送来的消息,事件只能接收到12345发来了消息,并不能知道先后顺序,故只能按12345的顺序处理消息),而消息机制本质和事件差不多,区别就是消息机制由系统的消息队列记录先后顺序,会按45321的顺序处理,处理更合理
相关文章:
TCP-事件模型
#include "main.h"VOID Server_write_error() {}/*1.打开网络库 * 2.校验网络库版本 * 3.创建SOCKET * 4.绑定IP地址和端口 * 5.开始监听 * 6.创建客户端socket/接受链接 * 7.与客户端收发消息 * 8.(6.7)两步的函数accept,send,recv 有堵塞,可…...
typescript 声明文件
作用 1、为已存在js库提供类型信息,这样在ts项目中使用这些库时候,就像用ts一样,会有代码提示、类型保护等机制 2、项目内共享类型:如果多个.ts文件中都用到同一个类型,此时可以创建.d.ts文件提供该类型,…...
BC96 有序序列判断
描述 输入一个整数序列,判断是否是有序序列,有序,指序列中的整数从小到大排序或者从大到小排序(相同元素也视为有序)。 数据范围:3≤n≤50 序列中的值都满足1≤val≤100。 输入描述 第一行输入一个整数N(3≤N≤50)。 第二行…...
QT操作excel的两种方式 QT基础入门【Excel的操作】
QT操作excel的方式有两种:QAxObject 和QtXlsx QAxObject是通过调用office或者wps组件来实现对excel图表的操作的。只有装office软件或者wps软件就可以实现,但是 如果只装了office软件,有时可以用有时不可以用;如果只装wps软件&a…...
c++ qt--QString,弹出框(第二部分)
c qt–QString,弹出框(第二部分) 一.QString 1.所用头文件 #include<QString>2.功能 1.初始化 可以用字符,常量字符串、字符指针、字符数组等类型给QString进行初始化 QString str2"4567";//进行初始化2.拼…...
CSS自学框架之动画
这一节,自学CSS动画。主要学习了淡入淡出、淡入缩放、缩放、移动、旋转动画效果。先看一下成果。 优雅的过渡动画,为你的页面添加另一份趣味! 在你的选择器里插入 animation 属性,并添加框架内置的 keyframes 即可实现࿰…...
RabbitMQ的5种消息队列
RabbitMQ的5种消息队列 1、七种模式介绍与应用场景 1.1 简单模式(Hello World) 一个生产者对应一个消费者,RabbitMQ 相当于一个消息代理,负责将 A 的消息转发给 B。 应用场景:将发送的电子邮件放到消息队列,然后邮件服务在队列…...
【C语言】选择排序
基本原理 先找到数组中最大的那个数,将最大的数放到数组最右端(交换a[maxid]和a[len-1]这两个数的位置),然后继续从a[0]到a[len-2]中找到最大的数,然后交换a[maxid]和a[len-2]位置,依次查找交换,…...
异步更新队列 - Vue2 响应式
前言 这篇文章分析了 Vue 更新过程中使用的异步更新队列的相关代码。通过对异步更新队列的研究和学习,加深对 Vue 更新机制的理解 什么是异步更新队列 先看看下面的例子: <div id"app"><div id"div" v-if"isShow&…...
【Unity的URP渲染管线下实现扩展后处理Volume组件_TemporalAntiAliasing(TAA)_抗锯齿(附带下载链接)】
【Unity的URP渲染管线下的TAA抗锯齿】 背景:1. Unity内置的抗锯齿只能够满足部分画面需求。展示一个锯齿示例。2. 在75寸大屏电视上跑通展示一个锯齿示例。- 在Camera上配置3. 安装了一个TAA组建,最后打包APK在安卓机上运行报错。- 经过测试排查,发现是没有将后处理的shader…...
NineData通过AWS FTR认证,打造安全可靠的数据管理平台
近日,NineData 作为新一代的云原生智能数据管理平台,成功通过了 AWS(Amazon Web Service)的 FTR 认证。NineData 在 FTR 认证过程中表现出色,成功通过了各项严格的测试和评估,在数据安全管理、技术应用、流…...
Qt应用开发(基础篇)——滚屏区域类 QScrollArea
一、前言 QScrollArea类继承于QAbstractScrollArea,QAbstractScrollArea继承于QFrame,是Qt滚动视图的常用部件。 滚屏区域基类 QAbstractScrollArea 框架类 QFrame QScrollArea类提供了对另一个小部件的滚动视图,基础功能、滚动条控制、界面策…...
安装最新版chromedriver 116,亲测可用
Version Selection...
html题库
什么是HTML? HTML的全称为 超文本标记语言 ,是一种 标记语言 。 它包括一系列标签 ,通过这些标签可以将网络上的文档格式统一,使分散的 Internet 资源连接为一个逻辑整体。 DOCTYPE 的作用是什么?标准模式与兼容模式(…...
Android11 中 LED 使用-RK3568
文章目录 前言原理图设备树驱动前言 现在我们来学习点亮LED 原理图 然后对应在核心板原理图上查找 Working_LEDEN_H_GPIO0_B7,如下图所示: 那么我们只要控制 GPIO0_B7 即可控制 led 的亮灭。 设备树 leds: leds {compatible = "gpio-leds";work_led: work {gpi…...
BC77 有序序列插入一个数
描述 有一个有序数字序列,从小到大排序,将一个新输入的数插入到序列中,保证插入新数后,序列仍然是升序。 输入描述 第一行输入一个整数(0≤N≤50)。 第二行输入N个升序排列的整数,输入用空格分隔的N个整数。 第三…...
通过脚本使用Cppcheck做静态测试并生成报告(Windows)
1.安装cppcheck 先从cppcheck官方网站下载cppcheck的安装包。 注: (1)官网地址:https://sourceforge.net/projects/cppcheck (2)截止2023年8月,官方发布的最新版本是cppcheck-2.11-x64-Setup.…...
工业安全生产信息化平台的基本架构和关键功能分享
工业安全生产信息化平台是指利用信息技术手段,将工业安全生产管理与数据采集、传输、处理相结合,实现对工业安全生产全过程的数字化、信息化、智能化管理的平台。它通过集成多种信息系统和设备,实现对重大危险源监控预警、安全风险分级管控、…...
每日一道面试题之session 和 cookie 有什么区别?
Session和Cookie是两种在Web开发中用于跟踪用户状态的机制: 它们之间的区别如下: 存储位置:Cookie是存储在用户浏览器中的小型文本文件,而Session是存储在服务器上的数据结构。 数据安全性:Cookie中的数据可以被用户…...
SHELL 基础 显示字符颜色, 修改历史命令,Linux里的命令 执行顺序
echo 打印命令 : 显示字符串 : [rootserver ~]# echo this is SHELL language this is SHELL language [rootserver ~]# echo this is SHELL language this is SHELL language [rootserver ~]# echo "this is SHELL language" this is SH…...
Vue 和 JQuery 的区别在哪?为什么 JQuery 会被 Vue 取代?
在 Web 前端开发领域,我们经常会遇到一些不同的工具和框架,其中 Vue 和 JQuery, JQuery 是曾经备受欢迎的选择,而现在 Vue 是大多数人的选择。本文将探讨 Vue 和 JQuery 之间的区别,并讨论为什么越来越多的开发人员放弃 JQuery 而…...
Spring 中 Bean 注入与获取
Spring 中有哪些方式可以把 Bean 注入到 IOC 容器? 关于这个问题,我的回答入下:把 Bean 注入到 IOC 容器里面的方式有 7 种方式 1. 使用 xml 的方式来声明 Bean 的定义,Spring 容器在启动的时候会加载并解析这 个 xml,…...
STM32 中断复习
中断 打断CPU执行正常的程序,转而处理紧急程序,然后返回原暂停的程序继续运行,就叫中断。 在确定时间内对相应事件作出响应,如:温度监控(定时器中断)。故障处理,检测到故障&#x…...
Django的模型
定义模型 from django.db import models class User(models.Model):# 类属性是表示表的字段username models.CharField(max_length50,uniqueTrue)password models.CharField(max_length200)create_time models.DateTimeField(auto_now_addTrue) # auto_now_add新增数据时间…...
非计算机科班如何丝滑转码
近年来,很多人想要从其他行业跳槽转入计算机领域。非计算机科班如何丝滑转码? 方向一:如何规划才能实现转码? 对于非计算机科班的人来说,想要在计算机领域实现顺利的转码并不是一件容易的事情,但也并非不…...
PyTorch深度学习实战(12)——数据增强
PyTorch深度学习实战(12)——数据增强 0. 前言1. 图像增强1.1 仿射变换1.2 亮度修改1.3 添加噪音1.4 联合使用多个增强方法 2. 对批图像执行图像增强3. 利用数据增强训练模型小结系列链接 0. 前言 数据增强是指通过对原始数据进行一系列变换和处理&…...
SpringCloud Ribbon中的7种负载均衡策略
SpringCloud Ribbon中的7种负载均衡策略 Ribbon 介绍负载均衡设置7种负载均衡策略1.轮询策略2.权重策略3.随机策略4.最小连接数策略5.重试策略6.可用性敏感策略7.区域敏感策略 总结 负载均衡通器常有两种实现手段,一种是服务端负载均衡器,另一种是客户端…...
04 qt功能类、对话框类和文件操作
一 QT中时间和日期 时间 ---- QTime日期 ---- QDate对于Qt而言,在实际的开发过程中, 1)开发者可能知道所要使用的类 ---- >帮助手册 —>索引 -->直接输入类名进行查找 2)开发者可能不知道所要使用的类,只知道开发需求文档 ----> 帮助 手册,按下图操作: 1 …...
安装软件包
安装软件包 创建一个名为 /home/curtis/ansible/packages.yml 的 playbook : 将 php 和 mariadb 软件包安装到 dev、test 和 prod 主机组中的主机上 将 RPM Development Tools 软件包组安装到 dev 主机组中的主机上 将 dev 主机组中主机上的所有软件包更新为最新版本 vim packa…...
玩转单元测试之gmock
引言 前文我们学习了gtest相关的使用,单靠gtest,有些场景仍然无法进行测试,因此就诞生了gmock。 gmock快速入门 在引入gtest时,gmock也同样引入了,因此只需要在编译时加上合适的编译选项即可,注意不同版…...
动态网站加速器/百度手机管家
用户通过shell 将我们输入的命令与内核进行通信,好让内核控制硬件工作。 引用百度百科:在计算机科学中,Shell俗称壳(用来区别于核),是指“提供使用者使用界面”的软件(命令解析器)。…...
web期末网站设计大作业/企业网站模板图片
我是一个react的初学者,在学习的过程中遇到了模板搭建问题,想把自己遇到的问题记录下来,顺便加深印象,有不对的地方请指正。 学习的过程中,我主要感谢两个人的博客: http://www.wukai.me/2016/09/14/create…...
新闻网站开发/nba最新排名榜
问题描述:按照默认的安装配置好Bonobo.Git.Server后在浏览页面点击下载会出现错误(下载到一个报错信息的页面),无法得到正确的源码文件。虽然平时一般不需要下载或者都是git来完成操作的,但是某些情况下需要单独下载一…...
农产品网站建设背景/网站备案查询系统
zabbix不支持中文图 开启zabbix对中文的支持 原来zabbix默认把对中文的支持给关闭了,我们需要修改zabbix的php源文件. 修改站点根目录下include/locales.inc.php文件. 1234567891011# vim include/locales.inc.phpfunction getLocales() {return array(en_GB > a…...
wordpress thepost/网站优化推广方法
作者: CC老师注:只能用作学习,不能用于其他途径。转载请署名好原作者名准备资源CLToolsglewlibGLTools.a现在开始配置 openGL 环境•打开Xcode -> macOS -> Cocoa Application•添加OpenGl.framework 和 GLUT.framework 两个系统库…...
京东网站的建设与发展前景/怎么免费自己做推广
最近学籍系统频繁报出ORA-12519的错。由于这台数据库承载着高中、中职等大型数据库,查看数据库状态基本判定为oracle进程数不够导致报错。 根据Oracle文档,SESSIONS和TRANSACTIONS的初始化参数应该源于PROCESSES参数,根据默认设置SESSIONS P…...