网络程序设计——异步选择模型(基于消息的选择、基于事件的选择)

news2025/7/15 6:18:11

目录

一、异步选择模型

1、基于消息的选择模型

(1)WSAAsyncSelect模型

(2) WSAAsyncSelect()函数

(3)使用 WSAAsyncSelect模型接收数据的过程

 (4)WSAAsyncSelect模型的编程方法

(5) 使用WSAAsyncSelect模型实现服务器

2、基于事件的选择模型

(1)WinSock中的网络事件与事件对象函数

 ①WSACreateEvent()函数

②WSAResetEvent()函数

③WSASetEvent()函数 

④WSACloseEvent() 函数 

(2) WSAEventSelect模型的函数

 (3)网络事件等待函数WSAWaitForMultipleEvents()       

  (4)网络事件枚举函数WSAEnumNetworkEvents()

 (5)WSAEventSelect模型的编程方法

一、异步选择模型

1、基于消息的选择模型

(1)WSAAsyncSelect模型

  •        阻塞模型是在不知I/O事件是否发生的情况下,应用程序会按自己既定的流程主动去执行IO操作,结果通常是阻塞并等待相应事件发生;
  •       非阻塞模型也是在不知I/O事件是否发生的情况下,应用程序按自己既定的流程,反复执行IO操作直到操作成功(I/O事件发生);
  •       Select模型则是在不知I/O事件是否发生的情况下,应用程序按既定流程调用select函数主动检查关心的IO事件是否发生,如果没有发生则select()函数也是阻塞等待。

      共同特点:不管 I/O事件是否发生,应用程序都会按既定流程主动试着进行I/O操作,而且直至操作成功才会罢休,因此这三种套接字模型都属于同步模型

      尽管非阻塞模型和Select模型一次能够尝试对多个套接字进行I/O操作,要比阻塞模型效率高很多,但应用程序一旦开始I/O操作,则I/O操作完成之前都是无法进行其它操作。

      解决这一问题的方法是采用异步I/O模型。

  •       异步套接字I/O模型中,当网络I/O事件发生时,系统将采用某种机制通知应用程序,应用程序只有在收到事件通知时才调用相应的套接字函数进行I/O操作。

      WSAAsyncSelect模型和WSAEventSelect模型都属于异步I/O模型,二者的差别在于系统通知应用程序的方法不同。

(2) WSAAsyncSelect()函数

WSAAsyncSelect()函数,其格式如下。

WSAAsyncSelect(s, hWnd, 0, 0);

  •       s为要被取消注册网络事件的套接字,hWnd为注册这些事件时指定的接收网络事件消息的窗口的句柄。
  •       取消网络事件的注册之后,系统将不再为该套接字发送任何与网络事件相关的消息。
  •       需要特别强调,WSAAsyncSelect模型应用在Windows环境下,使用该模型时必须创建窗口。
  •       而Slelect模型广泛应用在Unix系统和Windows系统,使用该模型不需要创建窗口。

      应用程序调用WSAAsyncSelect()函数后,自动将套接字设置为非阻塞模式,而应用程序中调用select()函数后,并不能改变该套接字的工作方式。

  •        WSAAsyncSelect模型是基于Windows的消息机制实现的,当网络事件发生时,Windows系统将发送一条消息给应用程序,应用程序将根据消息做出相应的处理。该模型的核心是WSAAsyncSelect()函数。
  •        WSAAsyncSelect()函数的主要功能:是为指定的套接字注册一个或多个应用程序需要关注的网络事件。
  •        WSAAsyncSelect模型是非阻塞的,在应用程序中调用WSAAsyncSelect()函数后,该函数将向系统注册完成参数lEvent指定的网络事件后立即返回。
  •        WSAAsyncSelet模型是异步的,当已被注册的网络事件发生时,系统将向应用程序发送消息,该消息将由参数hWnd指定的窗口的相应消息处理函数进行处理,编写相应的消息处理函数是程序编写的主要工作之一。

      注意:注册网络事件时需要指定事件发生时需要发送的消息以及处理该消息的窗口的句柄。

      程序运行时,一旦被注册的事件发生,系统将向指定的窗口发送指定的消息。

