C#环境下的钩子详解

C#环境下的钩子详解

摘自网上供自己备查: http://www.csharpwin.com/csharpspace/2423.shtml

 

1、 WINDOWS的消息机制
2、 HOOK介绍
3、 HOOK链
4、 HOOK钩子的作用范围
5、 HOOK类型
6、 回调函数
7、 HOOK钩子的安装与卸载
8、 HOOK实例演示

 

+++++++++++++++++++
WINDOWS的消息机制
+++++++++++++++++++
Windows系统是以消息处理为其控制机制,系统通过消息为窗口过程(windows
procedure)传递输入。系统和应用两者都可以产生消息。对于每个输入事件,例如用
户按下了键盘上的某个键、移动了鼠标、单击了一个控件上的滚动条,等等,系统都
将产生一系列消息。此外,对于应用带给系统的变化,如字体资源的改变、应用本身
窗口的改变,系统都将通过消息以响应这种变化。应用通过产生消息指示应用的窗口
完成特定的任务,或与其他应用的窗口进行通信。
每个窗口都有一个处理Windows系统发送消息的处理程序,称为窗口程序。它是
隐含在窗口背后的一段程序脚本,其中包含对事件进行处理的代码。
Windows系统为每条消息指定了一个消息编号,例如当一个窗口变为活动窗口时,它事
实上是收到一条来自Windows系统的WM_ACTIVATE消息,该消息的编号为6,它对应于窗
口的Activate事件。对于窗口来说,诸如Load,MouseDown等事件,实际上对应的是窗口
内部的消息处理程序,这些程序对于用户来讲是不可见的。
类似地,命令按钮也有消息处理程序,它的处理程序响应诸如WM_LBUTTONDOWN
和WM_RBUTTONDOWN之类的消息,即激活命令按钮的MouseDown事件。

WINDOWS的消息处理机制为了能在应用程序中监控系统的各种事件消息,提供
了挂接各种回调函数(HOOK)的功能。这种挂钩函数(HOOK)类似扩充中断驱动程序,
挂钩上 可以挂接多个反调函数构成一个挂接函数链。系统产生的各种消息首先被送
到各种挂接函数,挂接函数根据各自的功能对消息进行监视、修改和控制等,然后交
还控 制权或将消息传递给下一个挂接函数以致最终达到窗口函数。WINDOW系统的
这种反调函数挂接方法虽然会略加影响到系统的运行效率,但在很多场合下是非常有
用的,通过合理有效地利用键盘事件的挂钩函数监控机制可以达到预想不到的良好效
果。

+++++++++++
hook介绍
+++++++++++

  Hook(钩子)是WINDOWS提供的一种消息处理机制平台,是指在程序正常运
行中接受信息之前预先启动的函数,用来检查和修改传给该程序的信息,(钩子)实
际上是一个处理消息的程序段,通过系统调用,把它挂入系统。每当特定的消息发出,
在没有到达目的窗口前,钩子程序就先捕获该消息,亦即钩子函数先得到控制权。这
时钩子函数即可以加工处理(改变)该消息,也可以不作处理而继续传递该消息,还
可以强制结束消息的传递。
注意:安装钩子函数将会影响系统的性能。监测“系统范围事件”的系统钩子特
别明显。因为系统在处理所有的相关事件时都将调用您的钩子函数,这样您的系统将
会明显的减慢。所以应谨慎使用,用完后立即卸载。还有,由于您可以预先截获其它
进程的消息,所以一旦您的钩子函数出了问题的话必将影响其它的进程。记住:功能
强大也意味着使用时要负责任。

+++++++++++++
HOOK链
+++++++++++++

WINDOWS提供了14种不同类型的HOOKS;不同的HOOK可以处理不同的消
息。例如,WH_MOUSE HOOK用来监视鼠标消息。
WINDOWS为这几种HOOKS维护着各自的HOOK链表。HOOK链表是一串由
应用程序定义的回调函数(CALLBACK Function)队列,当某种类型的消息发生时,
WINDOWS向此种类型的HOOK链的第一个函数(HOOK链的顶部)发送该消息,
在第一函数处理完该消息后由该函数向链表中的下一个函数传递消息,依次向下。如
果链中某个函数没有向下传送该消息,那么链表中后面的函数将得不到此消息。(对
于某些类型的HOOK,不管HOOK链中的函数是否向下传递消息,与此类型HOOK
联系的所有HOOK函数都会收到系统发送的消息)一些Hook子过程可以只监视消息,
或者修改消息,或者停止消息的前进,避免这些消息传递到下一个Hook子过程或者
目的窗口。最近安装的钩子放在链的开始,而最早安装的钩子放在最后,也就是后加
入的先获得控制权。

 

