、   消息说明 

8.1     握手消息

8.1.1       RFB协议版本号

1、vnc服务器发送所能够支持的最高RFB协议版本号给客户端,格式如下:

  “RFB xxx.yyy\n”共12bytes,

  比如:“RFB
003.006\n”,即版本号为3.6,版本号固定格式为×××.×××,不足部分前面补零。
   

2、客户端回复将要使用的版本号,格式如上。客户端的版本号必须小于或等于服务器版本号。这样服务器可以实现向后兼容。
3、目前发布的协议版本主要有3.3、3.7、3.8(3.5版本被报告存在问题),最高版本号为4.0。

8.1.2      
协商安全类型

(一)v3.7以上版本安全类型
  服务器发送所支持的安全类型列表,如果客户端能支持服务器的某一安全类型,那么客户端就会发送一个字节来确认连接的安全类型:

  

  

  如果安全类型数是0,那么连接失败(例如服务器不支持客户请求版本号),这样就会有字符串来描述失败原因:

  

  服务器在发送原因字串后,就会关闭连接。

(二)3.7以下版本(以vnc认证为例)
  1、服务器发送一个无符号的32位整数标识一个安全类型(与认证有关)。
 
  

安全类型:

  

其他认证类型:

  

说明:
①0,连接失败(例如服务器不支持客户请求版本号),这样就会有字符串来描述失败原因:

服务器发送完reason-string就关闭连接。
②NONE,不需要认证(不要输密码),协议数据将被使用明文发送。
V3.8 以上版本, 还会带有安全结果的消息。
V3.3 和 3.7 协议直接进入初始报文.
③VNC认证,协议数据将采用明文发送,服务器发送一个16 字节的随机数。

客户端使用DES对验证进行加密,使用用户密码作为密钥,把16 字节的回复返回到服务器。

随之而来的就是安全结果消息。

2、服务器发送16位随机数。
3、客户端使用DES对验证进行加密,使用用户密码作为密钥,把加密后的16字节返回给服务器。
4、服务器对安全认证进行确认,返回值为无符号32位整数,如果为0则表示成功,1表示失败。如果不成功,服务器直接关闭连接。
   

  V3.8 以上版本 如果不成功,就会有字符串来描述失败原因,并关闭连接。

  

  对于V3.8以下,如果不成功,服务器直接关闭连接。

8.2    
初始化消息

  1、客户端发送一个字节的初始化消息。
   

  如果允许服务器其他客户继续连接,那么共享标志应该是非零(真)。否则,服务器将断开其他客户的连接。
  2、服务器发送初始化消息,主要告知客户端服务器的帧缓存(桌面屏幕)的高、宽、象素格式和桌面相关的名称。
   

  这个跟实现有关,有些实现是先发送24个字节,然后再发送桌面名字字符串。名称字符串格式如:sh-yinghua -1 ( 192.168.70.69 )。
帧缓存宽度一般为水平分辨率的大小,帧缓存高度一般是垂直分辨率的大小,比如1024×768等。
  象素格式主要包括以下段:
   

  服务器象素定义服务器本来的象素格式,这种象素格式会被一直使用,除非客户端使用设置象素格式消息来请求另一种象素格式。

  bits-per-pixel是表示每个像素值需要的位数。这个数字必须大于等于depth,而depth用来表示像素值中有用的位数。目前位每象素必须是8,16