int WSAAsyncSelect
{
    SOCKET s,  //需要事件通知的套接字
    HWND hWnd,//当网络事件发生时接收消息的窗口句柄
    unsigned int wMsg,  //当网络事件发生时向窗口发送的用户自定义消息
    long lEvent  //要注册的应用程序感兴趣的套接字s的网络事件集合

};

   函数返回值:应用程序感兴趣的事件注册成功,则返回0;如果注册失败,则返回SOCKET_ERROR。

       常用的网络事件包括FD_READ网络事件、FD_WRITE事件、FD_ACCEPT事件、FD_CONNECT事件、FD_CLOSE事件等。    

  •      FD_READ事件:读数据就绪的通知事件。事件触发时调用recv(), recvfrom(), WSARecv(), WSARecvfrom()。
  •      FD_WRITE事件:写数据就绪的通知事件。事件触发时调用send(), sendto(), WSASend(), WSASendto()。
  •       FD_ACCEPT事件:当前有连接请求需要接受。事件触发时调用accept(), WSAAccept()。
  •       FD_CONNECT事件:调用connect()函数后,建立连接完成。
  •       FD_CLOSE事件:仅对面向连接套接字有效,收到套接字关闭时触发。

   

Tips:

在VC++2017不鼓励使用 WSAAsyncSelect()模型,若使用编译器将发出错误警告并停止编译,如果要关闭错误警告继续编译,需要在头文件stdAfx.h中添加如下宏定义:

  • #define _WINSOCK_DEPRECATED_NO_WARNINGS

或者在调用该函数的CPP文件头部使用以下预处理命令:

  • #pragma warning(disable : 4996)

(3)使用 WSAAsyncSelect模型接收数据的过程

  •        调用recv()函数接收数据前,首先调用WSAAsyncselect()函数注册网络事件、事件发生时发出的用户自定义消息及处理消息的窗口。
  •        当系统收到数据时,系统将向应用程序发送消息。
  •        应用程序接收到这个消息后,将在消息对应的消息处理函数中调用recv()函数接收数据并处理数据。

 (4)WSAAsyncSelect模型的编程方法

     WSAAsyncSelect模型是基于Windows消息机制的,而其WSAAsyncSelect()函数要求消息的接收对象必须是一个窗口,因此基于WSAAsyncSelect模型的应用程序一般都是图形界面的窗口应用程序。

  程序的编写可以分为两大部分:建立并完善应用程序框架、编写消息处理函数。

   ① 第一步建立并完善应用程序框架需要完成如下任务:

(1)使用应用程序向导创建对话框应用程序框架;

(2)设计程序界面,主要是绘制控件并设置相关属性等;

(3)为相关控件添加控件变量;

(4)将通信所必须的套接字变量作为成员变量添加到窗口类中;

(5)添加WSAAsyncSelect()函数在为套接字注册网络事件时发送的自定义消息;

(6)在窗口类的成员函数OnInitDialog()中添加程序代码,完成创建套接字、给套接字绑定地址、使套接字处于监听状态、调用WSAAsyncSelect()函数为套接字注册网络事件等功能。

  ②第二步编写消息处理函数是程序设计的主要工作,除了编写相关控件消息的处理函数外,最主要的就是为套接字编写与网络事件关联的自定义消息的处理函数,在这些处理函数中要调用相关的套接字函数完成相关的IO处理。

      网络事件消息的处理函数具有类似下面代码所示的原型。

       afx_msg LRESULT OnSocketMsg(WPARAM wParam, LPARAM lParam);

      wParam参数存放发生网络事件的套接字的句柄,lParam参数的低16位存放的是发生的网络事件,高16位则用于存放网络事件发生错误时的错误码。

     函数的参数个数和类型是由系统规定的,它们的值在因消息到达而触发函数运行时由系统传入。

(5) 使用WSAAsyncSelect模型实现服务器

      为了配合基于消息的选择模型,服务器的设计采用MFC对话框类程序。该程序的客户端仍然沿用标准客户端StdClient.exe,或者可以开发一个基于对话框的标准客户端。

(1)使用“应用程序向导”创建“对话框应用程序”框架(项目名称为MsgSelectServer),其间应注意要在“高级功能”对话框中选中“Windows套接字”复选框,完成框架后要注意将项目所使用的字符集改为“多字节字符集”。

(2)按照图示服务器程序界面,为程序添加控件并调整大小和位置。