+++++++++++++++++
钩子的作用范围
++++++++++++++++

一共有两种范围(类型)的钩子:局部的和远程的。
一、局部钩子仅钩挂您自己进程的事件。
二、远程的钩子还可以将钩挂其它进程发生的事件。
远程的钩子又有两种:
1、基于线程的 它将捕获其它进程中某一特定线程的事件。简言之,就是可
以用来观察其它进程中的某一特定线程将发生的事件。
2、系统范围的 将捕捉系统中所有进程将发生的事件消息。

+++++++++++++
HOOK类型
+++++++++++++

      Windows共有14种HOOKS,每一种类型的Hook可以使应用程序能够监视不同
类型的系统消息处理机制。下面描述所有可以利用的Hook类型的发生时机。(这些常
数值均可以API浏览器里查到)

1、WH_CALLWNDPROC和WH_CALLWNDPROCRET Hooks

      WH_CALLWNDPROC和WH_CALLWNDPROCRET Hooks使你可以监视发送到
窗口过程的消息。系统在消息发送到接收窗口过程之前调用WH_CALLWNDPROC
Hook子过程,并且在窗口过程处理完消息之后调用WH_CALLWNDPROCRET Hook
子过程。

      WH_CALLWNDPROCRET Hook传递指针到CWPRETSTRUCT结构,再传递到
Hook子过程。CWPRETSTRUCT结构包含了来自处理消息的窗口过程的返回值,同
样也包括了与这个消息关联的消息参数。

2、WH_CBT Hook

      在以下事件之前,系统都会调用WH_CBT Hook子过程,这些事件包括:
      1. 激活,建立,销毁,最小化,最大化,移动,改变尺寸等窗口事件;
      2. 完成系统指令;
      3. 来自系统消息队列中的移动鼠标,键盘事件;
      4. 设置输入焦点事件;
      5. 同步系统消息队列事件。
    
      Hook子过程的返回值确定系统是否允许或者防止这些操作中的一个。

3、WH_DEBUG Hook

      在系统调用系统中与其它Hook关联的Hook子过程之前,系统会调用
WH_DEBUG Hook子过程。你可以使用这个Hook来决定是否允许系统调用与其它
Hook关联的Hook子过程。

4、WH_FOREGROUNDIDLE Hook

      当应用程序的前台线程处于空闲状态时,可以使用WH_FOREGROUNDIDLE
Hook执行低优先级的任务。当应用程序的前台线程大概要变成空闲状态时,系统就
会调用WH_FOREGROUNDIDLE Hook子过程。

5、WH_GETMESSAGE Hook

      应用程序使用WH_GETMESSAGE Hook来监视从GetMessage or PeekMessage函
数返回的消息。你可以使用WH_GETMESSAGE Hook去监视鼠标和键盘输入,以及
其它发送到消息队列中的消息。

6、WH_JOURNALPLAYBACK Hook

      WH_JOURNALPLAYBACK Hook使应用程序可以插入消息到系统消息队列。可
以使用这个Hook回放通过使用WH_JOURNALRECORD Hook记录下来的连续的鼠
标和键盘事件。只要WH_JOURNALPLAYBACK Hook已经安装,正常的鼠标和键盘
事件就是无效的。WH_JOURNALPLAYBACK Hook是全局Hook,它不能象线程特定
Hook一样使用。WH_JOURNALPLAYBACK Hook返回超时值,这个值告诉系统在处
理来自回放Hook当前消息之前需要等待多长时间(毫秒)。这就使Hook可以控制实
时事件的回放。WH_JOURNALPLAYBACK是system-wide local hooks,它们不会被
注射到任何行程地址空间。

7、WH_JOURNALRECORD Hook
     WH_JOURNALRECORD Hook用来监视和记录输入事件。典型的,可以使用这
个Hook记录连续的鼠标和键盘事件,然后通过使用WH_JOURNALPLAYBACK Hook
来回放。WH_JOURNALRECORD Hook是全局Hook,它不能象线程特定Hook一样
使用。WH_JOURNALRECORD是system-wide local hooks,它们不会被注射到任何行
程地址空间。