或32——小于8 位象素不被支持。如果多字节象素被看做big-endian,那么Big-endian 标志非零。当然了,这对8 位每象素没有任何意义。

  如果真彩标志非零,那么最后6 项规定如何按照象素值来确定红、绿、蓝的亮度。红的最大值是红色的最大值(=2
^n - 1, n 表示用在红色上的位数)。注意这个值一般在big endian的顺序中。红色-替换表示要得到最低明显bit 所需要的替换个数。绿色最大值、绿色-替换和蓝色最大值、蓝色-替换和红色类似。要在0—红色最大值之间找一个红色值,按照以下步骤进行:

  1. 遵循big-endian 标志进行象素值。(例如:如果big-endian 标志为0,主机的字节顺序是big
    endian,然后交换)。
  2. 使用红色—替换将右边替换。
  3. 和红色最大值进行逻辑与(按照主机字节顺序)。

 如果真彩标志是零,那么服务器使用的象素值不是直接由红、绿、蓝的亮度组成,但是服务为索引到颜色图中去。颜色图中的项目是由服务器使用“设置颜色面板条目” (FixColourMapEntries)消息进行设置的。
  说明:位/象素一般为显示设置的颜色质量位数。

  目前的任何服务器都还不能支持FixColourMapEntries消息,只有基于X的服务器才能支持颜色映射。实际上,为了能够完全支持颜色映射,客户端大概需要能够指定特殊的、服务器不会使用的像素值。这可能会加在未来的协议版本里。

8.3    
客户端到服务器的消息

  所有客户端到服务器的消息第一个字节都为消息类型,数据类型U8。
  客户到服务器的消息在本文中有如下定义:
   

  其余的注册消息类型有:
   

  值得注意的是:如果要发送未在本文中定义的消息,那么必须得到服务器端的消息确认。

8.3.1      
SetPixelFormat设置象素格式消息

  “帧缓存更新”消息中设置什么格式的象素值如何设置。
  如果客户端没有发送“设置象素格式”消息,那么服务器发送的象素值将遵循在服务器初始化消息中所包括的象素格式。
  如果真彩标志是零,那么意味着使用“颜色面板”,只要客户端发送颜色面板空的消息,或者是面板项被服务器端重设,服务器可以使用设置颜色面板项目进行颜色面板的设置。
   

  注:其中的象素格式如在上文中的描述。

8.3.2      
SetEncoding设置编码格式

  设置编码方式可以来确定服务器发送象素数据的类型。消息中编码方式的顺序是客户端按照优先级来排列(第一个拥有最高的优先级)。服务器可能选择这种顺序,也可能不选择。
  象素数据也可以使用“原始编码”如果没有具体说明。

  除了基本的编码方式,客户端也可以请求“伪编码”通告服务器它支持某一种扩展协议。如果服务器不支持这种扩展,它就会忽略这种伪编码。注意:这意味着客户端在得到服务器的确认之前都要假设服务器并不支持它的扩展。
   

接下来就是编码数目个编码类型的重复

   

由编码类型决定编码格式。