(3)通过类向导分别为列表框控件(用于显示和回射的内容)、“启动”按钮添加控件变量m_CListBox(类别为Control)、和m_StartButton(类别为Control)。

(4)在应用程序的主头文件MsgSelectServer.h中的CMsgSelectServerApp类定义之前添加如下代码,定义两个自定义消息,这两个消息分别是注册监听套接字的FD_ACCEPT事件和注册已连接套接字的FD_READ事件时关联的消息。

#define MsgAccept    WM_USER +100

#define MsgRecv      WM_USER +101

(5)通过类向导或者直接在文件MsgSelectServerDlg.h中的对话框类的定义中,添加如下自定义成员变量

SOCKET m_ListenSocket;   //监听套接字变量

SOCKET m_acceptSocket;  //存储连接建立后accept得到的套接字号

struct sockaddr_in addr, client_addr;  //分别存储本地地址和客户端地址

在MsgSelectServerDlg.h文件开始处添加常量定义:

#define PORT 8883  //监听端口

#define  BUFFER_LEN 1000   //接收缓冲区长度

(6)在MsgSelectServerDlg.cpp文件中的CMsgSelectServerDlg::OnInitDialog()函数中添加如下代码,来创建套接字、给套接字绑定地址、使套接字处于监听状态,并调用WSAAsyncSelect()函数,为监听套接字注册FD_ACCEPT异步事件。

(7) 利用类向导添加自定义消息MsgAccept及其消息处理函数。该消息发出时,说明有客户的连接请求到达,因此,该消息处理函数调用accept()与客户建立连接,并为连接成功后得到的套接字注册FD_READ事件和MsgRecv消息。

(8)利用类向导添加自定义消息MsgRecv及其消息处理函数。该消息发出时,说明有数据到达,因此,该消息处理函数调用recv()函数接收数据,并将数据添加到ListBox控件中显示。

 Tips:

为了能让VC++2019能忽略对WSAAsyncSelect()函数的警告而顺利编译,在头文件stdafx.h中的预处理命令 #define _AFX_ALL_WARNINGS之下,添加如下宏定义:

#define _WINSOCK_DEPRECATED_NO_WARNINGS

在“调试”->"MsgSelectServer调试属性"->"C/C++"->“常规”->"sdl检查"->“否”

2、基于事件的选择模型

(1)WinSock中的网络事件与事件对象函数

  •         WSAEventSelect模型与WSAAsyncSelect一样都属于异步I/O模型,二者的不同之处在于网络事件发生时系统通知应用程序的形式不同。
  •        WSAAsyncSelect模型是基于Windows的消息机制的,网络事件发生时系统将以消息的形式通知应用程序,并且消息必须与窗口句柄相关联,因此程序必须要有窗口对象才行。
  •        WSAEventSelect模型是以事件对象为基础的,网络事件需要与事件对象关联,当网络事件发生时,经由事件对象句柄通知应用程序。

 ①WSACreateEvent()函数

  • 功能是创建一个“人工重设模式”工作的事件对象,初始为“无信号”状态。
  • 函数原型:WSAEVENT  WSACreateEvent( void );
  • 该函数无参数。函数执行成功则返回事件对象句柄,否则返回WSA_INVALID_EVENT。其中WSAEVENT是事件对象句柄类型。
  • 该函数是CreateEvent()函数的扩展,但它创建的是人工重设模式的事件对象,而CreateEvent()函数创建的则是自动重设模式。如果程序需要一个自动重设模式的事件对象,可直接使用CreateEvent()函数。

②WSAResetEvent()函数

  • 该函数将事件对象从“有信号”状态更改为“无信号”状态。函数原型如下:
  • BOOL  WSAResetEvent(WSAEVENT hEvent);
  • –参数hEvent是要设置的事件对象的句柄。
  • –如果该函数调用成功,则函数返回TRUE;反之函数返回FALSE。

③WSASetEvent()函数 

  • 该函数将事件对象设置为“有信号”状态,函数原型:
  • BOOL  WSASetEvent(WSAEVENT hEvent);
  • 函数参数hEvent是要设置的事件对象的句柄。
  • 如果该函数调用成功,则函数返回TRUE;反之函数返回FALSE。