8、WH_KEYBOARD Hook

      在应用程序中,WH_KEYBOARD Hook用来监视WM_KEYDOWN and
WM_KEYUP消息,这些消息通过GetMessage or PeekMessage function返回。可以使
用这个Hook来监视输入到消息队列中的键盘消息。

9、WH_KEYBOARD_LL Hook

      WH_KEYBOARD_LL Hook监视输入到线程消息队列中的键盘消息。

10、WH_MOUSE Hook

      WH_MOUSE Hook监视从GetMessage 或者 PeekMessage 函数返回的鼠标消息。
使用这个Hook监视输入到消息队列中的鼠标消息。

11、WH_MOUSE_LL Hook

      WH_MOUSE_LL Hook监视输入到线程消息队列中的鼠标消息。

12、WH_MSGFILTER 和 WH_SYSMSGFILTER Hooks

      WH_MSGFILTER 和 WH_SYSMSGFILTER Hooks使我们可以监视菜单,滚动
条,消息框,对话框消息并且发现用户使用ALT+TAB or ALT+ESC 组合键切换窗口。
WH_MSGFILTER Hook只能监视传递到菜单,滚动条,消息框的消息,以及传递到通
过安装了Hook子过程的应用程序建立的对话框的消息。WH_SYSMSGFILTER Hook
监视所有应用程序消息。
    
      WH_MSGFILTER 和 WH_SYSMSGFILTER Hooks使我们可以在模式循环期间
过滤消息,这等价于在主消息循环中过滤消息。
    
通过调用CallMsgFilter function可以直接的调用WH_MSGFILTER Hook。通过使用这
个函数,应用程序能够在模式循环期间使用相同的代码去过滤消息,如同在主消息循
环里一样。

13、WH_SHELL Hook

      外壳应用程序可以使用WH_SHELL Hook去接收重要的通知。当外壳应用程序是
激活的并且当顶层窗口建立或者销毁时,系统调用WH_SHELL Hook子过程。
    WH_SHELL 共有5钟情况:
1. 只要有个top-level、unowned 窗口被产生、起作用、或是被摧毁;
2. 当Taskbar需要重画某个按钮;
3. 当系统需要显示关于Taskbar的一个程序的最小化形式;
4. 当目前的键盘布局状态改变;
5. 当使用者按Ctrl+Esc去执行Task Manager(或相同级别的程序)。

      按照惯例,外壳应用程序都不接收WH_SHELL消息。所以,在应用程序能够接
收WH_SHELL消息之前,应用程序必须调用SystemParametersInfo function注册它自
己。


++++++++++++++++++++++++++
回调函数(HOOK处理子过程)
++++++++++++++++++++++++++

为了拦截和处理特定的消息,你可以使用SetWindowsHookEx函数(下面将具体
说明这些函数的声明及各种参数)在该类型的HOOK链中安装你自己的处理HOOK
的子过程(回调函数)。只要您安装的钩子的消息事件类型发生,WINDOWS就将调
用钩子函数。譬如您安装的钩子是WH_MOUSE类型,那么只要有一个鼠标事件发生
时,该钩子函数就会被调用。不管您安装的是那一类型钩子,钩子函数的原型都时是
一样的,语法如下:

public int MyHook(int nCode, Int32 wParam, IntPtr lParam)
{

//处理代码

}

其中MyHook可以随便命名,其它不能变。该函数必须放在模块段。
参数说明:
nCode指定HOOK传入的信息类型。Hook子过程使用这个参数来确定任务。这个
参数的值依赖于Hook类型,每一种Hook都有自己的Hook代码特征字符集。
wParam:短整型参数。
lParam:长整型参数。
wParam,iParam的取值随nCode不同而不同,它代表了某种类型的HOOK的某个特
定的动作。它们的典型值是包含了关于发送或者接收消息的信息。
至于以上的几个参数及返回值的具体含义,各种类型的钩子都不相同,所以您必须查询
WIN32 API 指南来得到不同类型钩子参数的详细定义以及它们返回值的意
义。
譬如:
WH_CALLWNDPROC
nCode 只能是HC_ACTION,它代表有一个消息发送给了一个窗口
wParam 如果非0,代表正被发送的消息
lParam 指向CWPSTRUCT型结构体变量的指针
return value: 未使用,返回0
WH_MOUSE
nCode 为HC_ACTION 或 HC_NOREMOVE
wParam 包含鼠标的事件消息
lParam 指向MOUSEHOOKSTRUCT型结构体变量的指针
return value: 如果不处理返回0,否则返回非0值