8.3.3      
FramebufferUpdateRequest请求帧缓存更新

  通知服务器,客户对帧缓冲区中的某个区域感兴趣,这个区域由x坐标、y坐标、宽度和高度几个参数限定。
  服务器通常对FramebufferUpdateRequest消息的响应,是发送一条FramebufferUpdate消息。
  注意,可以发送一条FramebufferUpdate消息用来回复几条FramebufferUpdateRequest消息。
  服务器假定客户保留了帧服务器中它感兴趣的所有部分的副本。这意味着,服务器通常只需要向客户发送增量部分的更新。但是,如果由于某种原因,客户丢失了它所需要的一个特定区域的内容,就发送一条FramebufferUpdateRequest消息,把消息中的incremental(增量)置为0(false。这要求服务器把指定区域的全部内容尽可能快地发送过来。这个区域的更新不会使用copy rectangle编码方式。如果客户没有丢失它感兴趣区域的任何内容,就发送一条FramebufferUpdateRequest消息,把消息中的incremental设为非零(true。当帧缓冲区中的指定区域发生变化时,服务器会发送一条FramebufferUpdate消息。
注意,FramebufferUpdateRequest和FramebufferUpdate之间可能会有一段不确定长的间隔。
  
对于速度快的客户,它可能希望以固定频率发送增量的FramebufferUpdateRequests消息,以避免占用网络资源。
   

  增量标志incremental为0时,表示必须发送完整内容过来。

8.3.4      
KeyEvent按键事件

  某一个键的按下与释放。如果某一个键被按下,那么按下标志非零。释放的时候变为零。
  在X Window 系统中键本身被赋值为“keysym”。
   

  对于大多数键来说,“keysym”与ASCII码相对应,具体参考《The
Xlib ReferenceManual》或者参考。在Linux上为/usr/include/X11/keysymdef.h。
  对于大多数普通键,“keysym”和ASCII码的值是一致的(前面3个字节为0,最后一个字节为ASCII码)。其他的命令键为:
   

8.3.5      
PointerEvent鼠标(指针)事件

  检测指针移动或者某一个键的按下或释放。指针目前在(x坐标、y 坐标),鼠标按钮的各键采用1到8位掩码标识,0 表示松开,1 表示按下。拿普通鼠标来说,全零表示鼠标移动,第1,2,3 分别对应左、中、右键。对于滑轮鼠标来说,滚轮向上对应第4位,滚轮向下对应第5位。拖动操作是不断的发送左键按下的消息,并变换鼠标的坐标
 

8.3.6      
ClientCutText客户端文本剪切

  客户端有新的ISO8859 - 1(Latin - 1) 文本在它的剪切缓存里,行的末尾通过新行字符(值为10)来表示。 需要无回车(值为13)。目前还没有找到传输非Latin - 1 字符集的方法。
   

8.4    
服务器到客户消息

  服务器到客户消息在本文中定义如下:
  

  其余注册的消息类型:
   

  注意在服务器发送消息之前必须确认客户端支持相关扩展,通常在请求“伪编码”的时候使用。

8.4.1      
FramebufferUpdate帧缓存更新

  帧缓存更新是由一系列像素数据矩形而组成,这些矩形会被客户端送入它的帧缓存中。
  它是对客户端帧缓存更新请求的响应。而在请求和响应之间有可能存在不确定时期。
   

  随着像素数据矩形的个数,每个矩形包括以下内容:
    

  后面就是特定编码的数据。

设置颜色面板条目

  当像素格式使用“颜色面板”时,消息告诉客户端对应像素值如何映射为RGB亮度。
    

  下面就是重复具体的色彩
   

  目前对颜色映射的支持还很少甚至没有。这方面已经做了一些初步的工作,但是还没有完成。
  目前,只有基于X 的服务器能够完全支持颜色映射。

8.4.2      
SetColorMapEntries

  当且仅当在客户端发送FramebufferUpdateRequest并同意使用color
map的时候。服务端才可能发送SetColorMapEntries消息,这消息可能一次只更新整块color map中的一部分。

  color map每个值是16bits,范围[0,65535]

  此消息头部定义:

   

  后续就是number-of-colors个RGB值,每个RGB值对应如下格式:

  

8.4.3      
Bell响铃

  如果有响铃事件,就在客户端上响铃。

  

8.4.4      
ServerCutText服务器剪切文本

  如果服务器的剪切板有新内容,服务器主动发送该消息给客户端
   

8.4.5      
Encodings编码

  本文的编码类型

   

  其他编码类型

  
原始编码( Raw 编码)

  即采用原始的像素数据,而不进行任何的加工处理。在这种情况下,对于一个宽度乘以高度(即面积)为N的矩形,数据就由N个像素值组成,这些值表示按照扫描线顺序从左到右排列的每个像素。很明显,这种编码方式是最简单的,也是效率最低的。
  RFB要求所有的客户都必须能够处理这种原始编码的数据,并且在客户没有特别指定需要某种编码方式的时候,RFB服务器就默认生成原始编码。
 
  

复制矩形编码( CopyRect编码)

  CopyRect 编码方式对于客户端在某些已经有了相同的象素数据的时候是非常简单和有效的。这种编码方式在网络中表现为x,y 坐标。让客户端知道去拷贝那一个矩形的象素数据。它可以应用于很多种情况。最明显的就是当用户在屏幕上移动某一个窗口的时候,还有在窗口内容滚动的时候。在优化画的时候不是很明显,一个比较智能的服务器可能只会发送一次,因为它知道在客户端的帧缓存里已经存在了。
  复制矩形编码并不是完全独立地发送所有的数据矩形,而是对于像素值完全相同的一组矩形,只发送第一个矩形全部数据,随后的矩形则只需要发送左上角X、Y坐标。实际上,复制矩形编码主要指的就是随后的这一系列X、Y坐标,而对于第一个矩形具体采用何种编码类型并没有限制,仅仅需要知道第一个矩形在帧缓冲区中的位置,以便于完成复制操作。因此,往往是把复制矩形编码和其它针对某一个矩形的编码类型结合使用。
  接下来使用CopyRect 编码方式发送相同的式样。
   

二维行程编码( rise-and-run-length,RRE)

  RRE表示提升和运行长度,正如它名字暗示的那样,它实质上表示二维向量的运行长度编码。RRE把矩形编码成可以被客户机的图形引擎翻译的格式。RRE不适合复杂的桌面,但在一些情况下比较有用。
  RRE的思想就是把像素矩形的数据分成一些子区域,和一些压缩原始区域的单元。最近最佳的分区方式一般是比较容易计算的。
  编码是由像素值组成的,Vb(基本上是在矩形中最常用的像素值)和一个计数N,紧接着是N的子矩形列表,这些里面由数组组成,(x,y)是对应子矩形的坐标,表示子矩形上-左的坐标值,(w,h) 则表示子矩形的宽高。客户端可以通过绘制使用背景像素数据值,然后再根据子矩形来绘制原始矩形。
  二维行程编码本质上是对行程编码的一个二维模拟,而其压缩度可以保证与行程编码相同甚至更好。而且更重要的是,采用RRE编码的矩形被传送到客户端以后,可以立即有效地被最简单的图形引擎所还原。
在传输中,数据以下面的头开始描述:
   

后面跟随重复的子矩形结构:
   

CoRRE 编码

  CoRRE是RRE的变体,它把发送的最大矩形限制在255×255个像素以内,用一个字节就能表示子矩形的维度。如果服务器想要发送一个超出限制的矩形,则只要把它划分成几个更小的RFB矩形即可。“对于通常的桌面,这样的方式具有比RRE更好的压缩度”。
  实际上,如果进一步限制矩形的大小,就能够获得最好的压缩度。“矩形的最大值越小,决策的尺度就越好”。但是,如果把矩形的最大值限制得太小,就增加了矩形的数量,而由于每个RFB矩形都会有一定的开销,结果反而会使压缩度变差。所以应该选择一个比较恰当的数字。在目前的实现中,采用的最大值为48×48。

Hextile 编码

  Hextile 是RRE编码的变种,矩形被分割成16×16
小片,允许每个小片的维数为4位,总共16 位。把原始矩形划分成小块是预定义的,这意味着每个块的位置与大小不需要明确地指定。
  矩形被分割的小片从上开始,遵守自左到右,自顶向下的顺序。小片的编码内容按照预定的顺序进行编码。如果整个矩形的宽度不是16 的整数倍,那么每行最后的小片也相应减少。高度也类似。
  每个小片可以使用raw 编码,也可以是RRE编码的变种,用一个类型字节来进行说明即可。每个小片有一个背景像素值。但是,如果小片的背景像素值和前一个小片相同,那么就不需要明确定义。如果小片的子矩形有相同的像素值,那么前景像素值就可以只定义一次。和背景像素值一样,前景像素值也可以通过前一个小片获得。因此由小片组成的数据是按照顺序进行编码的。每一个小片以子编码类型的字节开始。它是位数的掩码组成。
   

  如果Raw 位被设置,那么其余的位就无效;接着是宽X高像素值(宽和高是小片的宽高)。否则其他的位就有效。
  背景定义-如果设置,那么像素值就会跟着小片的背景色:
   

  在矩形中的第一片非Raw 小片必须设置这一位,如果不设置,那么它的背景就会和上一片相同。

  前景定义-如果设置,那么像素值就会定义小片中所有子矩形的前景色。
  

  如果这一位被设置,那么子矩形着色位必须为0。
  任意子矩形-如果设置,那么一个字节包含着子矩形的个数。
   

  如果这一位不设置,那么就不会有子矩形。(例如,整个小片就是背景颜色)

  子矩形着色-如果设置,那么任意子矩形的像素值的优先级都高于子矩形的颜色定义,因此子矩形是:
   

  如果不设置,所有子矩形都是前景色的颜色,如果前景定义没有设置,那么前景色和前一个片的相同。子矩形就是:
 
  

  每一个子矩形的位置和大小都是使用两位进行定义,x - and - y - position 和width -And - height。最重要的四位x - an d - y - posi tion 定义X的位置,不重要的定义Y位置。最重要的四位width - and - height 定义宽度- 1,不重要的定义高度- 1。

ZRLE 编码

  ZRLE(Zlib Run - Length Encoding),它结合了zlib 压缩,片技术、调色板和运行长度编码。在传输中,矩形以4 字节长度区域开始,紧接着是zlib 压缩的数据,一个单一的zlib“流”对象被用在RFB协议的连接上,因此ZRLE矩形必须严格的按照顺序进行编码和译码。
   

  zlibData 在没有压缩之前,代表了由64x64 像素组成的从左到右,从高到低的顺序的片,和hextile 编码有点类似。如果整个矩形的宽度不是64 的整数倍,那么每行最后的小片也相应减少。高度也类似。
ZRLE编码利用了一种新的压缩像素CPIXEL(Compres se d PIXEL)。这个和PIXEL有着相同的像素格式,除了真彩标志是非零,位每像素是32,色深不大于24。所有的位组成红,绿和蓝的亮度填充最不重要的或最重要的三字节。如果CPIXEL只有3 字节长,并且包含有合适的最不重要或最重要3 字节。那么bytesPerCPixel 就是CPIXEL的字节数。每片都是以子编码类型字节开始,如果片被使用运行长度编码,那么本字节的最高位
就会被设置。其余7 位表示绘图样式-零表示没有样式,1 表示片为单色,2 - 127 表示对应的样式。可能的子编码值如下:
0 - Raw 像素数据 宽X高像素值(宽和高为对应片的宽和高,对应像素值如下:

2 - 16 -打包的样式类型。对应像素值是由palet teSize(=子编码)像素值,打包像素值组成,每个打包像素值表示为一位区域服从样式索引(0 表示第一个条目),对应palet teSize 2,1 位被使用,palet teSize 3,4 有两位被使用,从5 - 16 均有4 位区域被使用。位的区域被打包成字节,最重要的位表示最左边像素。因为片并不是8,4,2 像素宽的乘积,所以填充位被用来按照字节数排列每一个行。


 

  m 表示打包像素的字节数。对于palet teSize 2 就是floor((width + 7) / 8) x height,相应3,4 就是floor((width + 3) / 4) x height,而5 - 16 就是floor((width + 1) / 2)xheight。
  17 - 127 未使用(对于palet te
RLE并没有什么优势)。128 -简单RLE 它由一些不断重复的执行组成,一直到片结束。执行可能从一行的结束到另一行的开始。每一次运行是通过一个像素值和像素值长度来表示的。长度一般为1 个或多个字节。经过计算多于所有字节总和+ 1 作为长度。除了255 任何字节值都隐含最后的字节。例如长度1 表示为[0],255 表示为[254],256 表示为[255,0],257 表示为[255,1],510 表示为[255,254],511 表示为[255,255,0]等等。
   

129 -未使用
130 - 255 调色RLE。调色紧跟其后,由palet
teSize = (subencoding - 128) 像素值组成:
   

接下来就合简单RLE相似,一些不断重复的执行组成,一直到片结束。执行长度通过
调色板索引来表示。
   

如果执行长度使用多于一位来表示调色板索引,并且最高位被设置。那么就会带有执行长度。

  

8.4.6      
伪编码

  • 指针/鼠标伪编码

  如果客户端请求指针/鼠标伪编码,那么就是说它有能力进行本地绘制鼠标。这样就可以明显改善传输性能。服务器通过发送带有伪鼠标编码的伪矩形来设置鼠标的形状作为更新的一部分。伪矩形的x 和y 表示鼠标的热点,宽和高表示用像素来表示鼠标的宽和高。包含宽X高像素值的数据带有位掩码。位掩码是由从左到右,从上到下的扫描线组成,而每一扫描线被填充为floor((width +7) / 8)。对应每一字节最重要的位表示最左边像素,对应1 位表示相应指针的像素是正确的。
   

  • 桌面大小伪编码

  如果客户端请求桌面大小伪编码,那么就是说它能处理帧缓存宽/高的改变。服务器通过发送带有桌面大小伪编码的伪矩形作为上一个矩形来完成一次更新。伪矩形的x 和y 被忽略,而宽和高表示帧缓存新的宽和高。没有其他的数据与伪矩形有关。

九、  
协议漏洞及解决方法

  RealVNC VNC Server采用的RFB(远程帧缓冲区)协议允许客户端与服务端协商合适的认证方法,协议的实现上存在设计错误,远程攻击者可以绕过认证无需口令实现对服务器的访问。
具体操作细节如下

1) 服务端发送其版本“RFB 003.008\n”
2) 客户端回复其版本“RFB 003.008\n”
3) 服务端发送1个字节,等于所提供安全类型的数量
3a) 服务端发送字节数组说明所提供的安全类型
4) 客户端回复1个字节,从3a的数组中选择安全类型
5) 如果需要的话执行握手,然后是服务端的“0000”

  RealVNC 4.1.1或之前版本在实现RFB 003.008协议时没有检查判断在上面第4步中客户端所发送的字节是否为服务器在3a步中所提供的,因此认证就从服务端转移到了客户端。攻击者可以强制客户端请求“Type 1 - None”为安全类型,无需口令字段便可以访问服务器。
  危害:远程攻击者可以绕过认证无需口令实现对服务器的访问。
  解决方法:检查客户端请求的安全类型是否为服务器支持的类型之一,否则断开连接,或者禁止无认证的安全类型