④WSACloseEvent() 函数 

  • 释放事件对象占有的系统资源。该函数声明如下:
  •   BOOL  WSACloseEvent(WSAEVENT hEvent);
  • –函数参数hEvent是要释放的事件对象的句柄。
  • –如果函数调用成功,该函数返回TRUE;否则返回FALSE。

(2) WSAEventSelect模型的函数

  •       WSAEventSelect()函数是WSAEventSelect模型的核心,该函数能够为套接字注册感兴趣的网络事件,将网络事件与事件对象关联起来。
  •       该模型的网络事件与WSAAsyncSelect模型完全相同。当为套接字注册的网络事件发生时,关联的事件对象将从“无信号”状态转变为“有信号”状态。
//网络时间注册函数
int WSAEventSelect
{
    SOCKET  s, //套接字
    WSAEVENT hEventObject,  //事件对象句柄
    Long  lNetworkEvents  //应用程序感兴趣的网络事件集合
};

注意:

  • (1)如果应用程序同时对多个网络事件感兴趣,需要对网络事件类型执行按位OR(|)运算。

例:应用程序对套接字s上的网络事件FD_READ和FD_CLOSE感兴趣,则可使用如下代码注册网络事件:

SOCKET  s;
WSAEVENT  hEvent;
int  nReVal=WSAEventSelect(s, hEvent, FD_READ|FD_CLOSE);

  • (2)要取消为套接字注册的网络事件,必须再次调用WSAEventSelect()函数,并将InetworkEvents参数设置为0。

例:要取消上面例子中为套接字s注册的网络事件,则只需使用如下一行代码:

WSAEventSelect( s, hEvent, 0);

  • (3)应用程序调用WSAEventSelect()函数后,套接字将被自动设置为非阻塞模式。如果要将套接字设置为阻塞模式,必须先取消套接字上注册的网络事件,然后再调用ioctlsocket()函数将套接字设置为阻塞模式。如果不取消已注册的网络事件而直接调用ioctlsocket()函数来设置套接字为阻塞模式,将会失败并返回WSAEINVAL错误。

 (3)网络事件等待函数WSAWaitForMultipleEvents()       

  •        该函数的功能是等待与套接字关联的事件对象由“无信号”状态变为“有信号”状态。
  •        应用程序在调用WSAEventSelect()函数为套接字注册网络事件后调用该函数等待事件发生,事件发生前该函数将阻塞等待,直到等待的事件发生或设置的等待时间超时该函数才会返回。
//函数原型
DWORD WSAWaitForMultipleEvents
{
    DWORD  cEvents,
    const WSAEVENT FAR * lphEvents,
    BOOL  fWaitAll,
    DWORD dwTimeout,
    BOOL   fAlertable
 };

    

函数参数

  • cEvents:等待的事件对象句柄的数量。等待事件对象句柄数量至少为1,最多数量为WSA_MAXIMUM_WAIT_EVENTS,其值为64个;
  • lphEvents:指向事件对象句柄的指针,实际上是一个WSAEVENT类型的数组,参数cEvents则是数组中事件对象句柄的数量;
  • fWaitAll:该参数为TRUE,则该函数在lphEvents中所有的事件对象都转变为“有信号”状态时才返回,若为FALSE,则在其中一个事件句柄转变为“有信号”状态时就返回,并且返回值指示出促使函数返回的事件对象;
  • dwTimeout:函数阻塞等待的时间,单位为毫秒。超过该等待时间,即使没有满足fWaitAll参数指定的条件函数也会返回。如果该参数为0,则函数检查事件对象的状态并立即返回。如果该参数为WSA_INFINITE,则该函数会无限期等待下去,直到满足fWaitAll参数指定的条件。
  • fAlertable:该参数主要用于重叠I/O模型,在完成例程的处理过程使用。如果该参数为TRUE,说明该函数返回时完成例程已经被执行。如果该参数为FALSE,说明该函数返回时完成例程还没有执行。这里只要将该参数设置为FALSE就可以了。
  • 返回值代表使该函数返回的事件对象,分4种情况:

    (1)一个从WSA_WAIT_EVENT_0到WAS_WAIT_EVENT_0+cEvents-1范围的值,其中宏WAS_WAIT_EVENT_0的值为0,这时如果fWaitAll为TRUE,则表示所有事件对象都处于“有信号”状态,如果fWaitAll为FALSE,则返回值减去WAS_WAIT_EVENT_0,即为“有信号”事件对象在lphEvents数组中的序号;

    (2)WAIT_IO_COMPLETION,表示一个或者多个完成例程已经排队等待执行;

    (3)WSA_WAIT_TIMEOUT,表示函数调用超时,并且所有事件对象都没有处于“有信号”状态。

    (4)如果该函数调用失败,则返回值为WSA_WAIT_FAILED。