++++++++++++++++++++++++++
钩子的安装/卸载
++++++++++++++++++++++++++

现在我们知道了一些基本的理论,接下来开始讲解如何安装和卸载一个钩子。


◆安装钩子

使用SetWindowsHookEx函数(API函数),指定一个HOOK类型、自己的HOOK
过程是全局还是局部HOOK,同时给出HOOK过程的进入点,就可以轻松的安装你
自己的HOOK过程。
SetWindowsHookEx总是将你的HOOK函数放置在HOOK链的顶端。你可以使用
CallNextHookEx函数将系统消息传递给HOOK链中的下一个函数。
[注意]对于某些类型的HOOK,系统将向该类的所有HOOK函数发送消息,这时,
HOOK函数中的CallNextHookEx语句将被忽略。

全局(远程钩子)HOOK函数可以拦截系统中所有线程的某个特定的消息,为了
安装一个全局HOOK过程,必须在应用程序外建立一个DLL,并将该HOOK函数封
装到其中,应用程序在安装全局HOOK过程时必须先得到该DLL模块的句柄。将DLL
名传递给LoadLibrary 函数,就会得到该DLL模块的句柄;得到该句柄 后,使用
GetProcAddress函数可以得到HOOK过程的地址。最后,使用SetWindowsHookEx将
HOOK过程的首址嵌入相应的HOOK链中,SetWindowsHookEx传递一个模块句柄,
它为HOOK过程的进入点,线程标识符置为0,指出:该HOOK过程同系统中的所
有线程关联。如果是安装局部HOOK此时该HOOK函数可以放置在DLL中,也可以
放置在应用程序的模块段。

建议只在调试时使用全局HOOK函数。全局HOOK函数将降低系统效率,并且
会同其它使用该类HOOK的应用程序产生冲突。

SetWindowsHookEx函数的C#声明及参数解释:
public delegate int HookProc(int nCode, int wParam, IntPtr lParam);
[DllImport("user32.dll", CharSet = CharSet.Auto,
CallingConvention = CallingConvention.StdCall, SetLastError = true)]
public static extern int SetWindowsHookEx(int idHook,HookProc lpfn,IntPtr hMod,int dwThreadId);

SetWindowHookEx函数参数说明:
idHook:代表是何种Hook(也就是上面讲的14种Hook)

HookProc:代表处理Hook的过程的委托,这是一个CallBack Fucnction(也就是上
面讲的回调函数),当挂上某个Hook时,我们便得定义一个Function来当作某个信
息产生时,来处理它的Functionhmod:代表.DLL的hInstance,如果是Local Hook,
该值可以是Null,而如果是Remote Hook,则可以使用System.Reflection.GetModule
(".dll名称")来传入。

dwThreadId:代表执行这个Hook的ThreadId(线程ID),如果是全局钩子,
则传0ThreadID是您安装该钩子函数后想监控的线程的ID号。该参数可以决定
该钩子是局部的还 是系统范围的。如果该值为NULL,那么该钩子将被解释成
系统范围内的,那它就 可以监控所有的进程及它们的线程。如果您指定了您自己
进程中的某个线程ID 号, 那该钩子是一个局部的钩子。如果该线程ID是
另一个进程中某个线程的ID,那该 钩子是一个全局的远程钩子。这里有
两个特殊情况:WH_JOURNALRECORD 和 WH_JOURNALPLAYBACK总是代表局部
的系统范围的钩子,之所以说是局部,是 因为它们没有必要放到一个DLL中。
WH_SYSMSGFILTER 总是一个系统范围内 的远程钩子。其实它和WH_MSGFILTER钩子
类似,如果把参数ThreadID设成0 的话,它们就完全一样了。

SetWindowHookEx函数回值: 如果SetWindowsHookEx()成功,它会传回一个值,
代表目前的Hook的Handle,否则返回NULL。您必须保存该句柄,因为后面我们
还要它来卸载钩子。

CallNextHookEx函数的C#声明及参数解释:

[DllImport("user32.dll", CharSet = CharSet.Auto,
CallingConvention = CallingConvention.StdCall)]
public static extern int CallNextHookEx(int idHook,int nCode,int wParam,IntPtr lParam);
hHook值是SetWindowsHookEx()的传回值,nCode, wParam, lParam则是回调函数
中的三个参数。

在钩子子程中调用得到控制权的钩子函数在完成对消息的处理后,如果想要该消
息继续传递,那么它必须调用另外一个API函数CallNextHookEx来传递它,以执行
钩子链表所指的下一个钩子子过程。这个函数成功时返回钩子链中下一个钩子过程的
返回值,返回值的类型依赖于钩子的类型。

 

◆ 卸载钩子

要卸载一个钩子非常简单,只需要使用UnhookWindowsHookEx函数来卸载创建
的钩子。
函数声明:
[DllImport("user32.dll", CharSet = CharSet.Auto,
CallingConvention = CallingConvention.StdCall, SetLastError = true)]
public static extern int UnhookWindowsHookEx(int idHook);

参数说明:
hHook:是SetWindowsHookEx()的传回值。

posted on 2013-01-17 14:23 Alfa 阅读(...) 评论(...) 编辑 收藏

转载于:https://www.cnblogs.com/wuyifu/archive/2013/01/17/2864399.html

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

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

相关文章

福昕PDF阅读器的图章妙用

前几天同事发来一个pdf文件,说要把其中一部分遮住。我本来还想用pdf编辑软件直接给删除,结果发现是扫描文件制作的pdf不能编辑,大呼坑爹又要用ps了(那家伙太慢,太占内存)。 不想打开ps,于是开始…

openldap linux客户端,OpenLDAP 客户端安装部署

六、OpenLDAP客户端验证1、配置/etc/openldap/ldap.conf默认客户端不允许查询OpenLDAP条目信息,如果需要让客户端查询条目,需要添加OpenLDAP服务端的URI以及BASE条目,命令如下:2、客户端验证用户的信息添加我已经在上篇博文里面介…

奋斗的IT小小鸟

写了两集的《迷茫的IT小小鸟》,在经过了这么长的堕落与反思的阶段,终于也有点豁然开朗的感觉了,这学期以来浪费了太多的时间,本来规划的很好的时间和任务在自己一次次的说服不了自己的过程中终究没能实现,在这个期间更…

基于.Net Framework 4.0 Web API开发(4):ASP.NET Web APIs 基于令牌TOKEN验证的实现

概述: ASP.NET Web API 的好用使用过的都知道,没有复杂的配置文件,一个简单的ApiController加上需要的Action就能工作。但是在使用API的时候总会遇到跨域请求的问题, 特别各种APP万花齐放的今天,对API使用者身份角色验…

匈牙利命名法为何被淘汰_为何甲烷的习惯命名法用甲烷而不是一烷?

其实在有机化合物中文翻译早期,是有过用数字命名的阶段的,先上图。部分有机化合物在不同时期的汉译名对照那么后来为何未采用数字,而使用天干。与商务印书馆和郑贞文个人其实有很大关系。那么有机物中文命名的演进是怎样的呢?下面…

Windows下Mysql Cluster集群启动脚本与启动服务添加方法

3.2.8 集群启动脚本及启动服务注册 从上面的启动过程我们可以看出,Mysql集群启动命令较复杂,容易造成cmd窗口因误操作关闭而导致的数据库停止,在此我介绍一下如何将这些命令的操作变成windos的服务项,当windos启动时&#xff0…

c语言中for语句的作用是,c语言中for语句是怎么用的

匿名用户1级2018-11-20 回答1:for循环for语句的格式为:for (初始化语句; 条件语句; 控制语句){语句1 ;语句2 ;....语句n ;}for 语句的执行顺序是:首先执行“初始化语句”;然后测试“条件语句”;若条件成立,…

[Azure] Notification Hubs注册模式

[Azure] Notification Hubs注册模式 关于Azure Notification Hubs的注册模式,可以参考下列连结的文件内容。 Notification Hubs Features - Registration Management 文件里介绍了两种注册模式:手机主动注册、服务代理注册,这两个模式主要的差…

iOS 本地化应用程序汇总 国际化

最近要做一个应用要实现本地化,因为使用的是xcode4,应用程序本地化的问题跟以前的版本还是有些不同,在网上找了些资料对于xcode4以上的版本资料还是相对较少,有些最后要通过手动创建文件,这样操作实在是太麻烦&#xf…