(二)RFB协议具体通信说明的更多相关文章

  1. WebSocket原理与实践(二)---WebSocket协议

    WebSocket原理与实践(二)---WebSocket协议 WebSocket协议是为了解决web即时应用中服务器与客户端浏览器全双工通信问题而设计的.协议定义ws和wss协议,分别为普通请求和基 ...

  2. Android之基于HTTP协议的通信详解

    Android系统中本身是有下载机制的,比如浏览器使用的DownloadManager.可遗憾的是,DownloadManager只提供给浏览器使用,一般的应用程序没法调用它. 另外,如果下载调用频繁 ...

  3. HslCommunication库的二次协议扩展,适配第三方通讯协议开发,基础框架支持长短连接模式

    本文将使用一个gitHub开源的项目来扩展实现二次协议的开发,该项目已经搭建好了基础层架构,并实现了三菱,西门子,欧姆龙,MODBUS-TCP的通讯示例,也可以参照这些示例开发其他的通讯协议,并Pul ...

  4. python中基于tcp协议的通信(数据传输)

    tcp协议:流式协议(以数据流的形式通信传输).安全协议(收发信息都需收到确认信息才能完成收发,是一种双向通道的通信) tcp协议在OSI七层协议中属于传输层,它上承用户层的数据收发,下启网络层.数据 ...

  5. (一)RFB协议概述

    (文章是基于刚刚做过的一个项目,对相关知识点进行总结回顾.主要内容均是对之前收集资料的总结概括,很多内容转载自其它地方.因为时间比较长,没有一一记录转载地址,特此感谢!) 一.简介 RFB(远程帧缓冲 ...

  6. 利用Netty构建自定义协议的通信

    在复杂的网络世界中,各种应用之间通信需要依赖各种各样的协议,比如:HTTP,Telnet,FTP,SMTP等等. 在开发过程中,有时候我们需要构建一些适应自己业务的应用层协议,Netty作为一个非常优 ...

  7. JAVA基础知识之网络编程——-基于UDP协议的通信例子

    UDP是一种不可靠的协议,它在通信两端各建立一个socket,这两个socket不会建立持久的通信连接,只会单方面向对方发送数据,不检查发送结果. java中基于UDP协议的通信使用DatagramS ...

  8. iOS-----使用CFNetwork实现TCP协议的通信

    使用CFNetwork实现TCP协议的通信 TCP/IP通信协议是一种可靠的网络协议,它在通信的两端各建立一个通信接口,从而在通信的两端之间形成网络虚拟链路.一旦建立了虚拟的网络链路,两端的程序就可以 ...

  9. 事件驱动的TCP协议Socket通信

    事件驱动的TCP协议Socket通信 介绍 常规的Socket通信案例一般都是在某个线程中建立连接,然后用一个while(true)循环判断是或否有数据传输,但是这种方法有局限性. 1.收到消息在处理 ...

随机推荐

  1. 10.Redis 主从架构

    作者:中华石杉 Redis 主从架构 单机的 redis,能够承载的 QPS 大概就在上万到几万不等.对于缓存来说,一般都是用来支撑读高并发的.因此架构做成主从(master-slave)架构,一主多 ...

  2. Linux 初识Libevent网络库

    初识Libevent libevent是用c写的高并发网络io库,只要有文件描述符,就都可使用libevent. libevent使用回调函数(callback) . 有了libevent,网络编程我 ...

  3. [PHP] 项目实践中的自动加载实现

    1.使用spl_autoload_register函数注册一个自己定义的自动加载函数2.当在代码中new一个不存在的类的时候,上面的函数会被调用,不存在的类名会被作为参数传入该函数中3.兼容了两种方式 ...

  4. rhel7学习第一天

    今天是在线学习刘遄老师<Linux就该这么学>的第一天,对Linux的发展和优越性有了进一步的了解.

  5. Python语言基础07-面向对象编程基础

    本文收录在Python从入门到精通系列文章系列 1. 了解面对对象编程 活在当下的程序员应该都听过"面向对象编程"一词,也经常有人问能不能用一句话解释下什么是"面向对象编 ...

  6. 关于Apache本地能访问外网不能访问的问题

    title: 关于Apache本地能访问外网不能访问的问题 date: 2018-08-05 19:22:12 tags: web --- 在配置apache和tomcat时,把它们都配置好,放到服务 ...

  7. CMS垃圾收集器深入详解

    上一次[https://www.cnblogs.com/webor2006/p/11048407.html]对安全点和安全区进行了理论化的了解,接下来继续对CMS进行其它理论的了解,还是纯理论!!坚持 ...

  8. uiautomator手动调试与快速高度设置

    创建java工程:Demo1包名:com.bing.cn类名:Test测试用例:testDemo android create uitest-project -n Demo1 -t 7 -p E:\e ...

  9. maven介绍(一)

    一.什么是maven Maven 翻译过来就是专家,其官网为: http://maven.apache.org/ Maven使用POM (Project Object Model)项目对象模型,就是通 ...

  10. Netty4的介绍(一)

    Netty是由JBOSS提供给的一个java开源框架.Netty提供异步的.事件驱动的网络应用框架和工具,用以快速开发高性能.高可靠的网络服务器和客户端程序. 也就是说,Netty是一个基于NIO的客 ...