(4)网络事件枚举函数WSAEnumNetworkEvents()

        用于获取套接字上发生的网络事件,同时清除系统内部的网络事件记录,如果需要,还可以重置事件对象。

//函数原型

int WSAEnumNetworkEvents

{
    SOCKET s,

    WSAEVENT hEventObject,

    LPWSANETWORKEVENTS lpNetworkEvents
};

函数参数

–s:发生网络事件的套接字句柄。

–hEventObject:被重置的事件对象句柄(可选)

–lpNetworkEvents:指向WSANETWORKEVENTS结构指针。在该结构中包含发生网络事件的记录和相关错误代码。

//WSANETWORKEVENTS结构声明如下:

typedef struct _WSANETWORKEVENTS {

  long  lNetworkEvents;

  int   iErrorCode[FD_MAX_EVENTS];

} WSANETWORKEVENTS, *LPWSANETWORKEVENTS;

      lNetworkEvents:发生的网络事件。事件对象进入“有信号”状态时,在套接字上可能会发生多个网络事件,因此本参数记录的可能是多个网络事件。

      iErrorCode:包含网络事件错误代码的数组。错误代码与lnetworkEvents字段中的网络事件对应。在应用程序中,使用网络事件错误标识符对iErrorCode数组进行索引,检查是否发生了网络错误。这些标识符命名规则是在对应的网络事件后面添加“_BIT”。例如,对应于FD_READ网络事件的网络事件错误标识符为FD_READ_BIT,网络错误标识符代表是iErrorCode数组序号。

      该函数调用成功时返回值为0,反之为SOCKETS_ERROR。如果该函数返回SOCKET_ERROR错误,则事件对象不会被重置,网络事件也不会被清除。

      在调用WSAEnumNetworkEvents()函数时,如果参数hEventObjec不为NULL,则该参数指定的事件对象被置为“无信号”状态。通常参数hEventObjec被指定为与s指定的套接字相关联的事件对象,如果该参数设为NULL,则应用程序必须要调用WSAResetEvent()函数来将关联事件对象设置为“无信号”状态。

 (5)WSAEventSelect模型的编程方法

WSAEventSelect模型编程的基本步骤是:

①创建一个事件对象数组,用于存放所有的事件对象;

②为相关的套接字创建事件对象;

③调用WSAEventSelect()函数将事件对象和需要关注套接字的网络事件关联起来;

④调用WSAWaitForMultipleEvents()函数等待网络事件发生。当有网络事件发生时关联的事件对象将变为“有信号”状态,此时在事件对象上等待的WSAWaitForMultipleEvents()函数将会立即返回;

⑤调用WSAEnumNetworkEvents函数,查询发生事件的事件对象获取具体发生的网络事件类型;

 ⑥根据网络事件类型调用相应的套接字函数进行处理。

       编写一个符合自定义标准的服务器端程序。要求服务器端使用WSAEventSelect模型,允许同时有多个客户接入,并能够持久与服务器通信。

  • 在调用WSAWaitForMultipleEvents()时,尽管fWaitALL参数指定为FALSE,但返回时它所等待的事件对象中仍可能有多个已检测到网络事件发生,这时返回的是所有已触发的事件对象中的在对象数组中下标值最小的,为了确保对所有的事件对象进行处理,需要对下标大于等于返回值nIndex的事件对象进行逐一检查,检查注册的网络事件是否发生,并对发生事件做出处理。
  • 这里判断一个事件对象是否有事件发生仍使用WSAWaitForMultipleEvents()函数,只不过其cEvents参数应指定为1,lphEvents参数为要查看的事件对象句柄变量的地址,而且也不能阻塞太长时间,所以参数dwTimeOUT需指定为有限值。