图卷积神经网络_深度层次化图卷积神经网络

来源:IJCAI 2019论文地址:https://arxiv.org/abs/1902.06667代码地址:https://github.com/CRIPAC-DIG/H-GCNIntroduction1、问题定义:什么是半监督的节点分类?图1 半监督节点分类如图1所示,在标记数据量很少…

计算机二级怎么测试c语言,全国计算机等级测试二级C语言视频教程(完整版).doc...

第一章 程序设计的基本概念01-01.程序设计的基本概念(1)01-02.程序设计的基本概念(2)01-03.程序设计的基本概念(3)第二章 C语言基础知识02-01.简单C语言的构成和格式(1)02-02.简单C语言的构成和格式(2)02-03.标识符的组成和分类02-04.整型数据和实型数据(1)02-05.整型数据和实型…

去掉Phoca Download的Powered By

进入components/com_phocadownload/views/ 这是Phoca Download的模板文件夹 打开category/tmpl/default.php 分类页 //echo </div><div class"pd-cb"> </div> . $this->tmpl[phoca_download];echo </div> ; 打开file/tmpl/default.php …

如何居中div

div居中 博客分类&#xff1a;笔记csshtmldiv CSS中怎么让div居中 CSS 如何使div层水平居中今天用CSS遇到个的问题,div本身没有定义自己居中的属性, 网上很多的方法都是介绍用上级的text-align: center然后嵌套一层div来解决问题. 可是事实上这样的方法科学吗? 经过网络搜索…

c语言小数加分,求救:c语言课程设计 员工工资管理程序 有加分的。谢谢

#define SIZE 50/* 定义结构体 */struct date{int month;int day;int year;};typedef struct employee{char name[50] ,num[10],sex,edu[10],duty[15];int age,income;struct employee *next;}empl[SIZE];/* 逐项输出链表中的内容 */void view (struct employee* head){struct …

老师能提供什么帮助

老师能提供什么帮助&#xff1f; 这篇本来想上周写的&#xff0c;原计划在感恩节推送&#xff0c;可惜太忙&#xff0c;计划赶不上变化。 时隔十年&#xff0c;我又要给计算机系的同学们上课了&#xff0c;心里还是有些小激动的。我下学期要开一门大课叫程序设计与数据结构,涵盖…

(转)SystemProcessesAndThreadsInformation

http://hi.baidu.com/hanjdud8606/item/7a970408a95acc843d42e27f NTSTATUS NTAPI ZwQuerySystemInformation(ULONG SystemInformationClass,PVOID SystemInformation,ULONG SystemInformationLength,PULONG ReturnLength ); 第一个参数是一个枚举类型&#xff0c;传入的是你需…

12个Icon图标资源网站

1.除了Icon以外&#xff0c;还有很多不错的UI设计素材。 地址&#xff1a;http://worldui.com/2.除了免费Icon资源下载以外&#xff0c;还提供Icon定制的付费服务。地址&#xff1a;http://dryicons.com/3.很喜欢这个icon资源站的展示方式。地址&#xff1a;http://www.icotrip…

python列表split_Python-split()函数实例用法讲解

在Python中&#xff0c;split() 方法可以实现将一个字符串按照指定的分隔符切分成多个子串&#xff0c;这些子串会被保存到列表中(不包含分隔符)&#xff0c;作为方法的返回值反馈回来。split函数用法split(sepNone, maxsplit-1)参数sep – 分隔符&#xff0c;默认为所有的空字…

go语言基础 -- 闭包

什么是闭包 闭包的概念&#xff0c;在很多语言中都有&#xff0c;比如python&#xff0c;这里要介绍的go&#xff0c;闭包就是函数与其相关的环境组合的一个整体。 我们通过一个例子来理解闭包&#xff1a; func Addfunc() func (x int) int {var n int 0// 返回的是一个函数…

linux中解决SSH连接慢问题

2019独角兽企业重金招聘Python工程师标准>>> 现在连接linux服务器一般都是使用SSH远程连接的方式。最近新装了一台服务器&#xff0c;发现telnet时速度很快&#xff0c;ping时一切也正常&#xff0c;但SSH连接的时候却很慢。经过网上资料查询&#xff0c;大致是有以…