FD_WRITE事件只有在以下情况下才会触发:

  • ①在建立连接成功时,客户服务器两端都会触发FD_WRITE事件;
  • ②send(WSASend)/sendto(WSASendTo)发送失败返回WSAEWOULDBLOCK,并且当缓冲区有可用空间时,则会触发FD_WRITE事件。

       第①种情况在本例中虽能频繁出现,但accept()返回的同时才获取套接字描述符,用于监视套接字的事件对象还没有创建,因此在这里用事件对象无法捕捉。在第②种情况中,由于只有套接字的发送缓冲区满的时候调用send()才会返回 WSAEWOULDBLOCK错误,因此 FD_WRITE 触发的前提是缓冲区要先被充满然后随着数据的发送又出现可用空间,而不是只要缓冲区中有可用空间。由于本例中只发送少量数据,套接字发送缓冲区不可能占满。

      从这里也可以知道,程序中需要发送数据时,应直接调用send()发送,而不应使用FD_WRITE触发。FD_WRITE一般用于发送大量数据时,调用send()函数发送数据失败返回WSAEWOULDBLOCK后,触发数据的再次发送。

如有错误,敬请指正。

您的收藏与点赞都是对我最大的鼓励和支持!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/36439.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

IDEA常用插件

笔记来源于B站视频 以下为视频的地址 【【尚硅谷】IDEA2022全新版教程,兼容JDK17(快速上手Java开发利器)】https://www.bilibili.com/video/BV1CK411d7aA?p26&vd_source581d732b20cb23e01428068f153a99ed 推荐1:Alibaba J…

MCE丨重组蛋白常见的融合标签

Q:什么是融合标签? A:融合标签是指利用 DNA 体外重组技术,在目的蛋白 N 端或 C 端进行融合表达的特定蛋白、多肽或寡肽标签。 Q:融合标签有什么作用? A:重组蛋白通过融合标签与包被在固相基质上…

第六章《类的高级特性》第5节:接口

在Java语言中,一个类只能继承一个父类,专业上把这种继承机制称为“单继承”。单继承是一种较为稳妥继承机制,能够规避很多潜在的问题,但这种继承机制的局限性也显而易见:子类不能从多个父类中继承属性和方法,从而无法最大程度的减少重复劳动。为了弥补这个缺陷,Java语言…

web前端-javascript-关系运算符(>、>=、<、<=、非数值,Unicode 编码说明)

文章目录关系运算符1. 说明2. > 大于号3. > 大于等于4. < 小于号5. < 小于等于6. 非数值的情况6.1. 对于非数值进行比较时&#xff0c;会将其转换为数字然后再比较6.2. 如果符号两端都是字符串时&#xff0c;不会将其转换为字符串进行比较6.3. 任何值和 NaN 做任何…

为什么单线程的Redis如此的快(Why is single-threaded Redis so fast)

视频地址&#xff1a;YouTube Why is Redis so fast? What fundamental design decisions did the developers make more than a decade ago that stood to test of time. Let’s take a look. Redis is a very popular in-memory database. It’s rock solid, easy to use, a…

HittER: Hierarchical Transformers for Knowledge Graph Embeddings

HittER: Hierarchical Transformers for Knowledge Graph Embeddings HittER由两部分组成&#xff1a; 1&#xff0c;底部&#xff1a;Entity Transformer 源实体的局部邻居的每个实体-关系对的特征提取。负责将实体关系对中所有有用特征打包成向量&#xff0c;以供顶部块使用…

mysql基础部分第一次复习(1-8章,到聚合函数)

基本的使用 show databases; create database 数据库名; //创建数据库 use 数据库名&#xff1b; //使用数据库 使用完use语句之后接下来的SQL操作都是针对当前数据库的了show tables; //查看某个数据库的所有表格 show tables from 数据库名&#xff1b;create table 表名称{…

C++--智能指针--1123

1.智能指针解决的问题 int div() {int a, b;cin >> a >> b;if (b 0)throw invalid_argument("除0错误");return a / b; } void Func() { // 1、如果p1这里new 抛异常会导致p1不会Delete而导致内存泄漏 // 2、如果p2这里new 抛异常会导致p1和p2都不会de…

【数据结构学习笔记】18:线段树(单点修改)

1 线段树上的操作 push_up(int u)&#xff1a;由子节点的信息去计算父节点的信息&#xff0c;例如两个子节点的区间和&#xff0c;加起来就是父节点表示的区间和。其中u是当前节点编号&#xff0c;表示用u的左右两个子节点来算一下自己这个节点的信息。push_down&#xff1a;将…

流氓设备检测和预防

自带设备 &#xff08;BYOD&#xff09; 策略中涉及的设备以及这些设备连接到的端口具有多个通信路径。确保这些设备及其路径在进入组织网络时立即被检测、评估和管理至关重要&#xff0c;因为非托管设备很容易成为安全风险。但是&#xff0c;在整个企业网络中同时添加许多设备…

反射、枚举、lambda——小记

文章目录反射反射定义反射相关的类Class 类反射示例获得Class对象的三种方式反射使用 ——代码面试题:你知道有几种创建对象的方式吗?反射优点和缺点枚举Lambda表达式概念Lambda表达式的语法代码反射 反射定义 Java的反射&#xff08;reflection&#xff09;机制是在运行状态…

路由策略和路由控制

路由策略和路由控制 路由策略 针对路由的发布&#xff0c;接收&#xff0c;引入进行控制&#xff0c;从而影响数据的路径或者可达性 路由匹配工具 ACL&#xff1a;访问前缀列表 一个ACL用多条规则组成&#xff0c;不同规则之间通过rule id进行区分&#xff0c;默认rule 步…

(附源码)python办公数据分析系统 毕业设计 021836

Python办公数据分析系统 摘 要 现代办公通过办公自动化系统可以大大提高的效率、节省成本、规范业务和流程&#xff0c;辅助提升管理水平。办公系统在单位信息化中占有非常重要的地位&#xff0c;涉及到单位的各个部门及绝大多数人员&#xff0c;流程和协作方面要求非常强。 办…

[附源码]java毕业设计英语知识竞赛报名系统

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

NDK 是什么 | FFmpeg 5.0 编译 so 库

前言 NDK 全称 Native Development Kit&#xff0c;也就是原生开发工具包 &#xff0c;官网对它有详细的 中文介绍 。可能一说到 NDK 或 JNI &#xff0c;大家脑子里第一反应就是集成 C/C 。其实 JNI 的含义是 Java Native Interface &#xff0c;这种接口允许 Java 和其他语言…

SpringBoot SpringBoot 原理篇 1 自动配置 1.3 bean 的加载方式【三】

SpringBoot 【黑马程序员SpringBoot2全套视频教程&#xff0c;springboot零基础到项目实战&#xff08;spring boot2完整版&#xff09;】 SpringBoot 原理篇 文章目录SpringBootSpringBoot 原理篇1 自动配置1.3 bean 的加载方式【三】1.3.1 第三种方式1 自动配置 1.3 bean …

体系结构26_输入输出系统(3)

盘阵列&#xff08;RAID&#xff09; 盘阵列容量大、速度快、可靠性高、造价低廉。它是目前解决计算机I/O瓶颈的有效方法之一&#xff0c;有着广阔的发展前景。 盘阵列有多种组织方式&#xff1a; RAID 0 亦称数据分块&#xff08;Striping&#xff09;&#xff0c;即把数据分…

推特群推掀开营销新篇章

与Facebook和Instagram相比&#xff0c;Twitter营销并不是一个非常热门的营销渠道&#xff0c;对于跨境卖家来说可能会有一些陌生和挑战&#xff0c;但是作为一个重要的营销渠道&#xff0c;Twitter在全球市场上拥有超过1.45亿的日活跃用户(超过3.26亿的月活跃用户)&#xff0c…

Pinia基本使用

文章目录1. 介绍2. Pinia 和 Vuex3. 安装和基本使用4. pinia修改数据状态5. pinia持久化处理6. 自定义插件1. 介绍 它是2019 年 11 月对于新版本的vue提供的组合Api进行的尝试&#xff0c;它可以很好的集合vue新的api方法&#xff0c;且还很好的支持ts的写法&#xff0c;Pinia…

web前端-javascript-运算符的优先级(如果遇到的优先级不清楚的,可以使用()来改变优先级)

文章目录运算符的优先级1. , 运算符2. 优先级2.1. 就和数学中一样&#xff0c;在 JS 中运算符也有优先级2.2. 在 JS 中有一个运算符优先级的表2.3. 但是这个表我们并不需要记忆2.3. &&和||的优先级运算符的优先级 var a, b, c;//var a1, b2 , c3; //alert(b);//var re…