<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Ryan&#39;s Blog - 个人工作日志</title>
    <link>https://www.crs811.com/</link>
    <description>Recent content on Ryan&#39;s Blog - 个人工作日志</description>
    <generator>Hugo -- gohugo.io</generator>
    <language>en-us</language>
    <copyright>Copyright © 2008–2018, Steve Francia and the Hugo Authors; all rights reserved.</copyright>
    <lastBuildDate>Mon, 01 Jun 2026 08:31:26 +0000</lastBuildDate><atom:link href="https://www.crs811.com/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>Rocky Linux 9 系统管理命令合辑</title>
      <link>https://www.crs811.com/archives/2208/</link>
      <pubDate>Mon, 01 Jun 2026 08:31:26 +0000</pubDate>
      
      <guid>https://www.crs811.com/archives/2208/</guid>
      <description>
        
          
            系统基础命令 系统信息查看 1# 查看系统版本 2cat /etc/redhat-release 3hostnamectl 4 5# 查看内核版本 6uname -a 7 8# 查看CPU信息 9lscpu 10 11# 查看内存信息 12free -h 进程与网络 1# 查看网络监听端口（推荐使用 ss 替代 netstat） 2ss -tuln # 查看所有监听端口 3ss -tulnp # 查看监听端口及对应进程 4 5# 查看后台进程 6ps aux | grep [进程名] 7ps -ef | grep [进程名] 8 9# 查看进程树 10pstree -p 文件查找 1# 全盘查找文件 2find / -type f -name &amp;#34;[文件名]&amp;#34; 3 4# 在指定目录中按内容查找（如 /etc） 5grep -r &amp;#34;content&amp;#34; /etc/ 2&amp;gt;/dev/null 6 7# 使用 find + xargs 组合 8find /etc -type f -print0 | xargs -0 grep &amp;#34;content&amp;#34; 9 10# 查找大文件（大于100M） 11find / -type f -size +100M -exec ls -lh {} \; 关机与重启 1# ========== systemctl 方式 ========== 2systemctl reboot # 重启 3systemctl poweroff # 关机（切断电源） 4systemctl halt # 停机（不切断电源） 5 6# ========== shutdown 方式 ========== 7shutdown -h now # 立即关机 8shutdown -h +2 # 2分钟后关机 9shutdown -h 10:01 # 10:01关机 10shutdown -r now # 立即重启 11shutdown -r +2 # 2分钟后重启 12shutdown -c # 取消已计划的关机/重启 13 14# ========== init 方式（传统SysV风格，兼容） ========== 15init 0 # 关机（运行级别0） 16init 6 # 重启（运行级别6） 17init 1 # 单用户模式 18init 3 # 多用户命令行模式 19init 5 # 图形界面模式 20 21# ========== 其他快捷命令 ========== 22reboot # 重启（通用） 23halt # 停机（不切断电源） 24poweroff # 关机（切断电源） 25 26# ========== 查看当前运行级别 ========== 27runlevel # 显示 当前级别 和 上次级别 28who -r # 查看当前运行级别 29systemctl get-default # 查看默认启动目标 网络与主机名 1# 临时禁ping 2echo 1 &amp;gt; /proc/sys/net/ipv4/icmp_echo_ignore_all 3 4# 临时启用ping 5echo 0 &amp;gt; /proc/sys/net/ipv4/icmp_echo_ignore_all 6 7# 释放并重新获取IP（需安装 dhcp-client） 8dnf install -y dhcp-client 9dhclient -r # 释放IP 10dhclient # 重新获取IP 11 12# 设置主机名 13hostnamectl set-hostname [新主机名] systemctl 服务管理 1# 服务启动/停止/重启/状态 2systemctl start [服务名] 3systemctl stop [服务名] 4systemctl restart [服务名] 5systemctl status [服务名] 6 7# 示例：管理防火墙 8systemctl start firewalld 9systemctl stop firewalld 10systemctl restart firewalld 11systemctl status firewalld 12 13# 允许/禁止服务开机启动 14systemctl enable [服务名] 15systemctl disable [服务名] 16 17# 查看服务是否开机启动 18systemctl is-enabled [服务名] 19 20# 列出所有正在运行的服务 21systemctl list-units --type=service --state=running 22 23# 列出所有已安装服务的开机自启状态 24systemctl list-unit-files | grep enabled 25 26# 查看所有服务（含未运行的） 27systemctl list-unit-files --type=service 系统运行级别（目标）设置 Rocky Linux 9 使用 systemd 目标替代传统的运行级别。
          
          
        
      </description>
    </item>
    
    <item>
      <title>Ubuntu 20.04 升级 GCC11, G&#43;&#43;11</title>
      <link>https://www.crs811.com/archives/2207/</link>
      <pubDate>Mon, 03 Nov 2025 11:18:43 +0800</pubDate>
      
      <guid>https://www.crs811.com/archives/2207/</guid>
      <description>
        
          
            1. 更新安装源 直接使用：
1sudo apt-get install gcc-11 安装高版本的gcc11，会有提示：
1Unable to locate package gcc-11 需要添加 PPA 安装源：
1sudo add-apt-repository ppa:ubuntu-toolchain-r/test 但默认的 PPA 下载很慢，可以更新成国内的下载源，编辑以下文件
1cd /etc/apt/sources.list.d 2vim ubuntu-toolchain-r-ubuntu-test-focal.list 将其中的 http://ppa.launchpad.net 替换为 http://launchpad.proxy.ustclug.org
修改后内容如下：
1deb https://launchpad.proxy.ustclug.org/ubuntu-toolchain-r/test/ubuntu focal main 2. 安装 GCC11, G++11 更新软件包并安装
1sudo apt update 2sudo apt install gcc-11 g++-11 3 4# 查询版本 5gcc --version 6g++ --version 7 8# 设置GCC-11为默认编译器 9sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-11 100 10sudo update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-11 100 3.
          
          
        
      </description>
    </item>
    
    <item>
      <title>NS3 网络模拟器基础</title>
      <link>https://www.crs811.com/archives/2205/</link>
      <pubDate>Wed, 08 Nov 2023 18:19:53 +0800</pubDate>
      
      <guid>https://www.crs811.com/archives/2205/</guid>
      <description>
        
          
            NS3初探 一、简介 NS3是一款离散事件驱动的网络仿真器，主要应用于研究和教育领域，旨在满足学术和教学的需求。NS3项目是一个完全开源的开发工程，于2006年启动。第一个版本发布于2008年6月，目前最新的版本为ns-3.35。NS3适用于Linux和Mac OS操作系统。
NS3和NS2 NS-3并不是NS-2的扩展，而是一个全新的模拟器。 NS-2采用C++和OTcl代码编写，在学习过程中需要学习新的OTcl语言。而NS-3全部采用C++语言编写，并且带有可选择性的Python语言绑定，用户可以选择C++或者Python语言编写脚本代码，使用起来更加灵活。
NS-3并不支持NS-2的API。虽然NS-2中的一些模块已经移植到了NS-3中，但NS-3远没有NS-2完善。在NS-3开发的过程中，NS-3项目组会继续维护NS-2，同时也会研究过渡和整合机制。NS-3并不包含目前所有NS-2的功能，但它具有某些新的特性，如：正确的多网卡处理、IP寻址策略的使用、更详细的802.11模块等等。
二、NS3重要概念 1 节点——Node类 在网络术语中，任何一台连接到网络的计算设备被称为主机，亦称为终端。NS3是一个网络模拟器，而非一个专门的因特网模拟器，为此我们避开术语“主机”，因为这个词太容易让人联想到因特网和及其相关协议。因此，我们选用了一个来源于图论，在其他网络模拟器亦广泛使用的术语：节点。
NS3中基本计算设备被抽象为节点。节点由用C++编写的Node类来描述。Node类提供了用于管理计算设备的各种方法。
可以将节点设想为一台可以添加各种功能的计算机。为了使一台计算机有效地工作，我们可以给它添加应用程序，协议栈，外设卡及驱动程序等。NS3采用了与此相同的模型。
2 信道——Channel类 在现实世界中，人们可以把计算机连接到网络上。通常我们把网络中数据流流过的媒介称为信道。当把以太网线插入到墙壁上的插孔时，你正通过信道将计算机与以太网连接。
在NS3中，可以把节点连接到代表数据交换信道的对象上。在这里，基本的通信子网这一抽象概念被称为信道，用C++编写的Channel类来描述。
Channel类提供了管理通信子网对象和把节点连接至信道的各种方法。信道类同样可以由开发者以面向对象的方法自定义。一个信道实例可以模拟一条简单的线缆（wire），也可以模拟一个复杂的巨型以太网交换机，甚至无线网络中充满障碍物的三维空间。
有几个重要的信道模型的实例，包括：
CsmaChannel（CsmaChannel信道模拟了用于一个可以实现载波侦听多路访问的信道，这个信道具有和以太网相似的功能。） PointToPointChannel（P2P信道，即点对点信道） WifiChannel（Wifi信道）。 3 网络设备——NetDevice类 如果想把一台计算机连接到网络上，必须在计算机上安装有网卡。一张网卡如果缺少控制硬件的软件驱动是不能工作的。在Unix/Linux系统中，外围硬件被划为“设备”。设备通过驱动程序来控制，而网卡通过网卡驱动程序来控制。在Unix/Linux系统中，网卡被称为像eth0这样的名字。
在NS3中，网络设备这一抽象概念相当于硬件设备和软件驱动的总和。NS3仿真环境中，网络设备相当于安装在节点上，使得节点通过信道和其他节点通信。像真实的计算机一样，一个节点可以通过多个网络设备同时连接到多条信道上。
网络设备由用C++编写的NetDevice类来描述。NetDevice类提供了管理连接其他节点和信道对象的各种方法，并且允许开发者以面向对象的方法来自定义。
有几个特定的网络设备的实例，它们分别是CsmaNetDevice,PointToPointNetDevice, 和WifiNetDevice。
正如以太网卡被设计成在以太网中工作一样，CsmaNetDevice被设计成在csma信道中工作，而PointToPointNetDevice在PointToPoint信道中工作，WifiNetNevice在wifi信道中工作。
4 应用程序——Application类 计算机软件通常可分为两大类：系统软件和应用软件。系统软件根据计算模型配置，并管理计算机中的各种资源，如内存，处理器周期，硬盘，网络等。系统软件通常并不直接使用这些资源来完成用户任务。用户往往需要运行应用程序来完成一些特定的任务，而应用程序需要使用由系统软件控制的资源。
通常，系统软件和应用软件的界线表现为特权级别的变化，而这种变化是通过操作系统的自陷功能（operating systemtraps）来实现的。在NS3中并没有真正的操作系统的概念，更没有特权级别或者系统调用的概念。然而，我们有应用程序的概念。正如“现实世界”中在计算机上运行应用程序以执行各种任务一样，NS3仿真环境中的应用程序在节点上运行来驱动模拟过程。
在NS3中，需要被仿真的用户程序被抽象为应用。用Application类来描述。这个类提供了管理仿真过程中用户层应用的各种方法。开发者应当用面向对象的方法自定义和创建新的应用。
经常使用有Application类的两个实例：UdpEchoClientApplication和UdpEchoServerApplication。这些应用程序包含了一个client应用和一个server应用来发送和回应仿真网络中的数据包。
5 拓扑帮助-topology helper 实际网络中有具有添加（或内置）NIC的主机。 在NS3中，则称为有带有NetDevices的节点。 在大型模拟网络中，您需要在节点，NetDevices和Channels之间安排许多连接。
由于将NetDevices连接到节点，NetDevices到通道，分配IP地址等是ns-3中的常见任务，因此我们提供了拓扑辅助工具，以使其尽可能简单。
例如，可能需要许多不同的ns-3核心操作来创建NetDevice，添加MAC地址，在节点上安装该网络设备，配置节点的协议栈，然后将NetDevice连接到Channel。 将多个设备连接到多点通道然后将各个网络连接到互联网络中将需要更多操作。 我们提供拓扑辅助对象，将这些许多不同的操作组合成一个易于使用的模型，以方便您使用。
6 节点容器–NodeContainer 一个节点Node代表了一台计算机，我们将添加协议栈，应用程序和外围卡等内容。 NodeContainer拓扑助手提供了一种方便的方法来创建，管理和访问我们创建的任何Node对象，以便运行模拟。
7 设备容器–NetDeviceContainer 正如使用NodeContainer拓扑辅助对象为模拟创建节点一样，我们将要求PointToPointHelper完成创建，配置和安装设备所涉及的工作。 我们需要有一个创建的所有NetDevice对象的列表，所以使用NetDeviceContainer来保存它们就像使用NodeContainer来保存创建的节点一样。
三、分析例子程序first.cc的源代码 1.文件开头定义
1#include &amp;#34;ns3/core-module.h&amp;#34; //内核模块 2#include &amp;#34;ns3/network-module.h&amp;#34; 3#include &amp;#34;ns3/internet-module.h&amp;#34; 4#include &amp;#34;ns3/point-to-point-module.h&amp;#34; //p2p模块 5#include &amp;#34;ns3/applications-module.h&amp;#34; //应用程序 6 7using namespace ns3; 8/*命名空间，NS3工程是在一个叫做ns3的C++命名空间中实现的。这把所有与ns3相关的声明，集中在一个与全局命名空间相区别的命名空间中。 9我们希望这样会给ns3与其他代码的集成带来好处。C++用“using”语句用来把ns-3namespace引入到当前的（全局的）作用域中。 10这个声明就是说，你不用为了使用ns-3的代码而必须在所有的ns-3代码前打上ns3::作用域操作符。*/ 11 12NS_LOG_COMPONENT_DEFINE (&amp;#34;FirstScriptExample&amp;#34;); 13/*声明一个叫&amp;#34;FirstScriptExample&amp;#34;的日志组件，通过引用FirstScriptExample这个名字的操作， 14可以实现打开或者关闭控制台日志的输出。*/ 2.
          
          
        
      </description>
    </item>
    
    <item>
      <title>Hugo 静态网站搭建</title>
      <link>https://www.crs811.com/archives/2204/</link>
      <pubDate>Sat, 31 Dec 2022 18:19:30 +0800</pubDate>
      
      <guid>https://www.crs811.com/archives/2204/</guid>
      <description>
        
          
            建站流程 (Linux) 1. 下载安装Hugo Hugo 官网： https://gohugo.io/
Hugo Git 网址：https://github.com/gohugoio/hugo/releases
1wget https://github.com/gohugoio/hugo/releases/download/v0.109.0/hugo_0.109.0_Linux-64bit.tar.gz 2mkdir /usr/local/hugo 3tar -xf hugo_0.109.0_Linux-64bit.tar.gz -C /usr/local/hugo 设置环境变量:
1vim /etc/profile 在　export PATH　行的上方添加：
1PATH=$PATH:/usr/local/hugo 命令行中验证：
1source /etc/profile #让配置生效 2hugo version 2. 创建网站 1mkdir /www/server/hugo 2cd /www/server/hugo 3hugo new site mywebsite 4cd mywebsite 3. 选择主题 选择并下载一个主题
1#所有主题： https://themes.gohugo.io/ 2git clone https://github.com/chipzoller/hugo-clarity themes/hugo-clarity #以clarity主题为例 4. 复制示例配置 将 hugo-clarity 下 exampleSite 的内容全部复制到 /www/server/hugo/mywebsite 下，这样可以利用示例网站的很多设置和样式
1cp themes/hugo-clarity/exampleSite/* /www/server/hugo/mywebsite -r 5. 修改域名 修改域名 example.
          
          
        
      </description>
    </item>
    
    <item>
      <title>Android 2025.2.3 开发环境搭建</title>
      <link>https://www.crs811.com/archives/2203/</link>
      <pubDate>Sun, 07 Aug 2022 07:10:03 +0000</pubDate>
      
      <guid>https://www.crs811.com/archives/2203/</guid>
      <description>
        
          
            准备工作：安装 JDK（&amp;gt;=17） 和配置环境变量 1 下载 Android Studio 下载最新版：
进入Android Studio 下载页 https://developer.android.google.cn/studio； 点击Download Android Studio下载最新版； 下载旧版本：
进入Android Studio 旧版下载页 https://developer.android.google.cn/studio/archive， 点击“同意条款”； 选择一个版本下载； 推荐使用 Android-Studio 2025.2.3 版本
2 安装Android Studio 及配置 &amp;gt;&amp;gt; Android studio 2024 [详细图文安装步骤] &amp;lt;&amp;lt; 2.1 Android Studio 中 Android SDK设置 [推荐] （1）设置Android SDK保存路径
首次启动 Android Studio，默认进入Android Studio Setup Wizard
在其中 Android SDK Location 处，建议重新设置 SDK 的保存位置，推荐保存到 D:\Android\android-sdk
最后Finish，会自动下载相关SDK文件。
（2）设置环境变量 [可选]
新建变量 ANDROID_HOME ，值为 D:\Android\android-sdk
在Path中增加：%ANDROID_HOME%\tools
在Path中增加：%ANDROID_HOME%\platform-tools
（3）检查路径
在 Android Studio 中，点击菜单栏的 File &amp;gt; Settings。
          
          
        
      </description>
    </item>
    
    <item>
      <title>Vue3.x 及相关热门技术</title>
      <link>https://www.crs811.com/archives/2170/</link>
      <pubDate>Wed, 29 Jun 2022 02:34:15 +0000</pubDate>
      
      <guid>https://www.crs811.com/archives/2170/</guid>
      <description>
        
          
            热门技术： yarn vite typescript (ts) pinia tailwind 1、Vue3 新特性： Vue3 新特性 2、Vue3基础： 从vue2到vue3，一文带你看完vue3的新特性
3、Vu3搭建技术变化： npm &amp;gt;&amp;gt; yarn yarn 是由Facebook、Google、Exponent 和 Tilde 联合推出了一个新的 JS 包管理工具，yarn是为了弥补 npm 的一些缺陷而出现的
npm的缺陷：
npm install的时候巨慢，新的项目拉下来要等半天 同一个项目，安装的时候无法保持一致性。由于package.json文件中依赖包版本号的特点，有时会由于安装版本不一致出现bug 安装的时候，包会在同一时间下载和安装，中途某个时候，一个包抛出了一个错误，但是npm会继续下载和安装包。因为npm会把所有的日志输出到终端中，有关错误包的错误信息就会在一大堆npm打印的警告中丢失掉，并且你甚至永远不会注意到实际发生的错误 yarn的优点：
速度快： 并行安装：npm是按照队列执行每一个包，也就是必须等到当前包安装完成之后才能继续后面的安装。而yarn是并行执行所有任务，提高了性能 离线模式：如果之前已经安装过一个软件包，用yarn再次安装时会从缓存中获取，就不用像npm那样再从网络下载了 安装yarn
npm install -g yarn 查看版本：yarn --version
命令对照
npm yarn npm yarn npm init yarn init npm init -y yarn init -y npm install yarn npm install xxx yarn add xxx npm install --global xxx yarn global add xxx npm uninstall xxx yarn remove xxx npm install xxx@版本号 yarn add xxx@版本号 npm install xxx --save yarn add xxx npm install xxx --save-dev yarn add xxx --dev npm update --save yarn upgrade npm run yarn run npm run xxx yarn run xxx npm run dev yarn dev 运行github 项目如下步骤：
          
          
        
      </description>
    </item>
    
    <item>
      <title>VS Code设置键盘快捷键</title>
      <link>https://www.crs811.com/archives/2168/</link>
      <pubDate>Sat, 25 Jun 2022 02:08:23 +0000</pubDate>
      
      <guid>https://www.crs811.com/archives/2168/</guid>
      <description>
        
          
            左下角：keyboard shortcuts &amp;gt; open keyboard shortcuts
配置：
{ &#34;key&#34;: &#34;ctrl+i&#34;, &#34;command&#34;: &#34;selectPrevSuggestion&#34;, &#34;when&#34;: &#34;editorTextFocus &amp;&amp; suggestWidgetVisible&#34; }, { &#34;key&#34;: &#34;ctrl+k&#34;, &#34;command&#34;: &#34;selectNextSuggestion&#34;, &#34;when&#34;: &#34;editorTextFocus &amp;&amp; suggestWidgetVisible&#34; } 作用：出现代码提示后使用 ctrl+i 和ctrl+k快速上下移动提示项，不用使用上下键 
          
          
        
      </description>
    </item>
    
    <item>
      <title>JS中的逻辑运算符</title>
      <link>https://www.crs811.com/archives/2143/</link>
      <pubDate>Thu, 31 Mar 2022 14:47:51 +0000</pubDate>
      
      <guid>https://www.crs811.com/archives/2143/</guid>
      <description>
        
          
            对于操作数为非boolean类型的数据
&amp;amp;&amp;amp; 或 || 运算前先将其进行隐式类型转换，在进行判断，最终返回原值
1//当操作数为两个时， 2console.log(5&amp;amp;&amp;amp;4+&amp;#34;\n&amp;#34;); // 5隐式转换之后为true，返回4 3console.log(4&amp;amp;&amp;amp;5+&amp;#34;\n&amp;#34;); // 4隐式转换之后为true，返回5 4console.log(&amp;#34;&amp;#34;&amp;amp;&amp;amp;5+&amp;#34;\n&amp;#34;); //空字符串转换之后为false，返回&amp;#34;&amp;#34; 5console.log(null&amp;amp;&amp;amp;5+&amp;#34;\n&amp;#34;); //操作符中存在null，结果就为null 6console.log(4&amp;amp;&amp;amp;undefined+&amp;#34;\n&amp;#34;); //操作符中存在undefined，结果就为null 7console.log(NaN&amp;amp;&amp;amp;5+&amp;#34;\n&amp;#34;); //操作符中存在NaN，结果就为null 8//当操作数为3个及以上时， 9console.log(5&amp;amp;&amp;amp;4&amp;amp;&amp;amp;6+&amp;#34;\n&amp;#34;); //结果为真时，返回最后一个数的原值 6 当操作数为非Boolean类型的时候，&amp;amp;&amp;amp;运算符依旧遵循“短路”运算法则：
以两个操作数为例： （表达式1,表达式2）
1.如果第一个操作数隐式转换为Boolean之后为true，则返回第二个操作数；
2.如果第一个操作数隐式转换为Boolean之后为false，则返回第一个操作数；
3.在&amp;amp;&amp;amp;运算中，但凡操作数中有 null ，undefined ，NaN 这些特殊值，结果就返回这些值。（虽然这些值转换为Boolean之后为false，但返回是将这些值直接输出）
1//当操作数为两个时， 2console.log(5||4+&amp;#34;\n&amp;#34;); // 5隐式转换之后为true，返回5 3console.log(4||5+&amp;#34;\n&amp;#34;); // 4隐式转换之后为true，返回4 4console.log(&amp;#34;&amp;#34;||5+&amp;#34;\n&amp;#34;); //空字符串转换之后为false，返回5 5console.log(null||5+&amp;#34;\n&amp;#34;); //null隐式转换之后为false，返回5 6console.log(4||undefined+&amp;#34;\n&amp;#34;); //4隐式转换之后为true，返回4 7console.log(NaN||5+&amp;#34;\n&amp;#34;); // NaN隐式转换之后为false，返回5 8//当操作数为3个及以上时， 9console.log(5||4||6+&amp;#34;\n&amp;#34;); //结果为真时，返回第一个数的原值 5 以两个操作数为例： （表达式1,表达式2）
1.如果第一个操作数隐式转换为Boolean之后为true，则返回第一个操作数；
2.如果第一个操作数隐式转换为Boolean之后为false，则返回第二个操作数；
3.需要注意的是：||运算符不对 null, undefined, NaN 有特殊要求，而是将他们隐式转换为 false。
!非运算符（非真即假）
对于操作数为非boolean类型的数据
对一个boolean值进行取反操作，即：!true=false !fasle=true
对于操作数为非boolean类型的数据
首先将其转换为Boolean，在进行双取反（两次非运算操作）
          
          
        
      </description>
    </item>
    
    <item>
      <title>Vue2.js 重要知识点一览</title>
      <link>https://www.crs811.com/archives/2088/</link>
      <pubDate>Tue, 29 Jun 2021 04:40:15 +0000</pubDate>
      
      <guid>https://www.crs811.com/archives/2088/</guid>
      <description>
        
          
            1.从 JQuery 库到Vue.js 框架 从 操作DOM 的思维模式切换到 以数据为主
2.安装 1$ npm install --global vue-cli # 全局安装 vue-cli 2$ vue init webpack my-project # 创建一个基于 webpack 模板的新项目 3$ cd my-project 4$ npm install # 安装依赖 加速：--registry https://registry.npm.taobao.org 5$ npm run dev # 运行项目 3.基本指令 1、双花括号 mustache(模板引擎)/interpolation（插值表达式）
语法：
1&amp;lt;any&amp;gt;{{表达式}}&amp;lt;/any&amp;gt; 作用： 将表达式执行的结果 输出当调用元素的innerHTML中；还可以将数据绑定到视图
2、指令-循环指令 基本语法1：
1&amp;lt;any v-for=&amp;#34;tmp in array&amp;#34;&amp;gt;&amp;lt;/any&amp;gt; 基本语法2：
1&amp;lt;any v-for=&amp;#34;(value,index) in array&amp;#34;&amp;gt;&amp;lt;/any&amp;gt; 作用： 在遍历array这个集合时，将临时变量保存在tmp中，创建多个any标签
3、指令-选择指令 语法：
1&amp;lt;any v-if=&amp;#34;表达式&amp;#34;&amp;gt;&amp;lt;/any&amp;gt; 2&amp;lt;any v-else-if=&amp;#34;表达式&amp;#34;&amp;gt;&amp;lt;/any&amp;gt; 3&amp;lt;any v-else=&amp;#34;表达式&amp;#34;&amp;gt;&amp;lt;/any&amp;gt; 作用： 根据表达式执行结果的真假，来决定是否要将当前的这个元素 挂载到DOM树
          
          
        
      </description>
    </item>
    
    <item>
      <title>hp1020 简单实用的 双面打印 方法</title>
      <link>https://www.crs811.com/archives/2150/</link>
      <pubDate>Sun, 09 May 2021 03:09:13 +0000</pubDate>
      
      <guid>https://www.crs811.com/archives/2150/</guid>
      <description>
        
          
            基本原理：
首先按奇数页正序打印，将打印出来的纸张翻转过来，再按偶数页逆序打印。
若文档为奇数页，则翻转前先取出最上面的一张。
1. word 转pdf
Adobe Acrobat 或其他阅读器中打开 pdf
2. 若文档为奇数页，则将打印出来的纸上面的最上面一张取出，若为偶数页则不管。
【纵向打印】将纸张一起翻转送入进纸口：打印出来的纸张会是这个方向：
要这样重新放入打印机：
3. 设置
原文链接：[小白笔记]hp1020双面打印方法 - 简书 (jianshu.com)
          
          
        
      </description>
    </item>
    
    <item>
      <title>word 文献编号自动更新与批量上标替换</title>
      <link>https://www.crs811.com/archives/2066/</link>
      <pubDate>Tue, 04 May 2021 00:53:20 +0000</pubDate>
      
      <guid>https://www.crs811.com/archives/2066/</guid>
      <description>
        
          
            office版本：安装 office 2010 以上版本
word 文献编号自动更新方法： 1、添加新的自动编号格式 =&amp;gt; 样式选择：[1]
2、到 百度学术 搜索文献批量导出成txt文件
3、把文献添加到word文档中，利用刚才添加的自动编号格式为这些文献编号，删除导出时指定的编号
4、在需要引用的地方，选择 菜单》插入》交叉引用，选择准备插入的文献，勾选 插入为超链接，即可插入该文献的链接进文档
5、如果需要更新参考文献，先在参考文献列表中增加或删除相关文献，接着选择需要更新的文档内容（即选中 [1]），在[1]上点击 右键》更新域，则链接过来的编号会自动更新
批量上标替换 利用word查找与替换中的的通符符功能可以实现：
查找内容：[[0-9]{1,2}] 即匹配数字 0-9，重复1到2次
替换为：下方 查找 》格式 》字体 》上标
勾选：使用通配符
不要使用全部替换功能，要挨个看清楚再替换
          
          
        
      </description>
    </item>
    
    <item>
      <title>前端学习资料汇总</title>
      <link>https://www.crs811.com/archives/1825/</link>
      <pubDate>Sat, 20 Feb 2021 03:01:52 +0000</pubDate>
      
      <guid>https://www.crs811.com/archives/1825/</guid>
      <description>
        
          
            一、软件： 1、VSCode (前端学习) ，下载地址：
https://code.visualstudio.com/
VSCode 常用插件列表：
https://www.crs811.com/archives/1823
VSCode 插件安装方法
https://jingyan.baidu.com/article/90808022029213fd91c80f15.html
微信小程序开发工具（《微信小程序开发实战》课程），下载地址：
https://developers.weixin.qq.com/miniprogram/dev/devtools/download.html
二、基础知识： HTML 基础
http://www.divcss5.com/html/h50900.shtml 快速入门
https://www.runoob.com/html/html-tutorial.html 内容全面
css 基础
https://blog.csdn.net/sheqianweilong/article/details/89483318 快速入门
https://www.runoob.com/css/css-tutorial.html CSS
https://www.runoob.com/css3/css3-tutorial.html CSS3
js 基础
https://blog.csdn.net/yurenning/article/details/79523027 快速入门
https://www.runoob.com/js/js-tutorial.html 内容全面 ES5 标准
https://es6.ruanyifeng.com/ 阮一峰 ES6 教程
https://www.runoob.com/w3cnote/es6-tutorial.html 菜鸟 ES6 教程
https://www.crs811.com/archives/1905 ES6编码规范
jQuery 基础
https://www.runoob.com/jquery/jquery-tutorial.html 内容全面
Node.js 教程
https://www.runoob.com/nodejs/nodejs-tutorial.html
三、Vue.js框架教程： VueJs2.0建议学习路线
https://www.crs811.com/archives/1286
VueJs2.0 菜鸟教程
https://www.runoob.com/vue2/vue-tutorial.html
B站视频教程：4个小时带你快速入门vue
https://www.bilibili.com/video/BV12J411m7MG?p=1
Vuex白话教程
https://www.jianshu.com/p/120eaf50331c
          
          
        
      </description>
    </item>
    
    <item>
      <title>ES6 编码规范</title>
      <link>https://www.crs811.com/archives/1905/</link>
      <pubDate>Tue, 16 Feb 2021 03:52:29 +0000</pubDate>
      
      <guid>https://www.crs811.com/archives/1905/</guid>
      <description>
        
          
            原文: https://github.com/yuche/javascript
目录 类型 引用 对象 数组 解构 字符串 函数 箭头函数 构造函数 模块 迭代器和生成器 属性 变量 提升 比较运算符和等号 代码块 注释 空白 逗号 分号 类型转换 命名规则 存取器 事件 jQuery ECMAScript 5 兼容性 ECMAScript 6 编码规范 测试 性能 相关资源 使用情况 其他翻译 JavaScript 编码规范说明 讨论 JavaScript 贡献者 许可协议 类型 1.1 基本类型: 直接存取基本类型。
字符串 数值 布尔类型 null undefined 1const foo = 1; 2let bar = foo; 3 4bar = 9; 5 6console.log(foo, bar); // =&amp;gt; 1, 9 1.
          
          
        
      </description>
    </item>
    
    <item>
      <title>vs code web 前端开发必备插件</title>
      <link>https://www.crs811.com/archives/1823/</link>
      <pubDate>Fri, 12 Feb 2021 14:41:11 +0000</pubDate>
      
      <guid>https://www.crs811.com/archives/1823/</guid>
      <description>
        
          
          
        
      </description>
    </item>
    
    <item>
      <title>由 Java Entity 类自动生成 SQL建表语句</title>
      <link>https://www.crs811.com/archives/2020/</link>
      <pubDate>Fri, 04 Dec 2020 02:37:02 +0000</pubDate>
      
      <guid>https://www.crs811.com/archives/2020/</guid>
      <description>
        
          
            网上下载的项目，有些只有代码，没有对应的数据库和sql语句。
需要自行根据Entity类来生成建表语句：
1package com.xx; 2 3import java.io.File; 4import java.io.FileOutputStream; 5import java.lang.reflect.Field; 6import java.util.ArrayList; 7import java.util.HashMap; 8import java.util.List; 9import java.util.Map; 10 11import org.slf4j.Logger; 12import org.slf4j.LoggerFactory; 13 14 15/** 16 * 根据 java 类自动生成sql 语句 - mysql 17 */ 18public class SqlGenerator { 19 public static Map&amp;lt;String, String&amp;gt; javaProperty2SqlColumnMap = new HashMap&amp;lt;&amp;gt;(); 20 21 static { 22 javaProperty2SqlColumnMap.put(&amp;#34;Integer&amp;#34;, &amp;#34;int&amp;#34;); 23 javaProperty2SqlColumnMap.put(&amp;#34;Short&amp;#34;, &amp;#34;tinyint(4)&amp;#34;); 24 javaProperty2SqlColumnMap.put(&amp;#34;Long&amp;#34;, &amp;#34;bigint&amp;#34;); 25 javaProperty2SqlColumnMap.put(&amp;#34;BigDecimal&amp;#34;, &amp;#34;decimal(19,2)&amp;#34;); 26 javaProperty2SqlColumnMap.put(&amp;#34;Double&amp;#34;, &amp;#34;double precision not null&amp;#34;); 27 javaProperty2SqlColumnMap.
          
          
        
      </description>
    </item>
    
    <item>
      <title>前端学习路线图 – 2020</title>
      <link>https://www.crs811.com/archives/2013/</link>
      <pubDate>Tue, 01 Dec 2020 05:02:50 +0000</pubDate>
      
      <guid>https://www.crs811.com/archives/2013/</guid>
      <description>
        
          
             
          
          
        
      </description>
    </item>
    
    <item>
      <title>vim 8  IDE 开发环境配置</title>
      <link>https://www.crs811.com/archives/1999/</link>
      <pubDate>Mon, 23 Nov 2020 06:49:51 +0000</pubDate>
      
      <guid>https://www.crs811.com/archives/1999/</guid>
      <description>
        
          
            1、升级 vim 到最新版本 ：vim8.2.2028 wget -O vim8.2.2028.zip https://github.com/vim/vim/archive/v8.2.2028.zipunzip vim8.2.2028.zipcd vim-8.2.2028/cd src/mkdir /usr/local/vim8编译vim，支持 python3
./configure --with-features=huge --enable-multibyte --enable-cscope --enable-python3interp=yes --with-python-config-dir=/usr/lib64/python3.6/config-3.6m-x86_64-linux-gnu --prefix=/usr/local/vim8/ --with-python3-command=/usr/bin/python3cp bin/vim /usr/bin/vimcp bin/vim /usr/local/bin/vim2、安装 cmake wget https://github.com/Kitware/CMake/releases/download/v3.19.0/cmake-3.19.0-Linux-x86_64.tar.gz最新版不需要编译，直接可以使用
mv cmake-3.19.0-Linux-x86_64 /usr/local/cmakeecho &#39;export PATH=/usr/local/cmake/bin:$PATH&#39; &gt;&gt; .zshrcsource ~/.zshrc3、安装vimplus git clone https://github.com/chxuan/vimplus.gitcd ./vimplus./install.sh4、配置 .vimrc &#34;===========================================================call plug#begin()&#34; 目录结构展示插件Plug &#39;scrooloose/nerdtree&#39;Plug &#39;Xuyuanp/nerdtree-git-plugin&#39;&#34; 代码自动补全Plug &#39;ycm-core/YouCompleteMe&#39;&#34; 括号自动补全Plug &#39;jiangmiao/auto-pairs&#39;Plug &#39;itchyny/lightline.
          
          
        
      </description>
    </item>
    
    <item>
      <title>随机预言模型（三）【转】</title>
      <link>https://www.crs811.com/archives/1957/</link>
      <pubDate>Wed, 05 Aug 2020 00:58:10 +0000</pubDate>
      
      <guid>https://www.crs811.com/archives/1957/</guid>
      <description>
        
          
            https://www.4hou.com/posts/rMQE
本文翻译自：https://blog.cryptographyengineering.com/2011/10/20/what-is-random-oracle-model-and-why_20/如若转载，请注明原文地址：
快速回顾一下 在前两篇文章中，我们已经讨论了一些内容。 我们讨论了加密哈希函数及其性质，并讨论了为什么密码学家的“理想”哈希函数是一个随机函数。 我们注意到，随机函数在现实生活中永远不会起作用(存储太大，计算太慢) ，因此我们得出了一个奇怪的结论: 我们假装我们的哈希是随机函数，只是为了安全分析的目的。 然后当然我们会使用真正的哈希函数，比如 SHA。
当然，即使是这样，我们也需要改变宇宙的结构，因为我们想要限制我们的“对手”在合理的时间内运行，而如果他们忙于评估随机函数，他们就无法做到这一点。因此，我们创造了一种新的计算模型(又名“思想实验”) ，称为随机预言模型。 在这个模型中，所有的哈希都是由一个叫做预言的神奇的第三方计算出来的。
如果你对随机预言模型有一点了解，比如说在阅读前面的文章时，你可以原谅自己认为它并没有那么糟糕。 基本上，我们假设哈希函数是超级“随机”函数。 可能比一个真正的函数要多一点，但是很重要。
但不幸的是，远不止这些。
这可能是世界上最短的可证明的安全课程 为了解释我的意思，我们首先需要了解一点可证明的安全性，特别是一种叫做约简证明的证明。
当我们说一个加密方案是“可证明的安全”时，我们通常指的是在某种假设下它是安全的。 对于大多数实际的方案来说，这个假设本质上是数学性质的。 例如，我们可以假设很难分解大的复合数，或者很难在格中找到最短的向量，从而找到一个加密方案。 在这种情况下，“难搞”并不意味着“我不知道该怎么做”。它的意思是: 没有(有效的)算法可以做到这一点。1
现在，我提到这些都是假设。 我们并不完全知道这些问题是困难的。 然而，我们倾向于认为，如果一些聪明的人已经注意到这个问题有一段时间了，但是没有人在解决这个问题上取得任何进展，那就意味着这可能并不容易。 在某些情况下，问题甚至可能属于一类有用的问题，例如，它可能是一个 NP-Hard 问题（译者注：NP-hard 请参见百度百科的解释）。
即使你不愿盲目相信这些假设，安全性证据仍然是有用的。 分析一个新的密码系统可以消耗大量的时间和精力。 如果我们至少可以将每个新方案“简化”为少数几个数学问题中的一个，我们就可以倾注我们的脑力来解决这些问题，因为我们知道我们的工作将适用于每个使用这些问题的方案。
所有这些带出了我的主要观点，即，这些证明是如何工作的。 具体来说，这种证明的一般流程如下:
1. 假设问题 X 很难。
2. 证明如果存在一个(有效的)算法来“破坏”我们的加密方案，那么就存在一个(有效的)算法来解决问题X。
3. 含蓄地指出(2)意味着如果方案可以被打破，那么问题X就不会很难。
如果第(1)点为真，那么第(3)点显然不可能为真。 根据这个逻辑，我们可以得出这样的结论: 如果问题 X 很难，那么就不可能有算法破解我们的加密方案。
当然，我还没有解释如何实际完成步骤(2) ，这是非常重要的。 这也是最美妙的部分。 你看，在大多数简化中，步骤(2)实际上包括编写一个解决问题 X 的有效算法。
你可能觉得我疯了。 我刚刚声称 X 问题不能有效地解决，现在我又告诉你们，我们写了一个算法可以解决这个问题。 但它的天才之处在于，我们的求解算法不能很好地工作。 它缺少一个重要的子程序。
这个子例程在 API 级别上与“破解”我们的加密方案的算法是一样的。
因此，这就是争论的症结所在:假设有一种算法有效地“破坏”了我们的加密方案，那么我们可以把它塞进我们的“求解器”算法留下的洞里。这将产生一个有效地解决 X 问题的算法，因此，它完全满足我们在点(2)中所要求的。
黑匣子 有了这个基础，我只需要再说一点。 有一个基本的简化证明必须遵守的限制。 我们的“问题 X 解决程序”算法必须使用“加密方案破坏程序”的子程序作为一个黑盒。它无法对破坏程序算法的内部工作方式做出假设。
          
          
        
      </description>
    </item>
    
    <item>
      <title>随机预言模型（二）【转】</title>
      <link>https://www.crs811.com/archives/1955/</link>
      <pubDate>Wed, 05 Aug 2020 00:55:28 +0000</pubDate>
      
      <guid>https://www.crs811.com/archives/1955/</guid>
      <description>
        
          
            https://www.4hou.com/posts/E6Dv
本文翻译自：https://blog.cryptographyengineering.com/2011/10/08/what-is-random-oracle-model-and-why-2/如若转载，请注明原文地址
这是关于随机预言（Random Oracle）模型系列文章的第二部分。第一篇文章请参见“第一部分: 介绍”。
在之前的那篇文章中，我承诺要解释什么是随机预言模型，更重要的是，为什么你应该关心它。 我想我已经起了一个好的开头，但是我意识到我还没有回答其中的任何一个问题。
相反，我做了很多关于哈希函数的讨论。 我描述了一个理想的哈希函数应该是什么样的，即一个随机函数。 然后我花了大部分时间解释为什么随机函数是完全不切实际的(重述一下: 存储太大，计算太慢)。
最后，我们得出了以下结论: 随机函数当然可以构成很棒的哈希函数，但不幸的是我们不能在现实生活中使用它们。 尽管如此，如果我们不能通过任何其他方式获得安全性证明，那么假设一个哈希函数可以表现得像一个随机函数也许是有用的。 当然，当我们实际部署这个方案时，我们必须使用一个真正的哈希函数，比如 SHA 或 RIPEMD ——绝对不是随机函数——在这种情况下，我们的证明意味着什么还不清楚。
不过，这也不是完全没用。 如果我们能够完成这样一个安全性证明，我们至少可以排除“明显的”攻击(基于真正的方案设计者往往倾向于制造的那种小故障)。 对该方案的任何特定攻击基本上都与哈希函数的属性有关。 这仍然是一个很好的启发式方法。
正如你所看到的，这有点技术性，在文章的末尾会有一点技术性的结论。 如果你已经掌握了足够的背景知识，可以直接跳到本系列的下一篇文章，我将在这篇文章中介绍这个模型的使用(提示：所有现代的 RSA 签名和加密!) 以及它对密码学实践的意义。
实质问题 安全性证明通常考虑两个或多个当事方的交互，其中一方是就是我们的对手。 在一个典型的例子中，大多数玩家都是“诚实的” ，这意味着他们会按照一个明确的安全协议进行操作。 另一方面，对手可以为所欲为。 她的目标是破坏这个计划。
通常我们会详细说明各方将要玩的游戏。 对于加密方案，该游戏规则允许对手做能够在“真实世界”环境中可以做的事情。 例如: 她可能能够获得选择明文的加密和选择密文的解密。 在大多数情况下，她会拦截由一个诚实的加密器传输的合法密文。 通常她的目标是学习(关于)潜在的明文。
标准的做法是假设各方都知道方案或协议，包括如何计算使用的哈希函数。 这是一个常识性的假设，有时也被称为科克霍夫斯原理（Kerckhoffs 原理）。 此外，我们通常假设对手在某些方面是有限的——她没有无限的计算能力或时间，这意味着她不能暴力破解解密的密钥。
随机预言机模型中的安全性证明。 所有参与者(Encryptor、 Decryptor 和对手)都可以调用随机预言，后者为它们计算哈希函数并向所有参与者提供一致的响应。
为什么是预言？ 好吧，因为预言是团体的“外部”，所以它们不再需要携带一个描述的哈希函数，也不需要计算它的工作。 这很好，因为——正如我在前一篇文章中所提到的—— 对一个随机函数的完整描述大得离谱，因此计算时间也长得离谱。 通过把它放入预言模型，我们就可以把这些丑陋的东西抛掉。一个随机预言的安全性证明就是这样的，但是我们做了进一步的调整。 尽管每个人都被允许计算哈希函数，但是他们不能自己完成。 哈希是由一个叫做“预言”的新魔法团体完成的。 如果任何一方需要对某些内容进行哈希操作，他们需要将消息(通过一个虚构的安全通道)发送给预言模型，由 预言模型计算哈希并将其发回给他们。
我们将对随机预言设置两个限制。 首先，它必须实现一个真正的随机函数(在游戏开始时采样) ，具有与我们可能使用的实际哈希函数相同的输入 / 输出配置文件(例如，我们最终要使用 SHA256实现256位输出字符串)。
其次，预言给出的回答必须是一致的。 换句话说，就像通过 SHA1对“Peter Piper”进行哈希一样，总是会产生1c6244929dc8216f5c1024eebefb5cb73c378431 * 这个结果，无论是谁做的，通过随机预言发送给定的字符串都会产生相同的结果，无论哪一方要求它。
建立随机预言模型 关于如何建立随机预言模型，还有最后一个(而且是一种巧妙的)技巧。 在内部，一个随机预言只是实现了一个巨大的表，这个表将输入值映射到随机输出字符串。 既然如此，我们的安全性证明可以“懒惰地”填满这张表。 与其从填满整个表开始分析，不如从一个空表开始分析然后生成它，而不是从整个填满的表开始。它是这样工作的：
          
          
        
      </description>
    </item>
    
    <item>
      <title>随机预言模型（一）【转】</title>
      <link>https://www.crs811.com/archives/1953/</link>
      <pubDate>Wed, 05 Aug 2020 00:52:02 +0000</pubDate>
      
      <guid>https://www.crs811.com/archives/1953/</guid>
      <description>
        
          
            https://www.4hou.com/posts/kO4K
本文翻译自：​https://blog.cryptographyengineering.com/2011/09/29/what-is-random-oracle-model-and-why-3/如若转载，请注明原文地址
碰巧我今天计划教一门关于可证明安全的课程，还有一门叫做“随机预言模型（Random Oracle Model）”的课程。 在整理我的想法的时候，我突然想到: a)这个主题可能会引起那些不是我的研究生的人的兴趣; b)对于这个知识点似乎还没有一个好的给“外行人”学习的介绍文章。 在大多数情况下，我喜欢谈论加密是如何实现的。 但是，如果你从不安全的原语开始，那么实现就无关紧要了。
因此，冒着疏远我那些微不足道的读者群的风险，我打算暂停一下我们定期安排的“密码系统是如何变坏的”编程内容，来谈谈这个学究般的话题——正如我们稍后会看到的，这本身就是密码如何变坏的另一种味道。
傻瓜式哈希函数 在我们讨论随机预言之前，我们首先需要讨论哈希函数。 这些函数接受(可能)长的输入，并将输入经“哈希”处理得到固定大小的值，我们称之为“消息摘要”。
我们在密码学中经常使用哈希函数。 在数字签名方案中，它们的出现受到了极大的关注，但也出现在许多加密方案中。 事实上，在整个球场上，扔一块石头而没有接触到它则是很难的事情。
在大多数情况下，密码哈希函数必须至少满足以下一些属性。 首先，我们希望它是“单向的” ，这意味着很难“颠倒”函数，也就是说，只给出一个消息摘要就可以找到原始消息。
其次，哈希函数应该是“防碰撞”的。 换句话说，应该很难找到两个不同的消息(M，M’) ，也就是Hash(M) == Hash(M’)。 此属性对于数字签名非常重要，因为我们通常不直接对消息签名，而是对消息的哈希进行签名。 如果攻击者能够找到两个哈希值相同的消息，那么一个消息上的签名(哈希)也就是另一个消息上的签名。 实际上，这可能会导致不好的后果。
有时候我们对哈希函数的要求甚至更高。 棘手的部分是知道我们还能要求多少。 为了说明这一点，让我先举一个例子。
Delphia 中的加密技术 想象一下你生活在 Delphia，一个禁止所有加密算法的国家。 尽管如此，你还是有秘密要保守。 你注意到你的政府并没有禁止哈希函数。 这给了你一个想法: 也许你可以从哈希函数中‘黑掉’一个加密方案。
这并不疯狂。 许多哈希算法的输出看起来非常随机。 也许你可以使用哈希函数来构建流密码。 基本上，你将使用一个哈希函数来哈希一个秘密密钥(以及某种计数器值) ; 这将产生一个“随机查找”的字节流，然后你可以使用明文进行 XOR。
问题是: “单向”和“防碰撞”哈希函数是否足以确保该方案是安全的？ 我给你一个直截了当的提示: 否。 从技术上讲，这两个属性都不意味着哈希函数的输出是“随机查找”的。 你可以设想满足这些保证的哈希函数，但是产生的输出对于构建流密码毫无用处(比如，它们可能包含由可预测值组成的长字符串)。 如果你使用这些来构建密码，那么你将非常失望。
球形马 当密码学家第一次开始思考类似上面的问题时，他们的问题是他们想从“理想”哈希函数中得到什么。 对于一位数学家来说，答案显而易见。 他们希望它表现得像一个随机函数。 这个术语有一个非常具体的数学定义; 为了这次讨论的目的，我们将使用一个更容易讨论的等价术语。
假设我们想要实现一个理想的哈希函数。 与其设计一个使用混淆与扩散的小算法(就像我们对大多数真正的哈希函数所做的那样) ，我们还不如创建一个大的硬编码表。 该表的某一列中包含输入消息，另一列中包含相应的输出。
关于这个表，重要的是每个输出值都是一个独立的随机字符串。
Input (binary) Output 0 Totally random bitstring 11 Totally random bitstring 200 Totally random bitstring 301 Totally random bitstring 410 Totally random bitstring 511 Totally random bitstring 6.
          
          
        
      </description>
    </item>
    
    <item>
      <title>探索零知识证明系列（四）【转】</title>
      <link>https://www.crs811.com/archives/1949/</link>
      <pubDate>Thu, 30 Jul 2020 13:41:53 +0000</pubDate>
      
      <guid>https://www.crs811.com/archives/1949/</guid>
      <description>
        
          
            作者：郭宇 安比实验室
本文已更新至Github
https://github.com/sec-bit/learning-zkp/blob/master/zkp-intro/4/zkp-rom.md
“Challenges are at times an indication of Lord&#39;s trust in you.” 挑战，有时是上天信任你的一种表现。― D. Todd Christofferson
本文继续长篇大论零知识证明背后的机制原理，希望帮助大家理解这一类「现代密码学工具」的大致轮廓。本文约8000字，少量数学公式。
交互与挑战 我们之前介绍的零知识证明系统都是「交互式」的，需要验证者 Bob 在交互中提供一个或若干个「随机数」来挑战，比如「地图三染色问题」（参看『系列二』）中，验证者 Bob 需要「不断地」随机挑选一条边来挑战 Alice 的答案，直到 Bob 满意为止，而 Alice 的作弊概率会「指数级」地衰减。而让 Bob 相信证明的「基础」取决于 Bob 所挑选的随机数是不是足够随机。如果 Alice 能够提前预测到 Bob 的随机数，灾难就会发生，现实世界就会退化成「理想世界」，而 Alice 就可以立即升级成「模拟器」，通过超能力来愚弄 Bob。
而『系列三』中，我们分析了 Schnorr 协议，协议中虽然验证者 Bob 只需要挑选一个随机数 c 来挑战 Alice ，让她计算一个值 z，但 Bob 绝对不能让 Alice 有能力来预测到 c 的任何知识，否则，Alice 也会变身成模拟器。
随机数的重要性不言而喻：
通过随机数挑战是交互式零知识证明的「信任根基」。
但，「交互过程」会限制应用场景。如果能将交互式零知识证明变成「非交互」？这会非常非常激动人心。所谓的非交互可以看成是只有「一轮」的证明过程，即Alice 直接发一个证明给 Bob 进行验证。
非交互式零知识证明，英文是 Non-Interactive Zero Knowledge，简称 NIZK。它意味整个证明被编码为一个「字符串」，它可以写到一张纸上，通过邮件、聊天工具等各种方式随意发送给任何验证者，字符串甚至可以放在 Github 上随时供大家下载验证。
          
          
        
      </description>
    </item>
    
    <item>
      <title>探索零知识证明系列（三）【转】</title>
      <link>https://www.crs811.com/archives/1946/</link>
      <pubDate>Thu, 30 Jul 2020 13:33:59 +0000</pubDate>
      
      <guid>https://www.crs811.com/archives/1946/</guid>
      <description>
        
          
            作者：郭宇 安比实验室
本文已更新至Github
https://github.com/sec-bit/learning-zkp/blob/master/zkp-intro/3/zkp-pok.md
导言：有些理论非常有趣，零知识证明便是其中之一，摸索了许久，想写点什么，与大家一起讨论。本文是『探索零知识证明』系列的第三篇。全文约 7,000 字，少量数学公式。
And what, Socrates, is the food of the soul? Surely, I said, knowledge is the food of the soul. 苏格拉底，什么是灵魂的食物？我说过，当然是知识。 —— 柏拉图
「零知识」vs. 「可靠性」 我们在许多介绍零知识证明的文章中都能看到这样三个性质：
Completeness —— 完备性
Soundness —— 可靠性
Zero-Knowledge —— 零知识
但是少有文章深入解释这个特性背后的深意和洞见。
在『系列（二）理解「模拟」』一文中，我们介绍了「模拟器」这个概念。许多介绍文章避而不谈「模拟」，但「模拟」可以说是安全协议中核心的核心，因为它是定义「安全性」的重要武器。
通常，我们定义安全会采用这样一种方式，首先列出一些安全事件，然后说明：如果一个系统安全，那么列出来的安全事件都不会发生。
Rather than giving a list of the events that are not allowed to occur, it (the definition of zero-knowledge proof) gives a maximalist simulation condition.
— Boaz Barak
          
          
        
      </description>
    </item>
    
    <item>
      <title>探索零知识证明系列（二）【转】</title>
      <link>https://www.crs811.com/archives/1941/</link>
      <pubDate>Thu, 30 Jul 2020 13:22:16 +0000</pubDate>
      
      <guid>https://www.crs811.com/archives/1941/</guid>
      <description>
        
          
            作者：郭宇 安比实验室 本文已更新至Github
https://github.com/sec-bit/learning-zkp/blob/master/zkp-intro/2/zkp-simu.md
I know that I know nothing —— 苏格拉底
相信很多人都听说过零知识证明，但是只有极少数人听说过模拟，然而模拟是理解零知识的关键。
我们在第一篇文章『初识「零知识」与「证明」』[1]中介绍了一个简单的零知识交互系统：地图三染色问题。那么这个系统真的是零知识的吗？我们为什么要相信这个结论呢？有证明吗？在 Alice 与 Bob 的对话过程中，如果不零知识，Alice就被坑了。交互式系统的设计者「我」需要让 Alice 确信，这个对话确实是零知识的。
如果从直觉主义角度解释，要证明一个交互系统中存在信息泄露，那么你只需要指证：第几个 bit 导致信息泄露即可；但如果要证明不存在信息泄露，那么你要对着所有信息流中的所有 bit 说，这从1，2，3，4，5，…… 编号的 bit 都没泄露任何信息。看官们，这是不是很难？
本文约八千字，略微烧脑。
安全的定义与不可区分性 首先，一个交互式系统，也就是一个对话，它的「零知识」需要证明。毕竟，现代密码学是建立在严格的形式化系统之上。在证明之前，还需要明确「安全假设」到底有哪些。所谓安全假设，比如我们说一个系统的权限隔离做得无比精确，每一个用户只能看到被授权的信息，但是这基于一个安全假设：管理员账号没有被破解。又比如在手机银行软件里，只能通过短信认证码，才能完成转账功能，这也基于一个安全假设：你的手机 SIM 卡没有被克隆。如果我们深入地分析每一个我们感觉安全的系统，都存在大量的似乎不那么稳固的安全假设。比特币私钥安全吗？比特币账户的安全假设也不少：首先你的助记词不能让别人知道，手机钱包里私钥保存加密算法足够强，密钥派生算法正规，你不能忘记助记词，等等等。
脱离安全假设来谈安全都是在耍流氓。一切安全都有前提的。只有经过数学证明之后，大家才能够确信这个 算法/方案 的安全性基于一些非常明确的「安全假设」。
在证明之前，还缺少一个东西，那就是「安全定义」。在多数人的认知系统中，安全就是一个框，什么都可以往里装。大家应该好好提醒下自己，当谈论安全二字的时候，有没有想过到底什么是安全？怎么算安全？
「安全」需要有一个数学意义上的严格定义
伟大的科学家香农（Claude Shannon）从信息论的角度给出了一个非常靠谱的安全性定义[2]：
完美安全：假设你是一个攻击者，你通过密文获取不到任何有价值的信息，破解的唯一手段就是靠瞎蒙。
大家想一想，这个定义很有趣，通过密文获取不到信息，这就意味着你没有获得任何额外的计算能力，能够帮助让你以更短的时间来计算出明文。
但是这个定义太完美，以至于使用的加密算法都很难满足这个安全性定义。后来 Goldwasser 与 Micali 等人写了另一篇载入史册的经典『概率加密』[2]。
在这篇论文中定义了这样一个概念：语义安全。所谓语义安全在完美安全的定义上放松了些要求。
语义安全：假设你是一个攻击者，你通过密文在多项式时间内计算不出来任何有价值的信息。 好了，这个看起来靠谱多了。接下来一个问题就是，怎么理解「计算不出来信息」这个概念？这看来要对信息进行度量，信息的定义又是什么呢？
我们又引入一个概念——「不可区分性」，来重新表述加密算法的安全性：假设你是一个攻击者，而我有一个加密算法：
1.你随机产生两段等长的明文，m1=「白日依山尽，黄河入海流」，m2=「烫烫烫烫烫，烫烫烫烫烫」
2.你把这两段明文，m1 与 m2 交给我
3.我随机挑选一个明文，不告诉你是哪一个，然后进行加密，产生一个密文 c
4.我把密文 c 出示给你看，让你猜这个c 究竟是由唐诗加密产生，还是乱码加密产生
5.如果你用一台计算机来破解c，在多项式时间内破解不出来，也就是说你没办法区分c的来源，那么就说明加密算法是语义安全的
OK，理解完「不可区分性」，我们再回到「零知识」，如何证明一个交互式系统是「零知识」呢？首先我们要定义下零知识这个概念。
注：不可区分性是概率意义上的不可区分；在学术上，它可以分为「完全不可区分」，「统计不可区分」，还有「计算不可区分」。在本文中，我们暂时不需要理解这些概念的差别。
遇见模拟器 先开个脑洞，设想在平行宇宙中，有两个平行的世界，一个叫做「理想世界」（Ideal World），另一个叫做「现实世界」（Real World）。我们每一个个体可以在两个平行世界中愉快地玩耍，但是两个世界的普通人无法互相感知，也无法互相沟通。
假设「你」是一个很厉害的密码破解者，而且「你」不是普通人，具备在平行宇宙之间穿梭的能力。而 Alice 有一个地图三染色的答案，你的目的是通过和 Alice 对话来获取地图三染色的答案，会话的过程参考上一篇文章的「地图三染色问题」协议。
          
          
        
      </description>
    </item>
    
    <item>
      <title>探索零知识证明系列（一）【转】</title>
      <link>https://www.crs811.com/archives/1934/</link>
      <pubDate>Thu, 30 Jul 2020 13:12:43 +0000</pubDate>
      
      <guid>https://www.crs811.com/archives/1934/</guid>
      <description>
        
          
            作者：郭宇 安比实验室
本文已更新至Github: https://github.com/sec-bit/learning-zkp/blob/master/zkp-intro/1/zkp-back.md
引言： 我认为区块链很难称为一个“技术”。它更像是一个领域，包罗万象。或者形而上地说，区块链更像一个有机体，融合了各种不同的理论技术。
零知识证明是构建信任的重要技术，也是区块链这个有机体中不可缺少的一环。
零知识证明是打通链上数据与链下计算的关键技术，也是实现链上数据隐私保护的重要途径
要解释「零知识证明」，我们需要先解释「证明」，然后解释什么是「知识」，最后再解释什么是「零知识」。
&#34;证明&#34; 的前世今生 什么是证明？很多人可能和我一样，看到这两个字，会不禁想起中学考卷中各种三角相似的几何图形，当老师在神奇地画出一条辅助线后，证明过程突然显而易见，然后会懊悔自己为何没想到。
古希腊：「证明」 == 「洞见」
数学证明最早源于古希腊。他们发明（发现）了公理与逻辑，他们用证明来说服对方，而不是靠权威。这是彻头彻尾的「去中心化」。自古希腊以降，这种方法论影响了整个人类文明的进程。
上图是「勾股定理」的巧妙证明。历史上曾出现过许许多多精巧的证明，神奇的思路，天才的灵感。一旦一个命题被证明，上帝都无能为力。嗯，对了，还有那个「上帝不是万能的」证明：上帝不能造出一块他举不起来的石头。
一个数学证明往往暗藏无比深刻的「洞见」，相信很多人都看过「费马大定理」的故事[1]，这个定理证明横跨四百年，从费马写下「这里空间太小，我写不下」，到怀尔斯最终登顶，耗费了许多代人的聪明才智。最近如「彭加莱猜想」，稍微带点年代感的如「哥德巴赫猜想」，还有我非常敬佩的华裔科学家张益唐十年磨一剑，在仔细研究了「Goldston-Pintz-Yıldırım」和 「Bombieri-Friedlander-Iwaniec.」的证明「洞见」之后，证明了「质数间的有界间隔」[2]。
自十七世纪，莱布尼茨起，人们就梦想找到一种机械的手段，可以来自动完成证明，而不再依赖天才的灵光一现。
二十世纪初：「证明」 == 「符号推理」 时间到了十九世纪末，康托、布尔、弗雷格、希尔伯特、罗素、布劳威、哥德尔等人定义了形式化逻辑的符号系统。而「证明」则是在利用形式化逻辑的符号语言编写的推理过程。逻辑本身靠谱么？逻辑本身「自恰」吗？逻辑推理本身对不对，能够证明吗？这让 数学家/逻辑学家/计算机科学家 发明（发现） 了符号系统，语法 vs. 语义，可靠 vs. 完备，递归 vs. 无穷。（这部分精彩故事请参看『逻辑的引擎』一书[3]）。
1910年，罗素发表了洪(zhuan)荒(tou)巨著『数学原理』。在书中，罗素与怀特海试图将数学完整地「形式化」下来。如果能达到这样的目标，所有的数学成果都将以证明的方式建立在坚实的基础上。下图就是『数学原理（卷二）』中的一页：
其中110.643这是一个命题：「1+1=2」，然后接下来就是这个定理的证明。大家可能奇怪，难道 1+1 还需要证明吗？是的，在数学原理一书中，数字 0，1，2，…… 都有严格定义，「加法」、「乘法」、「等于」都要严格定义，然后每一步的推理都需要指出依据。证明意味着什么？证明是可能繁琐无比的、但是每一步推理都严格无误。书中大量的证明都机械式的，按照公理和推理规则进行一种证明的构造，寻找证明就好像可以交给一个人，然后他无脑在公理与推理规则的集合中进行机械查找。 似乎人们距离「定理的自动证明」并不遥远了。
不幸的是，哥德尔在 1931 年证明了「哥德尔不完备性定理」[4]，图灵在 1936 年证明了图灵机停机问题的不可判定性[5]。这些成果彻底终结了这个几百年的幻想。无论公理系统如何精巧设计，都无法抓住所有的真理。
证明不仅仅是一个严格推理，而且凝结了似乎很难机械化的创造性思维。证明中蕴含了大量的「知识」，每一次的突破，都将我们的认知提升到一个新的高度。不管是「洞见」，还是推理过程中所构造的「算法」，一个定理的证明的内涵往往远超出定理本身的结论。
六十年代：「证明」 == 「程序」 又过了半个世纪，到了六十年代，逻辑学家 Haskell Curry 和 William Howard 相继发现了在「逻辑系统」和「计算系统— Lambda 演算」中出现了很多「神奇的对应」，这就是后来被命名的「Curry-Howard Correspondence」。这个发现使得大家恍然大悟，「编写程序」和「编写证明」实际在概念上是完全统一的。而在这之后的 50 年，相关理论与技术发展使得证明不再停留在草稿纸上，而是可以用程序来表达。这个同构映射非常有趣：程序的类型对应于证明的定理；循环对应于归纳；……（这里推荐一本书：『软件基础』（Software Foundations 中译本）[6]）。在直觉主义框架中，证明就意味着构造算法，构造算法实际上就是在写代码。(反过来也成立，嗯，码农码的不是代码，是数学证明，:P)
目前在计算机科学领域，许多理论的证明已经从纸上的草图变成了代码的形式，比较流行的「证明编程语言」有 Coq，Isabelle，Agda 等等。采用编程的方式来构造证明，证明的正确性检查可以机械地由程序完成，并且许多啰嗦重复性的劳动可以由程序来辅助完成。数学理论证明的大厦正在像计算机软件一样，逐步地构建过程中。1996 年 12 月 W. McCune 利用自动定理证明工具 EQP 证明了一个 长达 63 年历史的数学猜想「Ronbins 猜想」，『纽约时报』随后发表了一篇题为「Computer Math Proof Shows Reasoning Power」的文章[7]，再一次探讨机器能否代替人类创造性思维的可能性。
          
          
        
      </description>
    </item>
    
    <item>
      <title>Ajax 请求 ES5,ES6,ES7的不同写法</title>
      <link>https://www.crs811.com/archives/1909/</link>
      <pubDate>Mon, 04 May 2020 11:41:39 +0000</pubDate>
      
      <guid>https://www.crs811.com/archives/1909/</guid>
      <description>
        
          
            登录Form： 1&amp;lt;form class=&amp;#34;form-aaa&amp;#34; method=&amp;#34;post&amp;#34;&amp;gt;&amp;lt;/form&amp;gt;&amp;lt;%ES6, 7%&amp;gt; 2&amp;lt;form class=&amp;#34;form-aaa&amp;#34; action=&amp;#34;${path}/user/dologin&amp;#34; method=&amp;#34;post&amp;#34;&amp;gt; &amp;lt;%ES5%&amp;gt; 3 &amp;lt;h2 class=&amp;#34;form-signin-heading&amp;#34;&amp;gt;用户登录&amp;lt;/h2&amp;gt; 4 &amp;lt;label for=&amp;#34;username&amp;#34; class=&amp;#34;sr-only&amp;#34;&amp;gt;用户名&amp;lt;/label&amp;gt; 5 &amp;lt;input type=&amp;#34;text&amp;#34; id=&amp;#34;username&amp;#34; name=&amp;#34;name&amp;#34; class=&amp;#34;form-control&amp;#34; placeholder=&amp;#34;用户名&amp;#34; required autofocus&amp;gt; 6 &amp;lt;br /&amp;gt; 7 &amp;lt;label for=&amp;#34;inputPassword&amp;#34; class=&amp;#34;sr-only&amp;#34;&amp;gt;密码&amp;lt;/label&amp;gt; 8 &amp;lt;input type=&amp;#34;password&amp;#34; id=&amp;#34;inputPassword&amp;#34; name=&amp;#34;pwd&amp;#34; class=&amp;#34;form-control&amp;#34; placeholder=&amp;#34;密码&amp;#34; required&amp;gt; 9 &amp;lt;div class=&amp;#34;checkbox&amp;#34;&amp;gt; 10 &amp;lt;label&amp;gt; 11 &amp;lt;input type=&amp;#34;checkbox&amp;#34; value=&amp;#34;remember-me&amp;#34;&amp;gt; 12 记住我 &amp;lt;/label&amp;gt; 13 &amp;lt;/div&amp;gt; 14 &amp;lt;input class=&amp;#34;btn btn-lg btn-primary btn-block ajax-post&amp;#34; type=&amp;#34;submit&amp;#34; value=&amp;#34;登录&amp;#34; target-form=&amp;#34;form-aaa&amp;#34;&amp;gt; 15&amp;lt;/form&amp;gt; ES5: 1//dom加载完成后执行的js 2$(function(){ 3 //ajax post submit请求 4 $(&amp;#39;.
          
          
        
      </description>
    </item>
    
    <item>
      <title>PHP  轮子介绍 – Yii2</title>
      <link>https://www.crs811.com/archives/1886/</link>
      <pubDate>Sat, 14 Mar 2020 03:41:19 +0000</pubDate>
      
      <guid>https://www.crs811.com/archives/1886/</guid>
      <description>
        
          
            &amp;quot;omnipay/common&amp;quot;: &amp;quot;^3.0&amp;quot;,
https://packagist.org/packages/omnipay/common?query=lokielse%2Fomnipay-alipay
https://github.com/thephpleague/omnipay-common
一个框架混合了多网关支付处理的库
&amp;quot;lokielse/omnipay-alipay&amp;quot;: &amp;quot;^3.0&amp;quot;,
&amp;quot;lokielse/omnipay-wechatpay&amp;quot;: &amp;quot;^3.0&amp;quot;,
&amp;quot;lokielse/omnipay-unionpay&amp;quot;: &amp;quot;^3.0&amp;quot;,
https://packagist.org/packages/lokielse/omnipay-alipay
Alipay/wechat/union gateway for Omnipay payment processing library
支付类扩展
&amp;quot;kartik-v/yii2-widget-datepicker&amp;quot;: &amp;quot;@dev&amp;quot;,
&amp;quot;kartik-v/yii2-widget-timepicker&amp;quot;: &amp;quot;*&amp;quot;,
&amp;quot;kartik-v/yii2-widget-colorinput&amp;quot;: &amp;quot;*&amp;quot;,
&amp;quot;kartik-v/yii2-widget-select2&amp;quot;: &amp;quot;@dev&amp;quot;,
&amp;quot;kartik-v/yii2-date-range&amp;quot;: &amp;quot;*&amp;quot;,
&amp;quot;kartik-v/yii2-widget-datetimepicker&amp;quot;: &amp;quot;dev-master&amp;quot;,
&amp;quot;kartik-v/yii2-field-range&amp;quot;: &amp;quot;~1.3.5&amp;quot;,
&amp;quot;kartik-v/yii2-widgets&amp;quot;: &amp;quot;~3.4.1&amp;quot;,
https://packagist.org/packages/kartik-v/yii2-widgets
用于Yii Framework 2.0的有用小部件的集合，扩展Bootstrap的功能
&amp;quot;2amigos/qrcode-library&amp;quot;: &amp;quot;^1.1&amp;quot;,
https://github.com/2amigos/qrcode-library
这个库允许开发人员轻松地生成二维码。它独立工作，还提供Yii2组件供在框架上使用。
&amp;quot;aliyuncs/oss-sdk-php&amp;quot;: &amp;quot;~2.0&amp;quot;,
https://packagist.org/packages/aliyuncs/oss-sdk-php
https://github.com/aliyun/aliyun-oss-php-sdk
阿里云对象存储服务(OSS)
&amp;quot;linslin/yii2-curl&amp;quot;: &amp;quot;*&amp;quot;,
Easy and nice cURL extension with RESTful support for Yii2
https://github.com/linslin/Yii2-Curl
&amp;quot;overtrue/pinyin&amp;quot;: &amp;quot;~3.0&amp;quot;,
Chinese to pinyin translator.
中文转拼音
&amp;quot;overtrue/easy-sms&amp;quot;: &amp;quot;^1.
          
          
        
      </description>
    </item>
    
    <item>
      <title>DI</title>
      <link>https://www.crs811.com/archives/1859/</link>
      <pubDate>Tue, 18 Feb 2020 01:33:28 +0000</pubDate>
      
      <guid>https://www.crs811.com/archives/1859/</guid>
      <description>
        
          
            依赖
如果在 Class A 中，有 Class B 的实例，则称 Class A 对 Class B 有一个依赖 1public class A { 2 ... 3 B _b; 4 ... 5 public A() { 6 _b = new B(); 7 } 8} 仔细看这段代码我们会发现存在一些问题：
(1). 如果现在要改变 _b 生成方式，如需要用 new B(...) 初始化 _b，需要修改 A 代码；
(2). 如果想测试不同 B 对象对 A 的影响很困难，因为 _b 的初始化被写死在了 A的构造函数中；
(3). 如果new B()过程非常缓慢，单测时我们希望用已经初始化好的 _b 对象 Mock 掉这个过程也很困难。
2. 依赖注入 简单的来说，依赖注入就是不在A类中进行实例化B，而是在A类的外面就把B类实例化好，然后通过参数的方式传入A类，再在A类中赋值给A类里的自定义变量
上面将依赖在构造函数中直接初始化是一种 Hard init 方式，弊端在于两个类不够独立，不方便测试。我们还有另外一种 Init 方式，如下：
          
          
        
      </description>
    </item>
    
    <item>
      <title>Servlet 详解</title>
      <link>https://www.crs811.com/archives/1836/</link>
      <pubDate>Sat, 15 Feb 2020 10:30:00 +0000</pubDate>
      
      <guid>https://www.crs811.com/archives/1836/</guid>
      <description>
        
          
            一、概念 1. Servlet Servlet是server applet的缩写，译为：运行在服务器端的小程序
servlet就是一个接口，定义了java类被浏览器访问到[tomcat识别]的规则
我们可以自定义一个类，实现servlet接口，重写方法，实现逻辑
Servlet比较特殊，不需要new，自动就可以运行。也有创建、垃圾回收和销毁过程。
Servlet是JavaWeb的三大组件之一（Servlet、Filter、Listener），属于动态资源。
Servlet的作用是处理请求，服务器会把接收到的请求交给Servlet来处理，在Servlet中通常需要：
接收请求数据
处理请求
完成响应
例如客户端发出登录请求，或者输出注册请求，这些请求都应该由Servlet来完成处理
Servlet需要我们自己来编写，每个Servlet必须实现javax.servlet.Servlet接口。Servlet对象驻留在服务器内存中。
2. servlet与servlet容器 Java Servlet（Java服务器小程序）是一个基于Java技术的Web组件，运行在服务器端，它由Servlet容器所管理，用于生成动态的内容。 Servlet是平台独立的Java类，编写一个Servlet，实际上就是按照Servlet规范编写一个Java类。Servlet被编译为平台独立 的字节码，可以被动态地加载到支持Java技术的Web服务器中运行。
Servlet容器（如 Tomcat）也叫做Servlet引擎，是Web服务器或应用程序服务器的一部分，用于在发送的请求和响应之上提供网络服务，解码基于 MIME的请求，格式化基于MIME的响应。Servlet没有main方法，不能独立运行，它必须被部署到Servlet容器中，由容器来实例化和调用 Servlet的方法（如doGet()和doPost()），Servlet容器在Servlet的生命周期内包容和管理Servlet。在JSP技术 推出后，管理和运行Servlet/JSP的容器也称为Web容器。
注：常用的MIME类型：
text/html，application/pdf，video/quicktime，application /java，image/jpeg，application/jar，application/octet-stream，application/x-zip
有了servlet之后，用户通过单击某个链接或者直接在浏览器的地址栏中输入URL来访问Servlet，Web服务器接收到该请求后，并不是将 请求直接交给Servlet，而是交给Servlet容器。Servlet容器实例化Servlet，调用Servlet的一个特定方法对请求进行处理， 并产生一个响应。这个响应由Servlet容器返回给Web服务器，Web服务器包装这个响应，以HTTP响应的形式发送给Web浏览器。
二、简单示例 1、创建 java 工程 File &amp;gt;&amp;gt; New Project &amp;gt;&amp;gt; Java Enterprise，工程命名为 ServletTest
2、创建目录 在项目根目录创建目录： **web/WEB-INF **
在 WEB-INF 下创建目录 classes 和 lib
点击file菜单，选择project Structure （ctrl+alt+shift+s）, 把当前项目的 **Paths ** 输出路径（Output path）改成 WEB-INF 下的 **classes **
3、创建Package 在 src 中创建 Package : com.
          
          
        
      </description>
    </item>
    
    <item>
      <title>JsTree3 基本用法 – checkbox和动态加载</title>
      <link>https://www.crs811.com/archives/1804/</link>
      <pubDate>Thu, 06 Feb 2020 14:07:18 +0000</pubDate>
      
      <guid>https://www.crs811.com/archives/1804/</guid>
      <description>
        
          
            jsTree是jQuery的插件，具有交互性的树。
它是免费的、开源的、容易扩展、主题化和可配置的，它支持HTML、JSON数据源和数据加载。
HTML: 1&amp;lt;div class=&amp;#34;row&amp;#34;&amp;gt; 2 &amp;lt;div class=&amp;#34;col-xs-3&amp;#34;&amp;gt;&amp;lt;/div&amp;gt; 3 &amp;lt;div class=&amp;#34;box box-primary&amp;#34;&amp;gt; 4 &amp;lt;div class=&amp;#34;box-header with-border&amp;#34;&amp;gt; 5 &amp;lt;i class=&amp;#34;fa fa-gears&amp;#34;&amp;gt;&amp;lt;/i&amp;gt;&amp;lt;h3 class=&amp;#34;box-title&amp;#34;&amp;gt;权限选择实验&amp;lt;/h3&amp;gt; 6 &amp;lt;/div&amp;gt; 7 &amp;lt;div class=&amp;#34;box-body table-responsive&amp;#34;&amp;gt; 8 &amp;lt;div id=&amp;#34;mytree&amp;#34;&amp;gt; 9 &amp;lt;/div&amp;gt; 10 &amp;lt;button class=&amp;#34;btn btn-primary&amp;#34; type=&amp;#34;button&amp;#34; onclick=&amp;#34;submitForm()&amp;#34;&amp;gt;提交&amp;lt;/button&amp;gt; 11 &amp;lt;/div&amp;gt; 12 13 &amp;lt;div class=&amp;#34;box-header with-border&amp;#34;&amp;gt; 14 &amp;lt;i class=&amp;#34;fa fa-gears&amp;#34;&amp;gt;&amp;lt;/i&amp;gt;&amp;lt;h3 class=&amp;#34;box-title&amp;#34;&amp;gt;动态加载实验&amp;lt;/h3&amp;gt; 15 &amp;lt;/div&amp;gt; 16 &amp;lt;div class=&amp;#34;box-body table-responsive&amp;#34;&amp;gt; 17 &amp;lt;div id=&amp;#34;mytree2&amp;#34;&amp;gt; 18 &amp;lt;/div&amp;gt; 19 &amp;lt;button type=&amp;#34;button&amp;#34; class=&amp;#34;btn btn-success btn-sm&amp;#34; onclick=&amp;#34;demo_create();&amp;#34;&amp;gt;添加子节点&amp;lt;/button&amp;gt; 20 &amp;lt;/div&amp;gt; 21 22 &amp;lt;/div&amp;gt; 23 &amp;lt;/div&amp;gt; 24&amp;lt;/div&amp;gt; 使用场景一：checkbox （如：权限设置） 需求1：加载所有权限树形清单
          
          
        
      </description>
    </item>
    
    <item>
      <title>SSM框架下，spring中service和dao层的关系[转]</title>
      <link>https://www.crs811.com/archives/1762/</link>
      <pubDate>Thu, 05 Dec 2019 09:30:08 +0000</pubDate>
      
      <guid>https://www.crs811.com/archives/1762/</guid>
      <description>
        
          
            1、java web 中dao 层和service层都使用接口，是否是为使用接口而使用接口？ 一个dao或者一个service都是一个接口，然后再一个类去实现，为什么不直接使用一个类呢？在入门级（单表）的SSM+maven代码里面，我们甚至可以看到dao和service的接口类中代码内容都是一样的，这个作何理解？
java web中的三层架构:
其中，表示层一般是采用 MVC 架构模式，业务层有事务脚本模式、领域模型模式等，持久层有数据映射器模式（Hibernate即是典型的）、入口模式（MyBatis、JDBC）。企业应用中最关键的显然是业务层。而对于初学者来说，事务脚本模式是最为简单，最容易掌握的。如果开发团队面向对象设计能力一般，而且业务逻辑相对简单，业务层一般都会采用事务脚本模式。
所谓事务脚本模式，就是将业务层的对象分为三类，按照下图的方式组织起来（下图是用EA画的UML类图，一个简单的学生管理的业务层设计）。
如上图所示，在事务脚本模式中，有三类对象。其中，Service类封装业务流程（或者说是界面上的业务流程），DAO类封装对持久层的访问，DTO类封装业务实体对象。各个对象之间的关系如上图所示，这就是所谓业务逻辑的组织方式。
为什么要用Service接口和DAO接口？ 其实就是为了解耦，解耦说的意思是你更改某一层代码，不会影响我其他层代码，如果你会像spring这样的框架，你会了解面向接口编程，表示层调用控制层，控制层调用业务层，业务层调用数据访问层。举个例子，用DAO接口，那么持久层用Hibernate，还是用myBatis，还是 JDBC，随时可以替换，不用修改业务层Service类的代码。
具体来讲：标准主流现在的表现层都是采用MVC综合设计模式，最终目的达到解耦， 初期也许都是new对象去调用下一层，比如你在业务层new一个DAO类的对象，调用DAO类方法访问数据库，这样写是不对的，因为在业务层中是不应该含有具体对象，最多只能有引用，如果有具体对象存在，就耦合了。 当那个对象不存在，我还要修改业务的代码，这不符合逻辑。好比主板上内存坏了，我换内存，没必要连主板一起换。我不用知道内存是哪家生产，不用知道多大容量，只要是内存都可以插上这个接口使用。这就是MVC的意义。
其实因为入门级程序做东西分层次不是那么严格，涉及到的业务很少，举个最简单的例子，你做一个分页的功能，数据1000条，你20条在一个页，你可以把这个功能写成工具类封装起来，然后在业务层里调用这个封装的方法，这才是业务里真正干得事，只要没访问数据库的，都要在业务里写。
DAO一定是和数据库的每张表一一对应，而service则不是。项目中一个service和一个DAO其实也一样可以操作数据库，只不过那要是表非常多，出问题了，那找起来多麻烦，而且太乱了。
一个DAO单独对1个表进行操作。一个Service可以操作几个DAO。
构建业务层的模式：Service + DAO,即DAO中只做CRUD及类似的简单操作(称之为功能点,不包含业务逻辑),Service中通过调用一个或多个DAO中的功能点来组合成为业务逻辑.Service的数量应该由功能模块来决定。在这种模型中业务逻辑是放在Service中的,事务的边界也应该在Service中控制. 当然,直接在Service中控制事务会引入非业务逻辑的代码,幸好spring的AOP可以解决这个问题,这也是引入Spring的原因之一。如果说到缺点,就在于对某些对象的操作就是简单的CRUD，Service层显得累赘。
2、java web中的service，dao，po分别是什么意思和什么作用 Service: Service层是在mcv三层模式中新添加一层，能够更加清晰的定义应用程序的边界，需要操作数据的时候，通过service层访问DAO层来实现。service层做的事情，不仅仅是调用DAO操作数据，还会包含了一定的业务逻辑。整个程序设计就变成了针对服务的设计。
DAO：Data Access Object是一个数据访问接口，数据访问：顾名思义就是与数据库打交道。夹在业务逻辑与数据库资源中间。是MVC模式中Model层
POJO：Persistent Object即持久对象，它们是由一组属性和属性的get和set方法组成。可以看成是与数据库中的表相映射的java对象
Dao主要做数据库的交互工作 Modle 是模型 存放你的实体类 Service 做相应的业务逻辑处理 Action是一个控制器 Action像是服务员，顾客点什么菜，菜上给几号桌，都是ta的职责；Service是厨师，action送来的菜单上的菜全是ta做的；Dao是厨房的小工，和原材料(通过mybatis操作数据库)打交道的事情全是ta管。对象的调用流程：
JSP—Action—Service—DAO—mybatis—数据库。
3、service层事物控制的理解 一般情况下，我们会把事务控制在service层。
例如我们的一个业务：删除A记录，插入B记录（需要在一个事务里进行），如果我们把这个业务逻辑写在了action层，我们再action层调用删除A的service，然后再调用插入B的service，如果说插入B失败了，那我们删除A这个操作将不能回滚，因为事务控制在了service层，这样写已不是一个事务。删除A操作的service已经完成，事务已经提交了，插入B的操作在另外的事务里运行。根据需要，业务逻辑尽量放在service层。通过配置spring事务控制的传播行为，在service层可以达到大部分的业务事务要求，而不需另加一层。spring的事务有两种一种是声明式事务，一种是编程式事务。
action和dao层，会使用一些框架技术。比如action层可能选择有springmvc、struts等，dao层有hibernate、mybatis等选择，所以action的dao有可能根据情况变化，而service层关注业务逻辑，业务代码都是自己完成的，代码对自己是透明的。
我们更应该把与业务相关的代码移至service层控制事务。这主要发生在我们把整个业务逻辑放在了service的一个方法，而这个方法以及调用的方法的事务配置为required（或其他），但业务的部分操作需要在不同的事务中进行，我们不想写另外的方法，也不想去更改事务配置，所以引入support层（或许你说可以把这种逻辑向action层移动，在action层处理，但记住我们的前提，action的框架是会变的，我们想尽量做到更改action层时，更简单。而且从分工来说，action层应该只关注视图逻辑，个人自扫门前雪，休管他人瓦上霜）。support层当然不是只为处理这种事务问题的，我把它定义为业务处理时需要的一些辅助层，可以协助处理业务，比如刚才说的事务问题，还有可以提供工具类支持等。
对于dao层，应该只关注数据库连接执行结果封装这些事。
原文：https://blog.csdn.net/ChenLeihappy/article/details/80003325
          
          
        
      </description>
    </item>
    
    <item>
      <title>Spring 常用注解</title>
      <link>https://www.crs811.com/archives/1757/</link>
      <pubDate>Tue, 26 Nov 2019 04:31:55 +0000</pubDate>
      
      <guid>https://www.crs811.com/archives/1757/</guid>
      <description>
        
          
            1. 注解是什么？ 其实 Java 的注解还是特别常见的，像平时用到的 @Override、@Deprecated 等都是注解的一种表现方式。
对于注解官方解释：为我们在代码中添加信息提供了一种形式化的方法，使我们可以在稍后的某个时刻非常方便地使用这些数据。
2. 注解作用 可以书写更加干净易读的代码，简化重复的工作，比如 Spring 的注解；
另外还提供编译期类型检查，比如外汇返佣@Override 当方法签名对不上覆盖的方法时，编译器就会发出错误提示：
编译时动态处理，编译时通过代码里标识的元数据动态处理，例如动态生成代码
运行时动态处理，运行时通过代码里标识的元数据动态处理，例如使用反射注入实例
简单一点说，Class 类可以看做是所有类的元数据类（JDK 对此类的解释为 Class 类代表了正在运行的 Java 程序中的类和接口），而我们又知道方法区是用来存放已经被加载的类的信息、常量、字段、方法等信息，所以说给人最直观的一个感受就是 Class 类可以间接的与方法区对应起来，具体是如何对应以及是如何操作的，感兴趣的小伙伴可以自行研究。
3. 注解分类 注解名字
注解类型
注解作用
@Override 标准注解
表示当前的方法覆盖自父类方法。如果不小心拼写错误或者方法签名对不上，编译器就会报错
@Deprecated 标准注解
表示此方法已经失效，将在未来版本中删除
@SuppressWarnings 标准注解
关闭编译器的警告信息
@Target 元注解
表示该注解用于什么地方。CONSTRUCTOR:构造器声明 FIELD:域声明(包括enum实例) LOCAL_VARIABLE:局部变量声明 METHOD:方法声明 PACKAGE:包声明 PARAMETER:参数声明 TYPE:类、接口(包括注解类)或者enum声明
4. Spring部分 1. 声明bean的注解
@Component 组件，没有明确的角色
@Service 在业务逻辑层使用（service层）
@Repository 在数据访问层使用（dao层）
@Controller 在展现层使用，控制器的声明（C）
2. 注入bean的注解
@Autowired：由Spring提供
@Inject：由JSR-330提供
@Resource：由JSR-250提供
都可以注解在set方法和属性上，推荐注解在属性上
3. java配置类相关注解
@Configuration 声明当前类为配置类，相当于xml形式的Spring配置（类上）
          
          
        
      </description>
    </item>
    
    <item>
      <title>SSM 架构基础</title>
      <link>https://www.crs811.com/archives/1746/</link>
      <pubDate>Tue, 26 Nov 2019 04:06:30 +0000</pubDate>
      
      <guid>https://www.crs811.com/archives/1746/</guid>
      <description>
        
          
            一、简介 Spring 框架是 Java 应用最广的框架，它的成功来源于理念，而不是技术本身，spring框架是一个为Java应用程序的开发提供了综合、广泛的基础性支持的Java平台。
spring主要的核心依赖有beans，code， context，spel 这是spring里最基本的也是最核心的jar包（或者说是依赖）
spring有两个核心思想：IOC (控制反转) , AOP（面向切面编程）
spring容器可以理解为生产对象（OBJECT）的地方，在这里容器不只是帮我们创建了对象那么简单，它负责了对象的整个生命周期--创建、装配、销毁。
而这里对象的创建管理的控制权都交给了Spring容器，所以这是一种控制权的反转，称为IOC容器，而这里IOC容器不只是Spring才有，很多框架也都有该技术。
springmvc是spring的子框架，继承于spring框架 ， 在ssm框架环境中，springmvc可以向上的扫描去用spring的东西，但是spring却不能扫描到springmvc里面去。
springmvc也是接收请求，返回响应 ，实际上也是一个servlet ，dispatchServlet。
springmvc和servlet的流程是差不多的，都是接受请求，返回响应，和 Sping 无缝结合
mybatis是目前非常流行的持久层框架，功能很强大，然而其实现却比较简单、优雅。mybatis是一个半自动的orm框架，也还是需要自己去写sql语句
mybatis是支持定制化 SQL、存储过程以及高级映射的优秀的持久层框架，其主要就完成2件事情：
封装JDBC操作 利用反射打通Java类与SQL语句之间的相互转换 mybatis的主要设计目的就是让我们对执行SQL语句时对输入输出的数据管理更加方便，所以方便地写出SQL和方便地获取SQL的执行结果才是MyBatis的核心竞争力。
mybatis和大部分框架一样需要一个配置文件，如果是和spring整合的话则不怎么需要，当然如果要开启缓存的话还是需要
然后需要mapper映射文件和dao层的类和方法所对应 ， 在mapper里面写sql语句
单独的mybatis使用需要解析配置文件，然后去调用mapper里的sql语句
二、Spring 2.1 Spring xml写法 原始类：
1public class Source { 2 private String property01; 3 private String property02; 4 /* setter and getter */ 5} bean.xml 文件：
1&amp;lt;beans xmlns=&amp;#34;http://www.springframework.org/schema/beans&amp;#34; 2 xmlns:xsi=&amp;#34;http://www.w3.org/2001/XMLSchema-instance&amp;#34; 3 xsi:schemaLocation=&amp;#34;http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd&amp;#34;&amp;gt; 4 &amp;lt;bean name=&amp;#34;source&amp;#34; class=&amp;#34;pojo.
          
          
        
      </description>
    </item>
    
    <item>
      <title>JavaWeb 开发环境配置 — 基于IDEA 2021.2</title>
      <link>https://www.crs811.com/archives/1708/</link>
      <pubDate>Mon, 18 Nov 2019 11:25:44 +0000</pubDate>
      
      <guid>https://www.crs811.com/archives/1708/</guid>
      <description>
        
          
            一、jdk 11 安装与配置 官网：Java SE Development Kit 11/
安装：双击安装一路下一步即可
配置环境变量：右键单击“我的电脑”图标，选择“属性”。
如果电脑桌面上没有我的电脑图标，按 Window + E 打开文件资源管理器，左侧有我的电脑图标。
点击高级系统设置 -&amp;gt; 环境变量 -&amp;gt; 新建，填入变量名，变量值后点击确定。
注：下图中第4步的变量值为 jdk 的安装位置，如：C:\Program Files\Java\jdk-11.0.5
需要添加的变量名和变量值分别有：
变量名：JAVA_HOME
变量值：C:\Program Files\Java\jdk-11.0.5
选中“系统变量”下的Path，点击编辑，在变量值的末尾加上以下内容后确定保存：
%JAVA_HOME%\bin; 如下图所示：
配置好环境变量接下来检验是否成功：
Window +R，输入cmd后点击确定打开命令窗口，如果配置正确输入java会显示如下信息：
二、Tomcat 9 的安装与配置 官网：https://tomcat.apache.org/
下载: apache-tomcat-9.0.86-windows-x64
安装：下载的文件是压缩包，解压即可用(注意解压路径不要有中文和空格)。
配置Tomcat环境变量和配置JDK环境变量类似：在系统变量下新建变量，
变量名：CATALINA_HOME
变量值：Tomcat的解压目录，如 D:\apache-tomcat-9.0.86
在变量 Path 后添加 %CATALINA_HOME%\bin; 后保存
注意：下面两个验证 tomcat 的步骤不成功也没有关系，只要在 IDEA 的配置中 tomcat 能够正常运行就可以了
按 Window + R 打开，输入cmd打开cmd命令窗口。
输入 startup 后按回车, 配置没问题会启动Tomcat服务
然后打开浏览器输入http://localhost:8080/，如果出现 Tomcat 9.0.86 页面说明Tomcat环境配置正确。
          
          
        
      </description>
    </item>
    
    <item>
      <title>Java Web 学习路线图</title>
      <link>https://www.crs811.com/archives/1705/</link>
      <pubDate>Fri, 15 Nov 2019 01:53:08 +0000</pubDate>
      
      <guid>https://www.crs811.com/archives/1705/</guid>
      <description>
        
          
            最近有些网友问我如何自学 Java 后端，还有些是想从别的方向想转过来，但都不太了解 Java 后端究竟需要学什么，究竟要从哪里学起，哪些是主流的 Java 后端技术等等，导致想学，但又很迷茫，不知从何下手。我就以过来人的经历，写在这篇博客里，不一定都对，但都是我根据自己的经历总结出来的，供你们的参考。
Java 基础 Java 是一门纯粹的面向对象的编程语言，所以除了基础语法之外，必须得弄懂它的 oop 特性：封装、继承、多态。此外还有泛型、反射的特性，很多框架的技术都依赖它，比如 Spring 核心的 Ioc 和 AOP，都用到了反射，而且 Java 自身的动态代理也是利用反射实现的。此外还有 Java 一些标准库也是非常常见，比如集合、I/O、并发，几乎在 Web 开发中无处不在，也是面试经常会被问到的，所以在自学 Java 后端之前，不妨先打好这些基础，另外还有 Java8 的一些新特性，也要重点关注，比如 Lambda 表达式、集合的 Stream 流操作、全新的 Date API 等等，关于新特性，我也写了几篇关于这方面的博客，请自行找吧，就不贴出来了。
关于书籍推荐，我是不建议初学者一开始就拿着「Java 编程思想」啃的，因为当初我就是那个当天下午决定自学 Java，晚上就抱着这本书啃的人，说实话，我当时真的不懂它在说啥，因为我没有一点的面向对象语言编程的基础，而这本书又写得太博大精深了，在当时的我来说，完全是天书，但是我认为它仍然是 Java 界的圣经，每读一次都有所收获。我在这里推荐你们一开始先看「Java 核心技术」，这本书讲得比较通俗易懂，初学者比较能接受。
关于视频推荐，我当初就是听某客的毕向东老师讲的 Java 基础教程（可以关注我的微信公众号获取），毕老师讲的实在是太生动有趣了，不知不觉把我带进 Java 的坑里无法自拔，有时候我会听他视频时笑出声来，也许是我那段自学阶段最有趣的时刻了。
数据库 关于 sql 方面：SQL 教程、MySQL 教程
我是了解了一些基础语法之后，就直接跟着视频的老师做一些表操作实战练习了，比如单表查询、多表查询等。我建议学 sql 切勿眼高手低，需多加练习，不要只看懂了就行，因为工作中写得一手简练的 sql 是非常重要的。在这里我说下我在项目一直秉承着 sql 语句是能避免多表查询就避免多表查询，能够分开多条语句就分开多条语句，因为这里涉及到多表查询性能和数据库扩展的问题。
关于 JDBC 方面：JDBC 教程、 JDBC 获取连接对象源码分析
你需要弄懂 JDBC API 的用法，其实它只是一组规范接口，所有数据库驱动只要实现了 JDBC，那么我们就可以通过标准的 API 调用相应的驱动，完全不用知道驱动是怎么实现的，这就是面向接口编程的好处。而且对于 JDBC 我是直接看视频去理解的，跟着视频做了一个基于 Apache Dbutils 工具做了一个具有事务性的小工具，我特意用思维导图总结了一下：
          
          
        
      </description>
    </item>
    
    <item>
      <title>用 Latex 制作 PPT : beamer模板</title>
      <link>https://www.crs811.com/archives/1659/</link>
      <pubDate>Fri, 18 Oct 2019 06:36:26 +0000</pubDate>
      
      <guid>https://www.crs811.com/archives/1659/</guid>
      <description>
        
          
            幻灯片的制作，整体来说是他们的好用程度是：keynote &amp;gt; Microsoft的PPT &amp;gt; Beamer
keynote有一些特色，比如说magic move，用起来很方便。
PPT作为专业的幻灯制作工具，功能强大，操作简单，很容易就能做出一些炫酷的切换和动画效果，但是对公式的支持不太好，需要在公式编辑器中编辑，可迁移性差，如果不生成PDF，在一台电脑上调好的版面，换一台电脑可能就乱了。
LaTeX Beamer模板，优点是非常简洁，适用于 **多公式，多算法 **的PPT应用场景，缺点是不非常灵活。
Beamer虽然在版面上千篇一律，灵活性差，要做一些动画效果或者实现一些其他功能很不容易，而且要消耗不少的slides页数。
然而，它在数学公式编辑上借助LaTex的强大后台，极具优势。
它编译生成的导航条和数学符号，在PPT上做起来也很不容易，需要用到各种超链接。
LaTeX Beamer 模板欣赏：
模板下载：https://www.latexstudio.net/archives/category/tex-slides/beamer-theme-template
          
          
        
      </description>
    </item>
    
    <item>
      <title>常用数学符号的 LaTeX 表示方法</title>
      <link>https://www.crs811.com/archives/1642/</link>
      <pubDate>Fri, 18 Oct 2019 06:16:09 +0000</pubDate>
      
      <guid>https://www.crs811.com/archives/1642/</guid>
      <description>
        
          
             常用数学符号的 LaTeX 表示方法 （以下内容主要摘自“一份不太简短的 LATEX2e 介绍”） 1、指数和下标可以用^和_后加相应字符来实现。比如： 2、平方根（square root）的输入命令为：\sqrt，n 次方根相应地为:
\sqrt[n]。方根符号的大小由LATEX自动加以调整。也可用\surd 仅给出
符号。比如： 3、命令\overline 和\underline 在表达式的上、下方画出水平线。比如： 4、命令\overbrace 和\underbrace 在表达式的上、下方给出一水平的大括号。 5、向量（Vectors）通常用上方有小箭头（arrow symbols）的变量表示。这可由\vec 得到。另两个命令\overrightarrow 和\overleftarrow在定义从A 到B 的向量时非常有用。 6、分数（fraction）使用\frac{...}{...} 排版。一般来说，1/2 这种形式更受欢迎，因为对于少量的分式，它看起来更好些。 7、积分运算符（integral operator）用\int 来生成。求和运算符（sum
operator）由\sum 生成。乘积运算符（product operator）由\prod 生成。上限和下限用^ 和_来生成，类似于上标和下标。 以下提供一些常用符号的表示方法 
          
          
        
      </description>
    </item>
    
    <item>
      <title>如何免费使用 Web of Science 数据库</title>
      <link>https://www.crs811.com/archives/1630/</link>
      <pubDate>Wed, 09 Oct 2019 02:13:52 +0000</pubDate>
      
      <guid>https://www.crs811.com/archives/1630/</guid>
      <description>
        
          
            Web of Science 是一个非常有用的文献检索数据库，一般需要科研机构购买使用权限，如何可以免费使用呢？
Web of Science 官方网址：http://apps.webofknowledge.com
可以使用如下方法访问：
首先找到一个可用的 sci-hub 域名，可以通过SciHub Desktop &amp;gt;&amp;gt; 功能菜单中的“查找可用域名”功能来查找。
例如这个域名http://sci-hub.tw，然后利用左斜杠（/）将sci-hub网址和上面的 Web of Science 网址连接起来，成下面这种形式：
http://sci-hub.tw/http://apps.webofknowledge.com
回车后一般可以成功进入 WOS，可以看出 WOS 页面是嵌入在 Sci-Hub 页面当中的，此时就可以在这个页面中进行检索操作了。
如果觉得速度慢也可以直接将网址前面的scihub 域名删除，然后就可以直接进入 WOS 当中，而不是嵌套在 sci-hub 中，这个时候就可以正常检索文献了
来源： https://cloud.tencent.com/developer/news/234123
          
          
        
      </description>
    </item>
    
    <item>
      <title>Total Command 9.1X 添加自定义快捷键</title>
      <link>https://www.crs811.com/archives/1595/</link>
      <pubDate>Wed, 25 Sep 2019 06:40:16 +0000</pubDate>
      
      <guid>https://www.crs811.com/archives/1595/</guid>
      <description>
        
          
            位置：配置 &amp;gt;&amp;gt; 选项 &amp;gt;&amp;gt; 其他
选择快捷键，例如用Cmder 替换系统默认的cmd，其快捷键为： Ctrl + G
选择usercmd.ini，新建 em_cmder
点击编辑，依次输入命令，参数（定位到当前目录）和图标文件位置：
在total command 中用Ctrl+G 会打开cmder 并定位到当前目录：
          
          
        
      </description>
    </item>
    
    <item>
      <title>综合布线视频</title>
      <link>https://www.crs811.com/archives/1586/</link>
      <pubDate>Sun, 22 Sep 2019 13:37:24 +0000</pubDate>
      
      <guid>https://www.crs811.com/archives/1586/</guid>
      <description>
        
          
            认识网络综合布线七大子系统 (10 min)
综合布线教学视频-端接、布线、水晶头等 (20 min)
RJ45水晶头与110配线架连接方法 (4 min)
机房总体介绍（综合布线及机房使用常识）( 17 min)
美国数据中心展示中心 机柜 ( 3 min )
24口配线架端接
09网络配线架的巧妙应用（1.5min）
综合布线视频教程2_标清
03-设备上架的流程（综合布线及机房使用常识）
洛杉矶GF机房整柜E3服务器上架实拍
数据中心建设工程
亚洲最大的腾讯数据中心机房是什么样的！
阿里巴巴千岛湖数据中心
Facebook的数据中心，这规模这维护简直太夸张！
探访google谷歌数据中心机房 (英文版)
《TCP/IP协议原理Flash动画讲解》TCP/IP工作流程
5分钟看懂比特币与挖矿的原理
海底光缆是如何铺设的
带你感受黑客专用linux系统(kali)
          
          
        
      </description>
    </item>
    
    <item>
      <title>形式化工具 Proverif 2.0 的使用</title>
      <link>https://www.crs811.com/archives/1673/</link>
      <pubDate>Sun, 25 Aug 2019 01:06:18 +0000</pubDate>
      
      <guid>https://www.crs811.com/archives/1673/</guid>
      <description>
        
          
            一、简介
安全协议已广泛地应用到身份认证、接入控制、密钥分配、电子商务等多个领域，其安全性的需求也越来越迫切。自安全协议出现以来，人们一直对它进行分析设计研究。但由于安全协议总是运行在复杂的、不安全的网络环境中，许多攻击方法产
生的错误用人工检测很难识别，从而保证对协议安全性分析的准确性。
ProVerif 是 Bruno Blanchet 开发的基于Dolev-Yao模型的形式化自动验证密码学协议工具，是用 Prolog 语言实现的系统。它能够描述各种密码学原语，包括：共享密钥密码学和公钥密钥密码学 (加密和数字签名)，Hash 函数和 Deffie-Hellman密钥交换协议，并指定了重写规则和方程式， 输入语言为应用 PI 演算或 Horn 字句。
ProVerif能处理一个无穷会话并发协议和无穷消息空间，克服了状态空间爆炸的问题。应用 ProVerif 工具验证密码协议时，如果协议有漏洞，此工具会给出一个相应的攻击序列。
其主要特点是：
它可以处理许多不同的密码原语，包括共享密钥和公用密钥密码术（加密和签名），哈希函数和Diffie-Hellman密钥协议，这些协议既指定为重写规则，也指定为等式。 它可以处理无限制数量的协议会话（即使是并行的）和无限制的消息空间。由于一些精心选择的近似值，因此获得了该结果。这意味着验证者可以发出错误的攻击，但是如果声称协议满足某些属性，则实际上满足该属性。所考虑的解析算法终止于一大类协议（所谓的“标记”协议）。当工具无法证明属性时，它会尝试重建攻击，即伪造所需属性的协议执行跟踪。 ProVerif可以证明以下属性：
保密（对手无法获得秘密） 身份验证以及更一般的对应属性 高度机密性（机密值更改时，对手看不到差异） 仅术语不同的过程之间的等价关系 二、ProVerif2.0（程序及文档） 下载：
http://prosecco.gforge.inria.fr/personal/bblanche/proverif/
备用下载地址
三、编辑工具
推荐 Sublime 3
3.1 可以自行设置 pv 文件语法高亮，具体设置：
Pv.tmLanguage
3.2 可以将 proverif 设置为默认 Builder System：
先添加环境变量，再创建 Proverif.sublime-build文件，内容如下:
{&#34;cmd&#34;: [&#34;proverif&#34;, &#34;$file&#34;],&#34;file_regex&#34;: &#34;pv$&#34;,&#34;selector&#34;: &#34;source.pv&#34;}三、简单使用
1、打开 sublime 3，输入以下内容并保存为：test.pv
2、从 命令行 进入 proverif 源代码文件夹
推荐使用 git软件，安装好后可以从命令行快速进入某一个文件夹： Git Bash Here
          
          
        
      </description>
    </item>
    
    <item>
      <title>密码学 需要的知识</title>
      <link>https://www.crs811.com/archives/1960/</link>
      <pubDate>Mon, 05 Aug 2019 07:18:20 +0000</pubDate>
      
      <guid>https://www.crs811.com/archives/1960/</guid>
      <description>
        
          
            原文链接
数学基础 密码学是一个高度跨学科的领域，包含纯数学、计算机科学以及电子工程等多方面的知识。个人认为数学基础是最重要的，也是最不好修炼的一门内功。
《高等数学》----------&amp;gt;工程学高数是必修课 《线性代数》---------&amp;gt;线性代数的研究对象是方程组和矩阵，对密码学来说，可以进一步了解《矩阵论》的相关知识。 《概率论》-----------&amp;gt;需要把后续课程，《信息论与编码》的知识也掌握。 《抽象代数》（又称近世代数）-----------&amp;gt;个人认为这是这些数学基础课里面，最重要的一门课，掌握好其中的群、环、域、模的知识，对学习目前热门的公钥加密，数字签名，认证等知识大有裨益。 《数论》-------&amp;gt;基础中的基础，必修课。 密码入门 密码学专业入门：
《现代密码学》第4版-------&amp;gt;杨波老师编写的，一本很薄的讲解基础密码学的书籍 《Introduction to Modern Cryptography》 2ed -------&amp;gt; by Jonathan Katz and Yehuda Lindell ， 口碑之作，入门有一定难度，国防工业出版社翻译出版了第一版：《现代密码学:原理与协议》。 《应用密码学 : 协议算法与c源程序》-------&amp;gt;介绍全面，值得阅读一遍，缺点就是书籍出版的有些年代了(1996年第二版)。 《密码编码学与网络安全——原理与实践》第七版 by William Stalling -------&amp;gt;很多著名大学都采用它做教材，内容比上面那本书新（2017年第七版）。 《密码学原理与实践》第三版 Douglas R.Stinson著 冯登国 译-------&amp;gt;值得精读的一本书 现代密码学所涉及的学科包括：
概率论、随机过程、信息论与编码、数论、代数学（线性代数、矩阵论、抽象代数）、离散数学、计算复杂性、计算机知识和电路基础等。
大学必须掌握数学分析，线性代数，概率论的知识，尤其是概率论，理解透彻；其次，最好熟悉一门编程语言，推荐C或者Java，了解数据结构和算法，锻炼自己的思维，说不定哪天写代码就用上了；如果有精力了解电路、模电、数电的基本知识，HDL语言和FPGA要会，在进行密码的硬件实现时有很方便。最后，推荐了解信息论和通信理论的一些知识，尤其是信息论，这玩意儿在进行熵值分析的时候很有用。
研究生阶段，密码学的基础还是三大块：数学、计算机、密码学。
数学：数论与代数学、信息论与编码、概率论与随机过程、线性代数与矩阵论
计算机：离散数学，可计算性和计算复杂性
密码学：对称密码学、公钥密码学、数据完整性算法、电子认证、安全协议、量子密码等。
密码学，最重要的还是数学基础，比较适合数学专业的学生来学习。
密码学的入门门槛较高，其难点集中在数学，打好数学基础，对于以后做一些有意义、有品位的研究是很重要的。
视频推荐：
信息安全数学基础：http://mooc.study.163.com/course/HIT-1000002013#/info
近视代数：http://mooc.study.163.com/course/HIT-1000003009#/info
近世代数_104_南京大学(孙智伟)：https://www.bilibili.com/video/av9351622/
Coursera 密码学公开课：Stanford University的Cryptography I和Cryptography II
          
          
        
      </description>
    </item>
    
    <item>
      <title>信息安全与密码学博硕士：应该掌握的52个知识点</title>
      <link>https://www.crs811.com/archives/1951/</link>
      <pubDate>Tue, 30 Jul 2019 15:16:15 +0000</pubDate>
      
      <guid>https://www.crs811.com/archives/1951/</guid>
      <description>
        
          
            Bristol大学的密码安全工作组为密码学和信息安全相关的博士准备了52个基本知识点，详细见该网站 密码学是一个高度跨学科的领域，包含纯数学、计算机科学以及电子工程等多方面的知识。考虑读研读博的学生专业知识背景不一，Bristol大学对这方面的知识点进行了一个全面的总结和覆盖。 52个知识点，Bristol大学推荐所有博一学生花一年的时间应该基本掌握，也就是差不多一个星期掌握一个知识点。掌握这些知识点后，对之后的课堂学习、项目执行、论文研读、科研协作、参加国际会议、与密码学者沟通会大有益处；要不然，可能一直处于懵懵懂懂的状态，荒废学业。 Computer Engineering ([E]) 计算机工程 1.What is the difference between the following? A general-purpose processor. A general-purpose processor with instruction-set extensions. A special-purpose processor (or co-processor). An FPGA. 2.What is the difference between a multi-core processor and a vector processor? 3.Estimate the relative computational and storage capabilities of... a smart-card a micro-controller (i.e. a sensor node) an embedded or mobile computer (e.g., a mobile phone or PDA) a laptop- or desktop-class computer.
          
          
        
      </description>
    </item>
    
    <item>
      <title>Linux下设置安全密钥登录</title>
      <link>https://www.crs811.com/archives/1556/</link>
      <pubDate>Wed, 03 Jul 2019 07:38:23 +0000</pubDate>
      
      <guid>https://www.crs811.com/archives/1556/</guid>
      <description>
        
          
            步骤：
1、本地生成密钥（公钥和私钥）：
(1) 本地是 Windows 系统：
打开 XShell ，选择 Tool &amp;gt;&amp;gt; New User Key Wizard
密钥长度可以是1024或2048，导出公钥，假设文件名为：
Ubuntu_59_rsa_2048.pub (2) 本地是 Linux 系统：
ssh-keygen -t rsa -b 2048 #-b 参数指定长度 执行密钥生成命令，基本上是一路回车既可以了，但是需要注意的是：执行命令的过程中是会提示呢输入密钥的密码的，不需要密码直接回车。密钥生成后会在当前目录下产生两个文件：id_rsa和id_rsa.pub，其中id_rsa是私钥，id_rsa.pub是公钥。
2、服务器设置
使用XShell的ssh方式登录服务器，切换到root用户
在用户主目录创建 .ssh 文件夹（没有的话），mkdir .sshcd .sshapt install lrzsz (或 yum install lrzsz) (安装 rzsz 软件)rz (上传公钥文件 Ubuntu_59_rsa_2048.pub)在.ssh 文件夹下创建认证文件authorized_keys，把公钥导入其中：cat Ubuntu_59_rsa_2048.pub &gt; authorized_keys设置文件权限，防恶意篡改chmod 600 authorized_keyschmod 700 /root/.ssh编辑 ssh 的主配置文件：vim /etc/ssh/sshd_config取消注释并修改成如下：StrictModes no //设置为noRSAAuthentication yes //Ubuntu 16 有此项PubkeyAuthentication yes //开启密钥登陆AuthorizedKeysFile .
          
          
        
      </description>
    </item>
    
    <item>
      <title>本地虚拟机 CentOS7 配置 https 站点 (宝塔面板)</title>
      <link>https://www.crs811.com/archives/1533/</link>
      <pubDate>Fri, 21 Jun 2019 07:45:25 +0000</pubDate>
      
      <guid>https://www.crs811.com/archives/1533/</guid>
      <description>
        
          
            本地主机是Windows，虚拟机是CentOS7，在CentOS7中配置 https 的步骤如下：
一、安装宝塔面板，配置站点
yum install -y wget &amp;&amp; wget -O install.sh http://download.bt.cn/install/install.sh &amp;&amp; sh install.sh 询问 Do you want to install Bt-Panel to the /www directory now?(y/n): 输入 y 等待安装完成
宝塔登录界面：
完成后的最后几行：
安装成功后会有登录链接账号以及密码； 在浏览器里打开链接输入账号密码登录； 登录成功后在首页会自动弹出环境类型选择；
选择LNMP；PHP选最新的php7.3 ；选择编译安装；点击“一键安装”
等待安装完成，安装会持续30 min-3 h
安装扩展：
取消禁用：
新建一个站点，如 wxapi.test，没有域名可以直接添加ip；
打开浏览器测试，看到如下界面则说明设置成功：
二、配置SSL
1、安装 openssl （默认是安装了的）
yum install openssl 2、切换到nginx配置文件夹，创建ssl文件夹，切换到ssl文件夹
宝塔面板的nginx 位置：/www/server/nginx
cd /www/server/nginx/confmkdir sslcd ssl 3、生成2048位的加密私钥
openssl genrsa -out server.key 2048 4 生成证书签名请求（CSR），这里需要填写许多信息，随便填写即可
          
          
        
      </description>
    </item>
    
    <item>
      <title>微服务，分布式事务</title>
      <link>https://www.crs811.com/archives/1527/</link>
      <pubDate>Sun, 16 Jun 2019 12:30:50 +0000</pubDate>
      
      <guid>https://www.crs811.com/archives/1527/</guid>
      <description>
        
          
            单体架构（Monolithic架构） 所有的功能打包在一个 包里，基本没有外部依赖（除了容器），部署在一个JEE容器（Tomcat，JBoss，WebLogic）里，包含了 DO/DAO，Service，UI等所有逻辑
优点：
①开发简单，集中式管理
②基本不会重复开发
③功能都在本地，没有分布式的管理和调用消耗
缺点：
1、效率低：开发都在同一个项目改代码，相互等待，冲突不断
2、维护难：代码功功能耦合在一起，新人不知道何从下手
3、不灵活：构建时间长，任何小修改都要重构整个项目，耗时
4、稳定性差：一个微小的问题，都可能导致整个应用挂掉
5、扩展性不够：无法满足高并发下的业务需求
常见的系统架构遵循的三个标准和业务驱动力：
1、提高敏捷性：及时响应业务需求，促进企业发展
2、提升用户体验：提升用户体验，减少用户流失
3、降低成本：降低增加产品、客户或业务方案的成本
微服务架构: 目的：有效的拆分应用，实现敏捷开发和部署
关于微服务的一个形象表达：
X轴：运行多个负载均衡器之后的运行实例
Y轴：将应用进一步分解为微服务（分库）
Z轴：大数据量时，将服务分区（分表）
微服务的具体特征： 官方的定义：
1、一些列的独立的服务共同组成系统
2、单独部署，跑在自己的进程中，近几年流行的Docker，为微服务架构提供了有效的容器
3、每个服务为独立的业务开发
4、分布式管理
5、非常强调隔离性，假如微服务A想要读写微服务B的数据库，只能调用微服务B对外暴露的接口来完成。
大概的标准：
1、分布式服务组成的系统
2、按照业务，而不是技术来划分组织
3、做有生命的产品而不是项目
4、强服务个体和弱通信（ Smart endpoints and dumb pipes ）
5、自动化运维（ DevOps ）
6、高度容错性
7、快速演化和迭代
SOA****和微服务的区别 1、SOA喜欢重用，微服务喜欢重写
SOA的主要目的是为了企业各个系统更加容易地融合在一起。 说到SOA不得不说ESB(EnterpriseService Bus)。 ESB是什么? 可以把ESB想象成一个连接所有企业级服务的脚手架。
通过service broker，它可以把不同数据格式或模型转成canonical格式，把XML的输入转成CSV传给legacy服务，把SOAP 1.1服务转成 SOAP 1.2等等。 它还可以把一个服务路由到另一个服务上，也可以集中化管理业务逻辑，规则和验证等等。 它还有一个重要功能是消息队列和事件驱动的消息传递，比如把JMS服务转化成SOAP协议。 各服务间可能有复杂的依赖关系。
微服务通常由重写一个模块开始。要把整个巨石型的应用重写是有很大的风险的，也不一定必要。我们向微服务迁移的时候通常从耦合度最低的模块或对扩展性要求最高的模块开始，
把它们一个一个剥离出来用敏捷地重写，可以尝试最新的技术和语言和框架，然 后单独布署。 它通常不依赖其他服务。微服务中常用的API Gateway的模式主要目的也不是重用代码，
而是减少客户端和服务间的往来。API gateway模式不等同与Facade模式，我们可以使用如future之类的调用，甚至返回不完整数据。
2、SOA喜欢水平服务，微服务喜欢垂直服务
          
          
        
      </description>
    </item>
    
    <item>
      <title>CentOS7 下 pure-ftp 1.0.47 配置</title>
      <link>https://www.crs811.com/archives/1509/</link>
      <pubDate>Tue, 21 May 2019 12:47:49 +0000</pubDate>
      
      <guid>https://www.crs811.com/archives/1509/</guid>
      <description>
        
          
            1、安装：
默认的 yum 源没有提供 pure-ftpd，需要先安装 epel 扩展源：
yum install epel-release
然后使用 yum 命令安装Pure-ftpd：
yum install pure-ftpd
2、配置：
配置文件位置：
vim /etc/pure-ftpd/pure-ftpd.conf
配置参考：
ChrootEveryone yes //锁定所有用户到家目录中
#TrustedGID 100 //信任组ID100，可以不锁定
MaxClientsNumber 50 //最大的客户端数量
MaxClientsPerIP 8 //同一个IP允许8个链接
DisplayDotFiles no //不显示隐藏文件
AnonymousOnly no //只允许匿名用户
NoAnonymous yes //不允许匿名用户
DontResolve yes //禁止反向解析
MaxIdleTime 10 //最大空闲10分钟
#LDAPConfigFile /etc/pureftpd-ldap.conf //LDAP配置文件目录
#MySQLConfigFile /etc/pureftpd-mysql.conf //MySQL配置文件目录
#PGSQLConfigFile /etc/pureftpd-pgsql.conf //PGSQL配置文件目录
PureDB /etc/pure-ftpd/pureftpd.pdb //虚拟用户数据库
#UnixAuthentication yes //主机认证
LimitRecursion 2000 8 //别表最大显示2000个文件，最深8个目录
AnonymousCanCreateDirs no //是否允许匿名用户创建目录
          
          
        
      </description>
    </item>
    
    <item>
      <title>JWT 相关知识</title>
      <link>https://www.crs811.com/archives/1481/</link>
      <pubDate>Fri, 10 May 2019 01:10:56 +0000</pubDate>
      
      <guid>https://www.crs811.com/archives/1481/</guid>
      <description>
        
          
            1. JSON Web Token是什么
JSON Web Token (JWT)是一个开放标准(RFC 7519)，它定义了一种紧凑的、自包含的方式，用于作为JSON对象在各方之间安全地传输信息。该信息可以被验证和信任，因为它是数字签名的。
简单的讲，JWT 是用于网络间传递声明而执行一种基于 JSON 的标准
官网：https://jwt.io/
2. 为什么使用 JWT？
（1） 跨域认证，单点登录
（2） API开发，前后端分离, 需要简单的对后台API进行保护
（3） 安全的信息交换（数字签名）
3. JWT的结构
JSON Web Token由三部分组成，它们之间用圆点(.)连接。这三部分分别是：
Header Payload Signature 因此，一个典型的JWT看起来是这个样子的：
xxxxx.yyyyy.zzzzz (各个部分均用 Base64URL转码，没有加密，不能放保密数据)
示例：
4. JWT的使用方式
（1） 放在 HTTP 请求的头信息 Authorization字段 里面：
Authorization: Bearer
（2） 放在 POST 请求的数据体里面
（3） 为了安全，JWT 应该使用 HTTPS 传输
5. JWT的优点
（1） 无状态和可扩展性
（2） 安全：Token不是Cookie，每次请求的时候Token都会被发送。而且，由于没有Cookie被发送，还有助于防止CSRF攻击
6. JWT与session的区别
相同点：存储用户信息
不同点：
Session是在服务器端的；JWT是在客户端的，服务端是无状态的
Session方式存储用户信息的最大问题在于要占用大量服务器内存，增加服务器的开销; JWT方式将用户状态分散到了客户端中，可以明显减轻服务端的内存压力。
Session的状态是存储在服务器端，客户端只有session id；而Token的状态是存储在客户端。
          
          
        
      </description>
    </item>
    
    <item>
      <title>AES-256 encryption and decryption in PHP and JS</title>
      <link>https://www.crs811.com/archives/1474/</link>
      <pubDate>Tue, 07 May 2019 03:46:14 +0000</pubDate>
      
      <guid>https://www.crs811.com/archives/1474/</guid>
      <description>
        
          
            PHP:
class clsAES{private $key = &#39;&#39;;private $iv = &#39;&#39;;public function __construct($key, $iv){$this-&gt;key = md5($key);$this-&gt;iv = $iv;}public function encrypt($data){$cryptText = openssl_encrypt($data,&#34;aes-256-cbc&#34;,$this-&gt;key ,OPENSSL_RAW_DATA,$this-&gt;iv);return base64_encode($cryptText);}public function decrypt($data){$cryptText = base64_decode($data);return trim(openssl_decrypt($cryptText, &#39;aes-256-cbc&#39;, $this-&gt;key , OPENSSL_RAW_DATA,$this-&gt;iv));}}JS:
Vue:
import CryptoJS from &#39;crypto-js&#39;const KEY = &#39;5NmhVXqSro6j9eyNO3bzw&#39;;const IV = &#39;1234567890123456&#39;;function getAesString(data, key, iv) {//加密var key_hash = CryptoJS.
          
          
        
      </description>
    </item>
    
    <item>
      <title>AES-256 encryption and decryption in PHP and C#</title>
      <link>https://www.crs811.com/archives/1467/</link>
      <pubDate>Fri, 03 May 2019 15:21:51 +0000</pubDate>
      
      <guid>https://www.crs811.com/archives/1467/</guid>
      <description>
        
          
            PHP
&lt;?php$plaintext = &#39;My secret message 1234&#39;;$password = &#39;3sc3RLrpd17&#39;;// CBC has an IV and thus needs randomness every time a message is encrypted$method = &#39;aes-256-cbc&#39;;// Must be exact 32 chars (256 bit)// You must store this secret random key in a safe place of your system.$key = substr(hash(&#39;sha256&#39;, $password, true), 0, 32);echo &#34;Password:&#34; . $password . &#34;\n&#34;;// Most secure key//$key = openssl_random_pseudo_bytes(openssl_cipher_iv_length($method));// IV must be exact 16 chars (128 bit)$iv = chr(0x0) .
          
          
        
      </description>
    </item>
    
    <item>
      <title>内网涉透工具配置 –  frp</title>
      <link>https://www.crs811.com/archives/1455/</link>
      <pubDate>Fri, 19 Apr 2019 02:12:21 +0000</pubDate>
      
      <guid>https://www.crs811.com/archives/1455/</guid>
      <description>
        
          
            frp 简介 frp 是一个可用于内网穿透的高性能的反向代理应用，支持 tcp, udp, http, https 协议
frp 的作用 利用处于内网或防火墙后的机器，对外网环境提供 http 或 https 服务。 对于 http, https 服务支持基于域名的虚拟主机，支持自定义域名绑定，使多个域名可以共用一个80端口。 利用处于内网或防火墙后的机器，对外网环境提供 tcp 和 udp 服务，例如在家里通过 ssh 访问处于公司内网环境内的主机。 架构 在具有公网IP的服务器或VPS上安装运行 frp 的服务端程序frps，并在处于内网的目标主机上面安装运行 frp 的客户端程序 frpc ，然后 User 就可以通过公网服务器来实现内网穿透从而访问内网主机。
场景 外网服务器：
CentOS 7
内网：
CentOS 7 Ubuntu 18 Windows Server 2008 配置 frp 下载地址 https://github.com/fatedier/frp/releases
外网服务器配置： 下载 frp_0.26.0_linux_amd64.tar.gz：wget https://github.com/fatedier/frp/releases/download/v0.26.0/frp_0.26.0_linux_amd64.tar.gz 解压：
tar -xzvf frp_0.26.0_linux_amd64.tar.gzcd frp_0.26.0_linux_amd64 删除客户端文件:
rm frpcrm frpc.ini 根据需要修改配置文件，默认监听端口是 7000
          
          
        
      </description>
    </item>
    
    <item>
      <title>PHP简洁之道</title>
      <link>https://www.crs811.com/archives/1451/</link>
      <pubDate>Sun, 14 Apr 2019 03:58:33 +0000</pubDate>
      
      <guid>https://www.crs811.com/archives/1451/</guid>
      <description>
        
          
            原文：https://github.com/jupeter/clean-code-php 译文：https://github.com/nineyang/clean-php-code 前言 前几天在GitHub看到一篇写PHP简洁之道的译文，觉得还不错，所以转在了自己的博客中，只不过有一些地方好像没有翻译，再加上排版上的一些小问题，所以决定自己翻译一遍
变量 使用更有意义和更加直白的命名方式 不友好的:
1$ymdstr = $moment-&amp;gt;format(&amp;#39;y-m-d&amp;#39;); 友好的:
1$currentDate = $moment-&amp;gt;format(&amp;#39;y-m-d&amp;#39;); 对于同一实体使用相同变量名 不友好的:
1getUserInfo(); 2getUserData(); 3getUserRecord(); 4getUserProfile(); 友好的:
1getUser(); 使用可以查找到的变量 我们读的代码量远比我们写过的多。因此，写出可阅读和便于搜索的代码是及其重要的。在我们的程序中写出一些难以理解的变量名 到最后甚至会让自己非常伤脑筋。 因此，让你的名字便于搜索吧。
不友好的:
1// 这里的448代表什么意思呢？ 2$result = $serializer-&amp;gt;serialize($data, 448); 友好的:
1$json = $serializer-&amp;gt;serialize($data, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT | &amp;gt;JSON_UNESCAPED_UNICODE); 使用解释型变量 不友好的
1$address = &amp;#39;One Infinite Loop, Cupertino 95014&amp;#39;; 2$cityZipCodeRegex = &amp;#39;/^[^,]+,\s*(.+?)\s*(\d{5})$/&amp;#39;; 3preg_match($cityZipCodeRegex, $address, $matches); 4 5saveCityZipCode($matches[1], $matches[2]); 不至于那么糟糕的:
稍微好一些，但是这取决于我们对正则的熟练程度。
1$address = &amp;#39;One Infinite Loop, Cupertino 95014&amp;#39;; 2$cityZipCodeRegex = &amp;#39;/^[^,]+,\s*(.
          
          
        
      </description>
    </item>
    
    <item>
      <title>[转]APP自动登录 – 深入了解Token认证的来龙去脉</title>
      <link>https://www.crs811.com/archives/1442/</link>
      <pubDate>Fri, 05 Apr 2019 03:12:29 +0000</pubDate>
      
      <guid>https://www.crs811.com/archives/1442/</guid>
      <description>
        
          
            Token 是在服务端产生的，如果前端使用用户名/密码向服务端请求认证，服务端认证成功，那么在服务端会返回 Token 给前端。前端可以在每次请求的时候带上 Token 证明自己的合法地位。
不久前，我在前后端分离实践中提到了基于 Token 的认证，现在我们稍稍深入一些。
通常情况下，我们在讨论某个技术的时候，都是从问题开始。那么第一个问题：
为什么要用 Token？
要回答这个问题很简单，因为它能解决问题！
Token 能解决哪些问题呢？有如下几点：
Token 完全由应用管理，所以它可以避开同源策略。 Token 可以避免 CSRF 攻击(http://dwz.cn/7joLzx)。 Token 可以是无状态的，可以在多个服务间共享。 Token 是在服务端产生的，如果前端使用用户名/密码向服务端请求认证，服务端认证成功，那么在服务端会返回 Token 给前端。 前端可以在每次请求的时候带上 Token 证明自己的合法地位。如果这个 Token 在服务端持久化（比如存入数据库），那它就是一个永久的身份令牌。
于是，又一个问题产生了：需要为 Token 设置有效期吗？
需要设置有效期吗？
对于这个问题，我们不妨先看两个例子：
登录密码，一般要求定期改变密码，以防止泄漏，所以密码是有有效期的。
安全证书，SSL 安全证书都有有效期，目的是为了解决吊销的问题，对于这个问题的详细情况，来看看知乎的回答(http://dwz.cn/7joMhq)。
所以无论是从安全的角度考虑，还是从吊销的角度考虑，Token 都需要设有效期。
那么有效期多长合适呢？只能说，根据系统的安全需要，尽可能的短，但也不能短得离谱。
想像一下手机的自动熄屏时间，如果设置为 10 秒钟无操作自动熄屏，再次点亮需要输入密码，会不会疯？
如果你觉得不会，那就亲自试一试，设置成可以设置的最短时间，坚持一周就好（不排除有人适应这个时间，毕竟手机厂商也是有用户体验研究的）。
然后新问题产生了，如果用户在正常操作的过程中，Token 过期失效了，要求用户重新登录……用户体验岂不是很糟糕？
为了解决在操作过程不能让用户感到 Token 失效这个问题，有一种方案是在服务器端保存 Token 状态，用户每次操作都会自动刷新（推迟） Token 的过期时间——Session 就是采用这种策略来保持用户登录状态的。
然而仍然存在这样一个问题，在前后端分离、单页 App 这些情况下，每秒种可能发起很多次请求，每次都去刷新过期时间会产生非常大的代价。
如果 Token 的过期时间被持久化到数据库或文件，代价就更大了。所以通常为了提升效率，减少消耗，会把 Token 的过期时保存在缓存或者内存中。
还有另一种方案，使用 Refresh Token，它可以避免频繁的读写操作。这种方案中，服务端不需要刷新 Token 的过期时间，一旦 Token 过期，就反馈给前端，前端使用 Refresh Token 申请一个全新 Token 继续使用。
          
          
        
      </description>
    </item>
    
    <item>
      <title>理解Javascript（NodeJS）中的回调函数</title>
      <link>https://www.crs811.com/archives/1398/</link>
      <pubDate>Tue, 26 Feb 2019 05:07:18 +0000</pubDate>
      
      <guid>https://www.crs811.com/archives/1398/</guid>
      <description>
        
          
            1、回调函数的概念
A callback is a function that is passed as an argument to another function and is executed after its parent function has completed
回调函数就是一个参数，将这个函数作为参数传到另一个函数里面，当那个函数执行完之后，再执行传进去的这个函数。这个过程就叫做回调。
示例：
1//定义主函数，参数是一个回调函数 2function A(callback callback(); 3 console.log(&amp;#39;我是主函数1&amp;lt;br/&amp;gt;&amp;#39;); 4 console.log(&amp;#39;我是主函数2&amp;lt;br/&amp;gt;&amp;#39;); 5 console.log(&amp;#39;我是主函数3&amp;lt;br/&amp;gt;&amp;#39;); 6} 说明：
回调函数本身就是一个数据类型。
在javaScript中，函数的地位和java中的String，int，boolean等等都是一样的，都可以看成是一个数据类型。
既然是数据类型，就可以当成参数传递（如：callback）
函数体中打了个括号（** callback(); **）就是执行函数的意思
把函数传入A 方法的目的就是让函数在里面执行
1//定义回调函数 2function B(){ 3 setTimeout(&amp;#34;console.log(&amp;#39;我是回调函数&amp;#39;)&amp;#34;, 3000);//延时3秒，模仿耗时操作 4} 5 6//调用主函数，将函数B传进去 7A(B); 输出：
我是主函数1 我是主函数1 我是主函数1 我是回调函数 定义主函数的时候，我们让代码先去执行callback()回调函数，但输出结果却是后输出回调函数的内容。
这就说明了主函数不用等待回调函数执行完，可以接着执行自己的代码 ( 异步，非阻塞 )。所以一般回调函数都用在耗时操作上面，比如ajax请求，文件处理等。
2、异步的概念
假定有一个需求： 全局变量a初值为0，然后过3秒后，让它为6，然后再打印出来，首先想到的写法如下：
1var a = 0; 2 3function B(x) { 4 console.
          
          
        
      </description>
    </item>
    
    <item>
      <title>丘成桐：这些会让中国科技至少倒退20年</title>
      <link>https://www.crs811.com/archives/1374/</link>
      <pubDate>Tue, 15 Jan 2019 02:41:06 +0000</pubDate>
      
      <guid>https://www.crs811.com/archives/1374/</guid>
      <description>
        
          
            丘成桐，哈佛大学终身教授、中国与全球化智库(CCG)学术专家委员会专家。
以目前的本科教育模式，国内不可能培养出一流人才，中国大学生的基础水平，尤其是修养和学风在下降。哈佛毕业生的论文水平比国内有些院士的文章都好，如果不重视学风建设，中国科技至少后退20年。
基础教育不扎实，不可能培养出一流人才
“如果不重视基础教育，以目前的本科教育模式，国内不可能培养出一流人才。”8月6日，数学大师丘成桐在北京接受记者专访时，开门见山道出了他的隐忧。
作为目前华人数学界的领袖人物，丘成桐先生不仅在学术上造诣深厚，而且十分关注国内数学人才的培养。他所在的哈佛大学近年来频繁接触国内大学及大学生，对于两国高等院校的差距，丘先生当然最有发言权。然而，通过和国内学校的直接接触，丘成桐却抛出一个让人意想不到的结论：“这些年，中国大学的基础教育存在很多问题，大学生的基础水平，尤其是修养和学风在下降。”
“有人说中国的基础教育不比美国差。但是在实践中我发现，国内大学的教育水平并非人们想象得那么高，美国的大学教育比中国好得多。研究生教育美国比中国好得更多。”
他举例说明：哈佛大学理学院每年大约招收20名念理科的中国留学生。“这些都是中国最好的学生，多数来自北大这些名校。”但是从学习成绩来看，在和其他国籍学生的比较中，“很难看出这些国内来的学生毕业成绩比来自其他国籍的学生成绩好得多。”
3年前，丘成桐招收了两个来自北大的留学生。可是这两个学生来到哈佛以后，一个学生连续三次没有通过考试，学校建议这名学生重新再念本科，还是不行，最后只好离开。另一个学生“考得也不好”，经过努力以后大有改进。
“我每年都会收到很多国内学生的推荐信。后来发现有很多是假的，是学生自己写了推荐信，然后请教授签个名，许多教授很不负责。”而且，他接触到的很多中国学生十分骄傲，不愿意用功，令他很失望。丘成桐说，10多年前，来哈佛念书的中国学生至少考试是没有问题的，但是近年来这种情况也发生了变化。“从前中国来的学生至少考试成绩在班级里占到前1/3位置，但是这些年顶多排在后1/3。当然也有好的，但是整体而言，平均水平下降了。一些甚至在国内是奥数比赛第一，但刚进来成绩也不好，经过重新训练才有好转。”
这位经验丰富的数学大师认为：这些现象都表明，是本科出了问题，学生本科没有念好。“做学问的修养等基本问题都没有得到应有的训练，而且还不用功。归根结底是本科教育不扎实。”
怪现象1：名教授不带本科生
丘成桐尖锐地指出：他发现国内高校一些“怪现象”：一些所谓的“名教授”不花时间参与本科教学。他以美国哈佛大学为例介绍，哈佛的教授数量比国内大学要少很多，数学系也就是十七八个正式教授。但是数学系每年都要开会一到两次，研究讨论本科生和研究生的学习进度，教授会花很多功夫去培养本科生。比如数学系的本科生，一年级就会根据学生情况划分不同水平，选择最好的学生去重点培养，当本科生毕业的时候，一般就会有2到3个毕业生的学术论文可以登载在第一流的杂志上。“论文水平比北京大学的教授还好。”丘成桐说。
国内名校的教授又是怎么和本科生打交道的呢？
丘成桐介绍：大概在1998年，国内有一个学生申请到哈佛大学念书，申请表上写明自己学问很高，推荐信说他是北京大学最好的学生，丘先生当时看到申请表，想既然学生这么好，来北京时就亲自和他面对面谈。结果在和北京大学20多个资深的教授座谈时，这20多个教数学的教授没有一个知道这名学生。“我还以为自己搞错了。后来有一名助理教授证实，的确有这个学生。”
“看得出来，最好的学生，20多个教授居然都没有见过。表示所谓大教授从来不参与本科生教学。”后来那个学生因为念书思路视野十分狭窄，只是考试成绩好，丘先生并没有接收他。
丘成桐认为，教授不带本科生，并非因为国内师资力量紧张。他介绍，在美国的大学，比如数学系的教授20名左右，而北大数学院的教授则大概在100多个，是美国的4到5倍，哈佛学生6400多人，北大有学生1万多人。如果按照比例，国内应该有条件让教授带本科生，提高教学质量。
为什么那些“名教授”没有时间塌实做学问？
丘成桐先生一语道破：“现在名校教授花时间不是在学术上。有些人首先到海外弄好处，捞金钱加荣誉，让外国人来评价自己，一年有3个月到5个月在国外‘走穴’。不管这个教授有没有能力，评博士点，自然基金会，甚至评某某大学这些活动都有他们的身影，至少1/3的时间用在学术交易和拉票。算起来，2/3是非学术生活。当然不愿意做学问了。”
怪现象2：一个导师带30个研究生
另一个让丘成桐先生感到困惑的现象是：现在国内有的教授，一个人居然带30个研究生。
“这样怎么保证教学质量？即便在哈佛这样的世界名校，一个教授一般带五六个学生已经很多了。国内这种做法是典型的讲量不讲质。质量粗糙，怎么可能搞好研究？
“老师自己的水平都不够，居然带30多个学生？真是糟糕！许多学生认为不用念书就可以做博士，博士论文抄抄写写，怎么可以？这样下去很危险。”
前不久在和人大附中学生交流之后，丘成桐还迫切感到中学也存在这样的问题。“目前国内很多城市中学一班有80个学生，这么多学生老师怎么能教好？不可想象。”他说，美国稍微好点的学校一个班一般不过是20多个学生。
丘成桐记忆深刻的一件事是：“大概4年前，有一个北大博士毕业写信给我，认为自己博士论文很好，希望到哈佛做教授，前后来了3次信，后来知道这人是国内某院士的学生，但我发现他的博士论文是至少70年前大家就熟悉的结果。他的论文水平也就相当于香港中文大学毕业生的水平。连香港中文大学学士的水平都不够，更不要讲哈佛了。但是对这个学生北大吹得很厉害，说他21岁就拿了博士，是个天才。但是我发现他的论文水平很低，所以坚持没有收他。”让丘成桐意想不到的是，“现在听说北大已经提升这个学生做了教授。这种事让真正做学问的人真的很失望。”
丘成桐认为，不重视本科和研究生教育的直接后果是，形成恶性循环，使整体水平慢慢压下来。“教育是长远的事情，基本的东西没有掌握，就根本没有前途。”说起这些，他十分着急。
为此，丘成桐在浙江大学成立了数学英才班，就是希望用先进的数学教学方法，比如采用了美国大学一些先进的教学方法，来培养中国学生扎实的基础能力。“选用美国的方法教并不是崇洋媚外。数学教学是没有国界的，我一定用最好的方法教中国学生。”
国内学术风气堪忧
在近年来和国内学术机构打交道的过程中，更让丘成桐忧心忡忡的是：国内学术风气已经到了必须整治不可的时候。
“学风很糟糕，我呼吁一下，如果不重视这个问题，中国科技的发展至少退后20年，如果这些基础教育不重视，问题越积越多，以后会更难。”丘成桐认为，导致教育重量不重质的原因，就是有些高校和主管部门喜欢用“文革”、“亩产万斤”的形式作为工作成绩向上汇报，却完全不考虑教育的真正使命。
为了说明整个问题的严重，丘成桐专门讲述了两个他亲身经历的例子。
“在数学界有一个很重要的数学猜想，100多年没有一个数学家不想解开它，非常重要。一个朋友在我的建议下做了很重要的第一步。1995年，我感觉时机成熟，可以再沿着已有的方向，做出有史以来第一流的成果，于是拿到中国办了一个讨论班。这个讨论班是开放式的，吸引了很多青年学者。但是后来有些参加的教授自己不想做了，因为他们考虑假如做这个事情，写文章时间就少了，而每一年写论文，创造多少文章才是他们关心的，做这种费力的事情他们觉得划不来。尽管当时有很多年轻的博士后很想念这个东西，这些教授还是不准学生继续做这个研究，怕论文数量不够。最后甚至硬性干预。自己没有学问也没有冲劲，还不允许年轻人做。最后这个本来很有希望的征服猜想的计划不了了之。”
于是，丘成桐又找到广东中山大学数学院朱院长继续做这个研究。朱做出了很好的成绩。“结果又惹恼了当时反对做这个事情的一些人，对朱很不满意。 2002年在陈省身先生和我倡议召开的世界数学大会上，大会给中国数学机构一些45分钟的演讲名额，结果他们自己定的名单全部是北京的，还有一个是上海的。其实就像奥林匹克100米比赛，朱的成绩当时是有目共睹的，但就是不容许其他地方有好处。”
还有一件事更让丘成桐耿耿于怀。
[ 详见：丘成桐与北京大学交锋事件 ]
“我的一个学生，现在做了院士，刚毕业的时候不错，以后一塌糊涂，错了不愿意改，出错的文章现在还挂在网上，表示他的成绩。
“这个人现在既是国内引进人才，又是院士，基金会什么都管，平时许多人都怕他，他的固定职位在国外，却作为引进人才，一年至少给他100万薪水，还不包括经费。但是他在好几个地方任教，有的年轻人学问比他好，但是薪水不到他的1/20，在海外名校，比如哈佛如果在9个月的授课时间里教授兼职是违法的，必须全职，但是这个人却兼了很多职。这个人做学生时还是不错，现在学问只是二流，他在国外拿的奖都是在我的帮助和指导下取得的，国内高校引进人才，给他大笔资金，可他全世界走，来一个月到三个月不等，行踪不定。
“而且严重的是，把我十几年前的文章，基本上改头换面，又据为己有，这种学风无疑误导很多学生，因为看到不用花太多时间就可以做院士。我批评他，这个人还说我荒唐可笑。真是不道德。”
丘成桐介绍，当年他花了很多功夫培养这个学生，“连我的儿子也没有下这么大功夫。太太都说我过分。”毕业那几年，哈佛一位名教授告诉丘成桐，这个学生抄袭他的论文，出于保护年轻学生的目的，丘成桐并没有深究。结果愈演愈烈。
丘先生说，这个人不光彩的记录还有很多，比如有年轻学者的文章，他看到不错，就要求把自己的名字放在真正作者的前面，如果不从，在国内就恐吓说，以后不给你研究经费，在国外则恐吓说写很差的介绍信，让作者找不到工作，导致很多搞学问的人很怕他。
“听说国内很多人怕他。学风坏到了这个地步，作为这个人的老师，我再不讲话，其他学者就不敢做事了。我有义务来澄清。”
还是这个人，在国际杂志上的一篇论文出了错，当时恰好有国内两个访问学者到丘成桐那里去，丘先生让他们解决这个错误，两个礼拜时间，进展很好，但是当丘先生说这是那个人的文章出现的问题时，“两个访问学者吓了一跳，再也不敢做了，害怕那个人打击他。你看，现在的学风有多糟糕！”
我们应该学习陈省身先生的学风
学风方面，身为数学大师陈省身的高徒，至今丘成桐仍然对恩师的学风赞不绝口，认为那才是做学问者应该遵循的方向。
“陈先生做学问也出过错，海外几个学者提出来错误，也没有办法，错了就承认。”
丘成桐介绍说，上世纪30年代，陈省身等人大学毕业到海外求学，学成后毅然全部回国，没有在海外留下，但是拿来了世界最先进的学问，当时国内许多大学互相交流，学风好得不得了。
尽管当时条件很艰苦，陈省身的数学讲义都是手写和油印，就在那种条件下，陈省身几乎看完了大部头的数学巨著。最终作出了划时代的贡献，包括华罗庚先生等人，共同训练出中国第一批数学高等人才。
就是在这些数学开拓者的努力下，当时在1946、1947年期间，中国第一批数学家出来了，即便是现在看也是世界第一流的。新中国成立以后，在华罗庚先生回国以后，陆启铿、谷超豪、王元、杨乐、张广厚、陈景润、潘承洞，这些人才相继脱颖而出。丘成桐认为，在“文革”以前，基本上中国数学已经接近世界一流。但是后来大跃进、反右，直至“文革”等历次政治运动，把这些全部破坏了。
丘先生对恩师至今念念不忘。尤其是前辈大师那种学贯中西的气质，现今已经很难看到。而丘成桐本人就具有深厚的古文功底，身边常常带一本《史记》，早年写就的一篇古文曾被人们至今记得。其中，“无奈华夏虽众长城未修，天地虽宽，瑕疵难容，终究德不如欧美，力不逮乎日苏。根之腐亦，枝叶不荣，叶之枯亦，根基何养？”更是振聋发聩。
丘成桐认为，现在中国改革开放，生活水平提高了，应该有理由在学术上作出更大的成绩。
毕生希望做成两件事
英国数学家约翰·拉慈称丘成桐是“华人数学界的领袖”。在陈省身等一代大师离世之后，重任已经落在丘成桐这代人的身上。
“领袖的工作就是确定方向。我生平立志只做好两件事情。第一，作出一等的数学研究，千古留名；第二，为中国数学教育服务，帮助中国成为数学强国。”丘成桐先生说。
“迫切的问题，是提高质量。学风要彻底改掉。”他认为，目前和国际优秀大学比较，国内仍然存在较大差距，需要迎头赶上。丘成桐饶有意味地说，“首先，中国学生素质完全可以比得上哈佛的学生。假如有好的导师和好的风气，是可以有所作为的。”但是他着重强调了“假如”两个字。
链接
丘成桐：1949年4月出生。现任美国哈佛大学教授，美国科学院院士、美国艺术与科学院院士、中国科学院首批外籍院士、俄罗斯科学院外籍院士等。
丘成桐1966年进入香港中文大学数学系。他自幼迷恋数学，经过不懈的努力，在大学三年级时就由于出众的才华被一代几何学宗师陈省身发现，破格成为美国加州大学伯克利分校的研究生，年仅22岁的丘成桐获得了博士学位。28岁时，丘成桐成为世界著名学府斯坦福大学的教授，并且是普林斯顿高级研究所的终身教授。
丘成桐教授的研究成果在国际上产生了重要影响，被国际数学大师唐纳森誉为“近四分之一世纪里最有影响的数学家”。他解决了一系列猜想和重大课题，如卡拉比猜想、正质量猜想、闵可夫斯基问题、镜猜想以及稳定性与特殊度量间的对应性等，以他的研究命名的卡拉比—丘流形在数学与理论物理上发挥了重要作用。鉴于他的杰出的贡献，1982年,年仅34岁的丘成桐教授荣获有数学诺贝尔奖之称的“菲尔兹”奖，成为迄今为止唯一荣获该奖的中国人。
他倡议与主持了一系列高水平的国际数学会议，为争取2002年在北京成功召开第“24届国际数学家大会”、“国际弦理论会议”作出了积极的努力，并通过自己的影响邀请著名物理学家霍金、威腾及“菲尔兹”奖得主等国际知名科学家前来参加，会议结束后，江/泽/民同志在百忙之中亲切会见了霍金等其他与会的世界著名数学物理学家，并对会议取得的成功表示祝贺。此次会议在国内学术界与社会上产生了重大影响，推动了中国的数学走向世界。
本文选自Mathleague，仅代表专家个人观点，不代表机构立场
          
          
        
      </description>
    </item>
    
    <item>
      <title>nodejs安装 – ubuntu 18</title>
      <link>https://www.crs811.com/archives/1360/</link>
      <pubDate>Sat, 12 Jan 2019 06:10:14 +0000</pubDate>
      
      <guid>https://www.crs811.com/archives/1360/</guid>
      <description>
        
          
            nodejs 官网：https://nodejs.org/en/download/
安装方式有两种：
1、下载编译好的二进制代码
2、下载源码编译安装
方式一 (recommand)：
step1: 下载 LTS 版本，
wget https://nodejs.org/dist/v10.15.0/node-v10.15.0-linux-x64.tar.xz step2: 解压
tar -xvf node-v10.15.0-linux-x64.tar.xz step3: 移动到保存位置，如 /opt
sudo mv node-v10.15.0-linux-x64 /opt/ step4: 改名为 node
sudo mv /opt/node-v10.15.0-linux-x64/ /opt/node step5: 修改配置文件，使命令 node 成为全局命令
vim ~/.zshrc (如果是bash，则为： vim ~/.bashrc) 末尾添加： export PATH=/data/software/node-v8.9.0-linux-x64/bin:$PATH //保存退出 step5: 使配置生效
source ~/.zshrc 测试：
方式二：
$ wget https://nodejs.org/dist/v10.15.0/node-v10.15.0.tar.gz $ sudo cp node-v10.15.0.tar.gz /usr/local/src/ $ tar xvf node-v10.15.0.tar.gz $ cd node-v10.15.0 $ ./configure $ make $ make install $ cp /usr/local/bin/node /usr/sbin/ 查看当前安装的Node的版本
          
          
        
      </description>
    </item>
    
    <item>
      <title>Manjaro 系统使用记录</title>
      <link>https://www.crs811.com/archives/1306/</link>
      <pubDate>Tue, 09 Oct 2018 01:11:08 +0000</pubDate>
      
      <guid>https://www.crs811.com/archives/1306/</guid>
      <description>
        
          
            Manjaro是一款基于Arch Linux、对用户友好、全球排名第1的Linux发行版。（排名数据源于DistroWatch，统计日期2018.03.02，时间段3个月。）
在Linux圈，Arch的确是一个异常强大的发行版。它有3个无与伦比的优势：
滚动更新可以使软件保持最新； AUR软件仓库有着世界上最齐全的Linux软件（参考《一张列表展示ArchLinux系软件有多丰富——看哭百万Debian、RedHat系同学》）； 丰富的wiki和活跃的社区让所有问题都可以快速得到满意的答案。 然而，Arch面向高级用户，缺乏技术专长或者没有耐心的人是无法顺利安装、配置Arch的。
ArchWiki上列举了ArchLinux的安装步骤，需要用户在黑色的tty界面下输入20多个命令
为了解决ArchLinux的“大bug”，Manjaro应运而生！
Manjaro基于Arch Linux，继承了Arch Linux滚动更新的特点，可以直接使用AUR上最齐全的软件。
更详细的内容，参见： https://www.manjaro.cn/
=========================================================================
ArchLinux的包管理系统: pacman
常用命令有：
pacman -Sy abc 和源同步后安装名为abc的包pacman -S abc 从本地数据库中得到abc的信息，下载安装abc包pacman -Sf abc 强制安装包abcpacman -Ss abc 搜索有关abc信息的包pacman -Si abc 从数据库中搜索包abc的信息pacman -Syu 同步源，并更新系统pacman -Sy 仅同步源pacman -R abc 删除abc包pacman -Rc abc 删除abc包和依赖abc的包pacman -Rsn abc 移除包所有不需要的依赖包并删除其配置文件pacman -Sc 清理/var/cache/pacman/pkg目录下的旧包pacman -Scc 清除所有下载的包和数据库pacman -Sd abc 忽略依赖性问题，安装包abcpacman -Su --ignore foo 升级时不升级包foopacman -Sg abc 查询abc这个包组包含的软件包pacman -Q 列出系统中所有的包pacman -Q package 在本地包数据库搜索(查询)指定软件包pacman -Qi package 在本地包数据库搜索(查询)指定软件包并列出相关信息pacman -Q | wc -l 统计当前系统中的包数量pacman -Qdt 找出孤立包pacman -Rs $(pacman -Qtdq) 删除孤立软件包（递归的,小心用)pacman -U abc.
          
          
        
      </description>
    </item>
    
    <item>
      <title>闭包的定义和作用</title>
      <link>https://www.crs811.com/archives/1292/</link>
      <pubDate>Mon, 10 Sep 2018 01:13:25 +0000</pubDate>
      
      <guid>https://www.crs811.com/archives/1292/</guid>
      <description>
        
          
            闭包定义：定义在一个函数内部的函数，静态保存所有了父级作用域的内部函数。
闭包定义：外部函数定义的内部函数就是闭包
简言之：闭包是就是函数中的函数，里面的函数可以访问外面函数的变量，外面的变量的是这个内部函数的一部分
闭包的作用：
闭包给访问外部函数定义的内部变量创造了条件，也将关于函数的一切封闭到了函数内部，减少了全局变量，这也是闭包的真实含义。
闭包的作用：
1、将函数作为参数传入另外一个函数。
2、实现封装，管理私有变量和私有方法，将变量（状态）的变化封装在安全的环境中。
3、使用闭包可以访问父级函数中的变量，并将其长期保存。
4、匿名自执行函数。在匿名自执行函数传入一个闭包函数，匿名自执行函数执行完立即销毁，可以减小内存消耗。
5、可以使变量长期保存在内存中(IncrementByTen 示例)，生命周期比较长，缺点是内存消耗大。
JS示例:
1function outer(){ 2 var num=0;//内部变量 3 return function add(){//通过return返回add函数，就可在outer函数外访问了 4 num++;//内部函数有引用，作为add函数的一部分了 5 console.log(num); 6 }; 7} 8var func1=outer();// 9func1();//实际上是调用add函数， 输出1 10func1();//输出2 11var func2=outer(); 12func2();// 输出1 13func2();// 输出2 与普通函数的区别：
1、普通函数只能曝光内部的值。方法A定义全局变量，但占用的内存无法释放且函数使用的变量定义到了函数外部不便于理解和管理。方法B将内部变量当参数传递，此种方法不美观太丑陋。
2、函数每次执行时都会且只会初始化其内部变量，导致了闭包与普通函数的最大区别。就是每次调用普通函数时它内部都被初始化成一致状态，导致执行的结果是一致的。闭包不同，它的本质是内部函数，调用闭包只会初始化内部函数变量，外部函数的变量没有被初始化，实现了变量值的传递。外部函数只在定义闭包时被初始化。闭包消亡时内存被回收。
什么时候需要使用闭包：
当每次调用函数A时都要改变全局变量B，且B只与A有关。以往没有闭包时只能将B定义为全局变量，现在可以将B定义为A的内部变量，同时在A内部定义闭包C，并将C当值返回。
          
          
        
      </description>
    </item>
    
    <item>
      <title>Python3 爬虫</title>
      <link>https://www.crs811.com/archives/1251/</link>
      <pubDate>Wed, 01 Aug 2018 07:08:53 +0000</pubDate>
      
      <guid>https://www.crs811.com/archives/1251/</guid>
      <description>
        
          
            一. 操作系统
操作系统： Windows 或 Linux均可，安装好Python运行环境，加入环境变量即可。
很Linux发行版默认为Python2，需要再安装Python3，步骤：
以CentOS7 下安装 Python3.7为例：
安装依赖包 #yum install zlib* libffi-devel -y
下载 Python-3.7.0 #wget https://www.python.org/ftp/python/3.7.0/Python-3.7.0.tgz
#tar -zxf Python-3.7.0.tgz
#cd Python-3.7.0/
安装 gcc #yum insatll -y gcc
编译，执行 #./configure --prefix=/usr/local/python3
#make
#make install
生成软链接 #ln -s /usr/local/python3/bin/pip3 /usr/bin/pip3
#ln -s /usr/local/python3/bin/python3 /usr/bin/python3/
二. 正则表达式
学习爬虫需要懂得简单的正则表达式的写法：
教程：
[零基础写python爬虫之神器正则表达式 &amp;gt;&amp;gt;][1]
三. 第三方库
BeautifulSoup BeautifulSoup是Python的一个库，最主要的功能就是从网页爬取我们需要的数据。BeautifulSoup将html解析为对象进行处理，全部页面转变为字典或者数组，相对于正则表达式的方式，可以大大简化处理过程。
安装
#pip3 install --upgrade beautifulsoup4
BeautifulSoup测试代码：
1#filename: bs4_test.py 2from bs4 import BeautifulSoup 3html = &amp;#39;&amp;#39;&amp;#39; 4&amp;lt;html&amp;gt;&amp;lt;head&amp;gt;&amp;lt;title&amp;gt;The Dormouse&amp;#39;s story&amp;lt;/title&amp;gt;&amp;lt;/head&amp;gt; 5&amp;lt;body&amp;gt; 6&amp;lt;p class=&amp;#34;title&amp;#34;&amp;gt;&amp;lt;b&amp;gt;The Dormouse&amp;#39;s story&amp;lt;/b&amp;gt;&amp;lt;/p&amp;gt; 7 8&amp;lt;p class=&amp;#34;story&amp;#34;&amp;gt;Once upon a time there were three little sisters; and their names were 9&amp;lt;a href=&amp;#34;http://example.
          
          
        
      </description>
    </item>
    
    <item>
      <title>Python 字符串操作</title>
      <link>https://www.crs811.com/archives/1246/</link>
      <pubDate>Thu, 26 Jul 2018 08:03:26 +0000</pubDate>
      
      <guid>https://www.crs811.com/archives/1246/</guid>
      <description>
        
          
            Python 字符串操作（string替换、删除、截取、复制、连接、比较、查找、包含、大小写转换、分割等）
1. 去空格及特殊符号 1s.strip() 2s.lstrip() 3s.rstrip() 4s.strip().lstrip().rstrip(&amp;#39;,&amp;#39;) 声明：s为字符串，rm为要删除的字符序列
s.strip(rm) 删除s字符串中开头、结尾处，位于 rm删除序列的字符
s.lstrip(rm) 删除s字符串中开头处，位于 rm删除序列的字符
s.rstrip(rm) 删除s字符串中结尾处，位于 rm删除序列的字符
2. 复制字符串 1#strcpy(str1,str2) 2str1 = &amp;#39;strcpy&amp;#39; 3str2 = str1 4str1 = &amp;#39;strcpy2&amp;#39; 5print str2 3. 连接字符串 1#strcat(str1,str2) 2str1 = &amp;#39;strcat&amp;#39; 3str2 = &amp;#39;append&amp;#39; 4str1 += str2 5print str1 4. 查找字符 1#strchr(str1,str2) 2# &amp;lt; 0 为未找到 3str1 = &amp;#39;strchr&amp;#39; 4str2 = &amp;#39;s&amp;#39; 5nPos = str1.index(str2) 6print nPos 5. 比较字符串 1#strcmp(str1,str2) 2str1 = &amp;#39;strchr&amp;#39; 3str2 = &amp;#39;strch&amp;#39; 4print cmp(str1,str2) 6.
          
          
        
      </description>
    </item>
    
    <item>
      <title>Ubuntu 下通过 Virtual Box 与 CentOS7 共享文件夹</title>
      <link>https://www.crs811.com/archives/1204/</link>
      <pubDate>Sat, 26 May 2018 14:40:48 +0000</pubDate>
      
      <guid>https://www.crs811.com/archives/1204/</guid>
      <description>
        
          
            环境：Ubuntu 18 下 VirtualBox + CentOS7(minimal)
目标：创建主机与虚拟机间的共享文件夹
步骤：
1、在Ubuntu中 将 VBox扩展 加入CentOS7光驱：
扩展位置：/usr/share/virtualbox/VBoxGuestAdditions.iso
2、CentOS7中安装：
#yum install update,gcc,kernel-devel,bzip2
3、将光盘挂载到CentOS7
#mkdir /mnt/cdrom
#mount /dev/cdrom /mnt/cdrom
到/mnt/cdrom 中执行：
#./VBoxLinuxAdditions.run
4、关闭CentOS7，在Ubuntu中新建/home/share文件夹作为共享的文件夹，添加到CentOS7的共享文件夹中，在VBox中设置：
Settings&amp;gt;&amp;gt;Shared Folders&amp;gt;&amp;gt;Add 给一个Folder Name，如myshare
5、打开CentOS7，挂载共享文件夹，类型为vboxsf：
#mount -t vboxsf myshare /root/share
          
          
        
      </description>
    </item>
    
    <item>
      <title>Ubuntu 22.04 优化</title>
      <link>https://www.crs811.com/archives/1011/</link>
      <pubDate>Sat, 19 May 2018 20:04:08 +0000</pubDate>
      
      <guid>https://www.crs811.com/archives/1011/</guid>
      <description>
        
          
            Ubuntu 相关软件(内网访问) &amp;gt;&amp;gt;&amp;gt;
软件：
Double commander
文件管理器，类似TC的免费开源的资源管理器软件
$sudo apt-get install doublecmd-qt1. oh my zsh : 终极Shell
(1) 安装 zsh(2) 安装 git(3) 安装 oh my zsh: #sh -c &#34;$(curl -fsSL https://raw.github.com/robbyrussell/oh-my-zsh/master/tools/install.sh)&#34;或#sh -c &#34;$(wget https://raw.github.com/robbyrussell/oh-my-zsh/master/tools/install.sh -O -)&#34;若上述命令者不能安装则可使用国内源安装 oh my zsh，执行下面3个步骤: #wget https://gitee.com/mirrors/oh-my-zsh/raw/master/tools/install.sh#chmod +x install.sh#./install.sh (4) chsh -s /bin/zsh(5) 修改在~/.zshrc文件，ZSH_THEME 设置为主题：ys，也可以设置为其他主题oh my zsh 常用插件：
(1) 命令行䃼全插件：incr-0.2 下载然后放置到 .oh-my-zsh/plugins 下，在~/.zshrc文件末尾加上source &#34;$ZSH_CUSTOM/plugins/incr-0.2.zsh&#34;(2) Zsh命令自动补全插件 zsh-autosuggestions#git clone https://github.
          
          
        
      </description>
    </item>
    
    <item>
      <title>MySQL/MariaDB数据库备份sql文件及恢复</title>
      <link>https://www.crs811.com/archives/1318/</link>
      <pubDate>Thu, 12 Apr 2018 01:05:30 +0000</pubDate>
      
      <guid>https://www.crs811.com/archives/1318/</guid>
      <description>
        
          
            数据备份
执行 mysqldump 命令：
$sudo mysqldump -u root --databases dbname --lock-all-tables --flush-logs &gt; ~/sqlfilename.sql还原数据库：
MariaDB [dbname]&gt; source ~/sqlfilename.sql
          
          
        
      </description>
    </item>
    
    <item>
      <title>后量子时代密码系统的现状</title>
      <link>https://www.crs811.com/archives/1388/</link>
      <pubDate>Mon, 22 Jan 2018 02:33:04 +0000</pubDate>
      
      <guid>https://www.crs811.com/archives/1388/</guid>
      <description>
        
          
            【后量子时代密码系统的现状】
到2017年11月30日截止日期前，NIST共收到各种后量子时代公钥密码方案82项，其中59项有关秘钥分发/加密解密，23项有关身份认证/电子签名。这些方案分别来自美国16个州和世界六大洲共25个国家。表面上看方案来自五湖四海，但实际上仍为欧美囯家所把持。中国也提交了一个方案，但与量子密码通信技术完全无关。
在提交的八十多项方案中，有些方案明显受到较多的关注，这里就让几位明日之星先亮亮相，它们都是达到抗量子攻击所必需的安全级别为128位的公钥密码。
NTRUEncrypt：这是后量子密码算法中最受关注的一位，NTRU（发音“en-true”）基于阻格数学原理。它的好处主要是内存占用低和运行速度快。缺点是涉及专利。很可惜，历史上开源项目一般都不会倾情于有专利授权的算法。
McEliece与Goppa：McEliece加密系统是目前密码界的一颗新星，它是第一个在加密过程中使用随机化的算法。它的好处是比RSA更快捷，主要缺点是密钥位数过长。典型的RSA密钥的键长是2048位，而McEliece键长达512千位！比RSA长256倍！
Ring Learning with Errors：另一个很有希望的后量子密钥分发方法是“带错的环学习”（RLWE）。它与场/集合理论中的问题有关，可以用于同态加密，这是密码界的另一个热点。
RLWE使用7,000位的密钥，比McEliece密钥短得多，与现在常用的RSA密钥长度在同一数量级。
CECPQ1: 这是密码界新杀出的一匹黑马。它是谷歌在RLWE基础上研发出了一种创新的密码算法并且作了实际测试，这是经典的椭圆曲线算法（Curve 25519）和被称为“New Hope”的RLWE变体的一种组合算法。谷歌使用一小部分Chrome浏览器和谷歌自已的服务器（可以有效地控制TLS通信的双方，谷歌做起来得心应手）测试了CECPQ1密钥分发功能。测试除了发现增加了1毫秒的延迟外，并没有发现任何其它的障碍，这可能是与密钥的大小有关。谷歌的实验已经结束，正在等待IETF的最后评判。
为后量子时代挑选合格的公钥密码有点像红楼梦剧组寻找林黛玉，在众多的美女演员中找来找去，初看个个千娇百媚，走近一看发现她们每个人都有这样哪样的瑕疵，不知天上什么时候才会掉下一个十全十美的林妹妹。
【后量子时代密码系统的展望】
2017年12月：NIST公布所有提交的新算法；2018年4月：召开第一届PQC算法标准化全会，由算法提交方作陈述，并听取专家意见，这就是本星期大会的主要内容；对第一轮候选PQC算法进行16～18个月评估和分析；2019年9月：召开第二届PQC算法标准化全会；对第二轮候选算法作出进一步评估和分析；估计在2022年或稍后，PQC算法的标准草案正式公布并开始征求意见。
          
          
        
      </description>
    </item>
    
    <item>
      <title>Latex中插入图片不失真的方法</title>
      <link>https://www.crs811.com/archives/1299/</link>
      <pubDate>Mon, 15 Jan 2018 03:00:11 +0000</pubDate>
      
      <guid>https://www.crs811.com/archives/1299/</guid>
      <description>
        
          
            首先，完成图形的绘制，流程图等（用Visio、亿图、word等）或者图表（Excel）。
然后在进行图片获得之前要确保以下几点：
1、安装Adobe Acrobat（专业版，不是阅读器），pdf编辑软件
2、将流程图等导出为 pdf 格式的文件
3、然后将上一步骤得到的pdf文件在Adobe Acrobat中打开，点击右侧“工具”中的“页面”中的“裁剪”功能进行裁剪形成只包含所绘图形的pdf格式的图片文件。
如果是Adobe Acrobat pro DC，则点击“编辑PDF”，选择顶部“裁剪页面”功能
选定双击后得到如下“设置页面框”页面，选择“裁剪框” ，确定后可得插入latex中不会失真的图像
4、找到 文件 &amp;gt;&amp;gt; 另存为，类型选择 *.eps格式
=======================================================
在latex中使用eps格式的图片：
1. 添加两个包：
\usepackage[pdftex]{graphicx} \usepackage{epstopdf} 2.举例：
\begin{figure}[!t] \centering {\includegraphics[width=0.9\linewidth]{picture.eps}} \caption{The xxxx of our scheme} \label{fig:1} \end{figure} 
          
          
        
      </description>
    </item>
    
    <item>
      <title>闭包(Closures) – js中的闭包 1</title>
      <link>https://www.crs811.com/archives/1072/</link>
      <pubDate>Wed, 03 May 2017 23:48:24 +0000</pubDate>
      
      <guid>https://www.crs811.com/archives/1072/</guid>
      <description>
        
          
            一、变量的作用域
要理解闭包，首先必须理解Javascript特殊的变量作用域。
变量的作用域无非就是两种：全局变量和局部变量。
Javascript语言的特殊之处，就在于函数内部可以直接读取全局变量。
var n=999;function f1(){alert(n);}f1(); // 999 另一方面，在函数外部自然无法读取函数内的局部变量。
function f1(){var n=999;}alert(n); // error 这里有一个地方需要注意，函数内部声明变量的时候，一定要使用var命令。如果不用的话，实际上声明了一个全局变量！
function f1(){n=999;}f1();alert(n); // 999 --------------------------------------------------------------------------------------------------------
二、如何从外部读取局部变量？
出于种种原因，我们有时候需要得到函数内的局部变量。但是，前面已经说过了，正常情况下，这是办不到的，只有通过变通方法才能实现。
那就是在函数的内部，再定义一个函数。
function f1(){n=999;function f2(){alert(n); // 999}} 在上面的代码中，函数f2就被包括在函数f1内部，这时f1内部的所有局部变量，对f2都是可见的。但是反过来就不行，f2内部的局部变量，对f1 就是不可见的。这就是Javascript语言特有的“链式作用域”结构（chain scope），
子对象会一级一级地向上寻找所有父对象的变量。所以，父对象的所有变量，对子对象都是可见的，反之则不成立。
既然f2可以读取f1中的局部变量，那么只要把f2作为返回值，我们不就可以在f1外部读取它的内部变量了吗！
function f1(){n=999;function f2(){alert(n);}return f2;}var result=f1();result(); // 999 --------------------------------------------------------------------------------------------------------
三、闭包的概念
上一节代码中的f2函数，就是闭包。
各种专业文献上的“闭包”（closure）定义非常抽象，很难看懂。我的理解是，闭包就是能够读取其他函数内部变量的函数。
由于在Javascript语言中，只有函数内部的子函数才能读取局部变量，因此可以把闭包简单理解成“定义在一个函数内部的函数”。
          
          
        
      </description>
    </item>
    
    <item>
      <title>文件编码处理</title>
      <link>https://www.crs811.com/archives/1064/</link>
      <pubDate>Wed, 26 Apr 2017 02:48:30 +0000</pubDate>
      
      <guid>https://www.crs811.com/archives/1064/</guid>
      <description>
        
          
            Windows 中文版 默认GBK
Linux 默认UTF-8
从Windows 拷贝到Linux的文件, 中文 在命令 cat , grep下是乱码：
cat:
grep:
vim:
1.在Vim中查看文件编码
:set fileencoding 即可显示文件编码格式。
如果只是想查看其它编码格式的文件或者想解决用Vim查看文件乱码的问题，那么可以在
~/.vimrc 文件中添加以下内容：
set encoding=utf-8 fileencodings=ucs-bom,utf-8,cp936 这可以让vim自动识别文件编码（可以自动识别UTF-8或者GBK编码的文件），其实就是依照fileencodings提供的编码列表尝试，如果没有找到合适的编码，就用latin-1(ASCII)编码打开。
2. enca (如果你的系统中没有安装这个命令，可以用#** yum install -y enca** 安装 )查看文件编码
$ enca filenamefilename: Universal transformation format 8 bits; UTF-8CRLF line terminators需要说明一点的是，enca对某些GBK编码的文件识别的不是很好，识别时会出现：
Unrecognized encoding 3. 编码转换
方法1.在Vim中直接进行转换文件编码,比如将一个文件转换成utf-8格式
:set fileencoding=utf-8 方法2. enconv 转换文件编码(安装enca)，比如要将一个GBK编码的文件转换成UTF-8编码，操作如下
enconv -L zh_CN -x UTF-8 filename 方法3. iconv 转换，iconv的命令格式如下：
iconv -f encoding -t encoding inputfile 比如将一个UTF-8 编码的文件转换成GBK编码
          
          
        
      </description>
    </item>
    
    <item>
      <title>JavaScript – new</title>
      <link>https://www.crs811.com/archives/1057/</link>
      <pubDate>Sun, 16 Apr 2017 00:29:05 +0000</pubDate>
      
      <guid>https://www.crs811.com/archives/1057/</guid>
      <description>
        
          
            造一个士兵
var 士兵 = {ID: 1, // 用于区分每个士兵兵种:&#34;美国大兵&#34;,攻击力:5,生命值:42, 行走:function(){ /*走俩步的代码*/},奔跑:function(){ /*狂奔的代码*/ },死亡:function(){ /*Go die*/ },攻击:function(){ /*糊他熊脸*/ },防御:function(){ /*护脸*/ }}兵营.制造(士兵)如果需要制造 100 个士兵怎么办呢？
循环 100 次吧：
var 士兵们 = []var 士兵for(var i=0; i&lt;100; i++){士兵 = {ID: i, // ID 不能重复兵种:&#34;美国大兵&#34;,攻击力:5,生命值:42, 行走:function(){ /*走俩步的代码*/}，奔跑:function(){ /*狂奔的代码*/ },死亡:function(){ /*Go die*/ },攻击:function(){ /*糊他熊脸*/ },防御:function(){ /*护脸*/ }}士兵们.
          
          
        
      </description>
    </item>
    
    <item>
      <title>JavaScript – this</title>
      <link>https://www.crs811.com/archives/1053/</link>
      <pubDate>Sun, 16 Apr 2017 00:21:25 +0000</pubDate>
      
      <guid>https://www.crs811.com/archives/1053/</guid>
      <description>
        
          
            做题：
var obj = {foo: function(){console.log(this)}}var bar = obj.fooobj.foo() // 打印出的 this 是 objbar() // 打印出的 this 是 windowJS（ES5）里面有三种函数调用形式：
func(p1, p2)obj.child.method(p1, p2)func.call(context, p1, p2)第三种调用形式，才是正常调用形式：
func.call(context, p1, p2)其他两种都是语法糖，可以等价地变为 call 形式：
func(p1, p2) 等价于func.call(undefined, p1, p2)obj.child.method(p1, p2) 等价于obj.child.method.call(obj.child, p1, p2)函数调用只有一种形式：
func.call(context, p1, p2)this，就是上面代码中的 context。
当写下面代码时
function func(){console.log(this)}func()等价于
function func(){console.log(this)}func.
          
          
        
      </description>
    </item>
    
    <item>
      <title>H5&#43;:  Hybrid App 开发</title>
      <link>https://www.crs811.com/archives/1042/</link>
      <pubDate>Thu, 13 Apr 2017 18:06:17 +0000</pubDate>
      
      <guid>https://www.crs811.com/archives/1042/</guid>
      <description>
        
          
            开发方式对比：H5、React Native、Native应用对比分析
原文：http://uikoo9.com/blog/list
Hybrid App（混合模式移动应用）是指介于web-app、native-app这两者之间的app，兼具“Native App良好用户交互体验的优势”和“Web App跨平台开发的优势”。
HPP hybirdApp或者hbuilderApp，
指通过html，css，js语言开发出ios和android两个版本的APP，
开发效率成倍上升，开发时间大幅缩减，开发成本同样也大大缩减。
移动互联网时代，还有多少中小公司没有自己的app，原因何在？ 1.中小公司有多少？ 这个都不需要引用相关数据，想想一句话就明白了，
“一将功成万骨枯”，这句话同样适合创业者，普通人耳熟能详的大公司已经很多了，
可以想象下中小公司有多少，数量极多极多。
2.大部分中小公司没有自己app 迫于app开发人员的用人成本极高，
初级android，ios工资基本10k左右，中级15k左右，高级25k左右，大概这个价，
中小公司找两个初级的做不出东西，找两个中级的差不多了，但是时间成本用人成本都很高，
最终的结果是只能做出一个demo类的app，或者计划一直往后拖，
又或者根本没有能力招app开发~
HPP，让所有中小公司轻松拥有自己的APP 1.成本比较 拿开发一个app，需要6个月，android，ios两个版本，
配备andorid中级（15k）+ios中级（15k）来说，成本是30*6=180k=18w，
配备一个hpp中级（15k）来说，成本是15*3=45k=4.5w，
这里是乘以3不是乘以6，因为hpp开发速度绝对比原生开发快一倍。
这样一来，
hpp开发app的成本是原生app的四分之一~
hpp开发app的成本是原生app的四分之一~
hpp开发app的成本是原生app的四分之一~
2.招人难度 android和ios的工资这么高（相对其他工种），原因之一就是招人比较难，
而hpp开发，只要会html+css+js就可以，
想想哪个java开发，php开发，.net开发不会点html+css+js，只需要在精通点，
想想哪个前端开发，不精通html+css+js呢，
所以招人来说，完成原生app
3.流畅度和加载速度 很多人会说流畅度，
随着手机厂商的竞争，手机硬件的发展，想想现在的千元小米，魅族之流，
目前来说千元机都很流畅，以后来说是手机就很流畅。
很多人说加载速度，
诚然，中小公司自己的带宽限制等等因素，加载页面比较满，
但是想想网络发展，从2g，3g，4g以及之后的5g，以及wifi的adsl，光纤，512k，1m，2m，10m，20m，
以及现在越来越普及的云服务，百度bae，新浪sae，阿里云等等，
网速也不是问题了。
HPP详述 1.HPP由来 其实用html+css+js本人用得比较多的是dcloud（公司）推出的hbuilder（ide），使用mui（ui）+nativejs开发app，
但是总这么hbuilder，mui的叫，感觉不是很顺口，或者不是很响亮，
百度上说基于html+css+js开发app的技术叫做HybirdApp，详见：这里
所以借用HybirdApp和Hbuilder开发的App这两个概念，推出HPP的叫法，
简单，好记。
2.HPP案例 说了这么多，如果你已经心动了，不妨看看这些HPP案例，
http://dcloud.io/case/#group-1
可以看出，HPP开发app本身流畅度是毫无问题，问题在于ui设计太low，一下子拉低档次，
如果有一个好的ui，外加一下开发的技巧，开发出的app还是很棒的，例如“爱学车”这个HPP。
3.HPP趋势如何 硬件趋势：手机硬件性能越来越好，
网络趋势：网速越来越快，
就业趋势：12年错过了android的你，15年还想错过HPP？
疑问解答 1.一次开发，生成android和ios两种app？ 是的
2.需要熟悉哪里技术才可以从事HPP开发？ 需要熟悉html，css，js，最好熟悉jquery，以及一些常用框架的上手方法（bootstrap，amazeui）。
3.具体使用哪些技术工具？ 使用Hbuilder做ide进行开发打包app，
          
          
        
      </description>
    </item>
    
    <item>
      <title>vagrant简介</title>
      <link>https://www.crs811.com/archives/984/</link>
      <pubDate>Thu, 30 Mar 2017 01:02:10 +0000</pubDate>
      
      <guid>https://www.crs811.com/archives/984/</guid>
      <description>
        
          
            一、Vagrant介绍 ​　Vagrant是一个基于Ruby的工具，用于创建和部署虚拟化开发环境。它 使用Oracle的开源VirtualBox虚拟化系统，使用 Chef创建自动化虚拟环境。我们可以使用它来干如下这些事：
建立和删除虚拟机 配置虚拟机运行参数 管理虚拟机运行状态 自动配置和安装开发环境 打包和分发虚拟机运行环境 ​　Vagrant的运行，需要依赖某项具体的虚拟化技术，最常见的有VirtualBox以及VMWare两款，早期，Vagrant只支持VirtualBox，后来才加入了VMWare的支持。
​ 为什么我们要选择Vagrant呢？因为它有跨平台、可移动、自动化部署无需人工参与等优点。
在Vagrant体系中，有个box(箱子)的概念，这优点类似于docker体系中的image(镜像)。基于同一个box，不同的人可以运行得到相同的内容。
三、Vagrant环境的安装 ​　因为vagrant依赖virtualbox，所以需要在安装vagrant之前先安装virtualbox
1. 下载并安装virtualbox 下载地址：https://www.virtualbox.org/wiki/Downloads
安装过程很简单，傻瓜式的一步一步点下去。
2.下载并安装vagrant 下载地址：https://www.vagrantup.com/downloads.html
安装过程依旧没什么难的，跟着提示一步一步next。
注意：下载的时候，virtualbox和vagrant的版本要搭配，建议都下载最新版的。还有就是要根据自己的操作系统版本进行选择32位或者64位下载。在windows系统中，可能还需要配置环境变量以及一定要开启VT-x/AMD-V硬件加速。
四、Vagrant基本命令 1. vagrant box基本命令 列出本地环境中所有的box vagrant box list添加box到本地vagrant环境 vagrant box add box-name(box-url)更新本地环境中指定的box vagrant box update box-name删除本地环境中指定的box vagrant box remove box-name重新打包本地环境中指定的box vagrant box repackage box-name在线查找需要的box官方网址：https://app.vagrantup.com/boxes/search 2. vagrant基本命令 在空文件夹初始化虚拟机 vagrant init [box-name]在初始化完的文件夹内启动虚拟机 vagrant upssh登录启动的虚拟机 vagrant ssh挂起启动的虚拟机 vagrant suspend重启虚拟机 vagrant reload关闭虚拟机 vagrant halt查找虚拟机的运行状态 vagrant status销毁当前虚拟机 vagrant destroy五、Vagrant高级功能 1.
          
          
        
      </description>
    </item>
    
    <item>
      <title>解决 CodeBlocks 编译 pbc 的问题</title>
      <link>https://www.crs811.com/archives/1002/</link>
      <pubDate>Wed, 29 Mar 2017 19:22:37 +0000</pubDate>
      
      <guid>https://www.crs811.com/archives/1002/</guid>
      <description>
        
          
            安装好CPABE后，有两种方法编辑 c
1、用vim/gedit 编辑运用pbc方法的c文件（如lbs.c）
在命令行通过如下命令编译生成可执行文件：
$ gcc -o lbs lbs.c -L. -lpbc -lgmp 2、用IDE(如codeblocks)编辑调试
但用codeblock编译时，会有一堆错误：
undefined reference to __gmpz_init
undefined reference to __gmpz_clear
undefined reference to pbc_die
undefined reference to element_printf
...
原因是没有链接库，命令可以加 -lpbc -lgmp，IDE则需要手动添加三个文件到Project Option &amp;gt; debug &amp;gt; linker setting中：
/usr/local/lib/libgmp.a/usr/local/lib/libgmp.so/usr/local/lib/libpbc.a编译成功：
命令行运行：
          
          
        
      </description>
    </item>
    
    <item>
      <title>1&#43;1&gt;2:用Docker和Vagrant构建简洁高效开发环境</title>
      <link>https://www.crs811.com/archives/986/</link>
      <pubDate>Wed, 29 Mar 2017 17:07:40 +0000</pubDate>
      
      <guid>https://www.crs811.com/archives/986/</guid>
      <description>
        
          
            Docker和Vagrant经常被认为是两种相互替代的工具，其实它们可以结合使用，构建隔离的、可重复的开发环境。我们将证明该环境可以构建一个Docker容器以便开发Java应用程序，并充分利用Vagrant的强大功能，以解决一些现实当中的实际问题。
这篇博客的第一部分探讨了开发环境的常见缺陷、简单Docker环境的构建以及Vagrant+Docker配置具有的优点。但是如果你想就开始使用Docker和Vagrant，不妨直接跳到本文的这个章节：使用Vagrant，让Docker容器易于移植。 开发环境有什么问题?
要花很长的时间来构建
新的开发人员要花多长时间才能构建好当前项目的开发环境?答案取决于诸多因素(项目时间、从事该项目的开发人员数量等)，但至少需要半天时间并不罕见。
嘿!其实应该比这快得多：查看脚本，执行脚本。就是这样。这两个步骤应该足以构建你的环境，并准备随时开发。
它可能与测试环境和生产环境大不一样
你有没有因构建的环境在机器上未通过而跳过自动化测试?或者更糟糕的是，即使更改的内容在机器上顺利编译，但是在持续整合(CI)服务器上老是失败，你有没有查过问题的根源出在哪里?
任何稍有不同，就会导致意料不到的行为。有的方法可能很简单，比如试一试框架的上一个版本，或者改用不同的项目。
查明什么导致你的系统出现不同行为是每个开发人员都应该避免的烦人任务。
虚拟机和Docker
因而，开发环境应该具有两个特点：
隔离：你不希望在测试某个新工具或不同项目时弄得一团糟。
可重复：同一个环境应该在每个团队成员的机器、持续整合服务器和生产服务器上都一再可复制。
虚拟机环境确保了这些特性，可是典型的虚拟机很耗费资源。开发人员需要每隔几分钟编码/构建/测试，不会接受虚拟化带来的开销。
这时候，Docker显得大有帮助。相比典型的虚拟机，其轻型容器极其快速，而且在开发人员当中极受欢迎。下面是来自Docker博客的一段摘要，解释了这种成功的原因：
在问世后的头12个月内，Docker在初创企业和早期采用者当中迅速流行起来，他们重视该平台的这一功能，即可以将应用程序开发管理的问题与基础设施提 供、配置和运营的问题分离开来。Docker为这些早期用户提供了一种新颖的、更迅速的方法，可以构建分布式应用程序，另外提供了一种“编写一次到处运 行”的部署选择，部署对象从笔记本电脑、裸机、虚拟机到私有云/公有云，不一而足。
使用Docker来配置的、可重复的开发环境
为了举例说明，我们将构建一个构建并测试Vert.x HTTP服务器的Docker容器。
Vert.x是一种轻型应用程序框架，鼓励小型、独立微服务的架构。微服务“就是一种小巧的独立式可执行程序，可与其他的独立式可执行程序进行沟通”(Uncle Bob，http://blog.cleancoder.com/uncle-bob/2014/09/19/MicroServicesAndJars.html)。我们认为，它在Docker容器中再合适不过了，这就是为什么我们在此选择它作为例子。
要是你之前还没有安装过Docker，先安装它。你可以参阅官方文档(https://docs.docker.com/installation/)，或者使用get docker script(https://get.docker.io)来安装它。我们假设在本章节中，我们在Linux上运行。即使Docker也可以安装到Windows和Mac上(借助boot2docker)，我们会在下一章中看到如何使用Vagrant来安装、为什么Vagrant是一种更好的选择。
Docker文件(Dockerfile)
为了描述容器，我们需要一个Docker文件：
FROM ubuntu:14.04
# 安装开发工具：jdk和git等
RUN apt-get update RUN apt-get install -y openjdk-7-jdk git wget
# jdk7是默认JDK
RUN ln -fs /usr/lib/jvm/java-7-openjdk-amd64/jre/bin/java /etc/alternatives/java
# 安装vertx
RUN \ mkdir -p /usr/local/vertx &amp;amp;&amp;amp; cd /usr/local/vertx &amp;amp;&amp;amp; \ wget http://dl.bintray.com/vertx/downloads/vert.x-2.1.2.tar.gz -qO - | tar -xz
# 将vertx添加到路径
          
          
        
      </description>
    </item>
    
    <item>
      <title>Docker生产环境架构讨论</title>
      <link>https://www.crs811.com/archives/975/</link>
      <pubDate>Wed, 29 Mar 2017 10:38:07 +0000</pubDate>
      
      <guid>https://www.crs811.com/archives/975/</guid>
      <description>
        
          
            讲师：方云麟，就职于网宿科技，负责docker集群的架构设计以及项目推进。兴趣：docker、传统虚拟化、golang
大家好，我是云麟。我今天和大家交流docker以及kubernetes。我们先讲下docker。
docker的特性是什么？
这个网上很多。我就不复制粘贴了。
我总结下我觉得比较好的几个特性
一键部署，部署原子化：我们可以狭隘的把 docker 理解成是一个应用打包解决方案：把运维环境、代码进行打包，在部署的时候，只需要载入该镜像，则服务被运行起来。这个过程是原子化的，所以很大程度避免了部署过程中人为或者不可预料的意外。同时也大大加快了部署过程，基本上可以在1分钟内部署好一个业务，因此也具有很大的弹性扩展优势。
隔离和性能：docker专注于隔离，并且镜像是只读的。于是提高了业务的安全性——复用主机的各业务之间，一旦被黑，影响的因素会少很多。并且 docker 仅仅做了隔离，并不虚拟硬件，所以和虚拟机比，没有虚拟化带来的性能消耗。
网上曾经有文章爆说docker有安全问题，官方registry镜像仓库，1/3镜像有安全漏洞。
我觉得这是有道理的。但是，哪个原始系统没漏洞？所以这时候问题就在于我们操作了。
我在正式环境中，都是要把系统更新到最新的。修复若干bug。
复用宿主机内核：docker 并不是虚拟机，仅仅是进程等资源的隔离，因此并没有独立的内核，所有进程都是复用宿主机内核。 这三点，是我认为docker比较显著的特性。
大家可以把docker的业务部署，狭隘的理解成是苹果的 app store。我要运行什么业务，一键下载运行，不需要我们去make config 等等。
也就是说，我认为docker更亲和于面向业务。
而不是面向部署细节的纠结（当然，需要镜像打包人员去纠结。）
有哪些公司已经把 docker 应用到生产环境呢？
我来出卖下一个队友。
福州的17173。80后还有70后，调皮的同学应该都多少有接触，游戏攻略网站。
此外，京东。
特别要指出 docker 分享了 618 大促的案例：http://www.infoq.com/cn/news/2015/06/jd-618-docker/ 很鼓舞人心。
京东用docker的弹性伸缩的支持性，抗住了618大促。
这里有么有jd的同学，来辟谣下？
当前，国内已经有把docker做成产品的服务商，很多细节已经不用我们烦恼了（如果你不介意把业务放在别人家里）
从这个角度，是可以省掉中小公司很多技术开支的。
灵雀云 – http://www.alauda.cn
时速云 – https://www.tenxcloud.com
希云 – https://csphere.cn
这是三家docker服务商，都提供了docker运行平台，还有镜像。
这里不一定有jd的人，但是一定有这三家的人，有木有？
我建议，有兴趣的可以去这三个网站看看，都可以免费试用的。
这是从0到1的比较好的了解方式，我是这么认为的。
希云有几个不错的 docker 入门视频，大家可以看看：https://csphere.cn/training
感谢一下希云的同学。
不只一个人问我，docker要直接运行在虚拟机里好呢，还是运行在物理机上好。
我是这么想的
docker 专注于环境隔离，并非一个完全的虚拟机产品。
docker 不具有内存状态迁移特性，即使是所谓迁移，也仅仅是在另一台机器运行同一个镜像而已。如果在 docker 外部包一层虚拟机，则可以提供内存热迁移特性。
但是如果和虚拟机结合，则丧失了 docker 相对于虚拟机的性能优势。
这就是业务和性能的一个平衡博弈。
重要的事情将三遍：docker不是虚拟化。docker不是虚拟化。docker不是虚拟化。
          
          
        
      </description>
    </item>
    
    <item>
      <title>Kubernetes系统架构简介</title>
      <link>https://www.crs811.com/archives/982/</link>
      <pubDate>Tue, 28 Mar 2017 16:58:25 +0000</pubDate>
      
      <guid>https://www.crs811.com/archives/982/</guid>
      <description>
        
          
            作者 杨章显 Kubernetes作为Docker生态圈中重要一员，是Google多年大规模容器管理技术的开源版本，是产线实践经验的最佳表现[G1] 。如Urs Hölzle所说，无论是公有云还是私有云甚至混合云，Kubernetes将作为一个为任何应用，任何环境的容器管理框架无处不在。正因为如此， 目前受到各大巨头及初创公司的青睐，如Microsoft、VMWare、Red Hat、CoreOS、Mesos等，纷纷加入给Kubernetes贡献代码。随着Kubernetes社区及各大厂商的不断改进、发展，Kuberentes将成为容器管理领域的领导者。
接下来我们会用一系列文章逐一探索Kubernetes是什么、能做什么以及怎么做。
2. 什么是Kubernetes Kubernetes是Google开源的容器集群管理系统，其提供应用部署、维护、 扩展机制等功能，利用Kubernetes能方便地管理跨机器运行容器化的应用，其主要功能如下：
使用Docker对应用程序包装(package)、实例化(instantiate)、运行(run)。
以集群的方式运行、管理跨机器的容器。
解决Docker跨机器容器之间的通讯问题。
Kubernetes的自我修复机制使得容器集群总是运行在用户期望的状态。
当前Kubernetes支持GCE、vShpere、CoreOS、OpenShift、Azure等平台，除此之外，也可以直接运行在物理机上。
接下来本文主要从以下几方面阐述Kubernetes：
Kubernetes的主要概念。
Kubernetes的构件，包括Master组件、Kubelet、Proxy的详细介绍。
3. Kubernetes主要概念 3.1. Pods Pod是Kubernetes的基本操作单元，把相关的一个或多个容器构成一个Pod，通常Pod里的容器运行相同的应用。Pod包含的容器运行在同一个Minion(Host)上，看作一个统一管理单元，共享相同的volumes和network namespace/IP和Port空间。
3.2. Services Services也是Kubernetes的基本操作单元，是真实应用服务的抽象，每一个服务后面都有很多对应的容器来支持，通过Proxy的port和服务selector决定服务请求传递给后端提供服务的容器，对外表现为一个单一访问接口，外部不需要了解后端如何运行，这给扩展或维护后端带来很大的好处。
3.3. Replication Controllers Replication Controller确保任何时候Kubernetes集群中有指定数量的pod副本(replicas)在运行， 如果少于指定数量的pod副本(replicas)，Replication Controller会启动新的Container，反之会杀死多余的以保证数量不变。Replication Controller使用预先定义的pod模板创建pods，一旦创建成功，pod 模板和创建的pods没有任何关联，可以修改pod 模板而不会对已创建pods有任何影响，也可以直接更新通过Replication Controller创建的pods。对于利用pod 模板创建的pods，Replication Controller根据label selector来关联，通过修改pods的label可以删除对应的pods。Replication Controller主要有如下用法：
Rescheduling 如上所述，Replication Controller会确保Kubernetes集群中指定的pod副本(replicas)在运行， 即使在节点出错时。
Scaling 通过修改Replication Controller的副本(replicas)数量来水平扩展或者缩小运行的pods。
Rolling updates Replication Controller的设计原则使得可以一个一个地替换pods来rolling updates服务。
Multiple release tracks 如果需要在系统中运行multiple release的服务，Replication Controller使用labels来区分multiple release tracks。
3.4. Labels Labels是用于区分Pod、Service、Replication Controller的key/value键值对，Pod、Service、 Replication Controller可以有多个label，但是每个label的key只能对应一个value。Labels是Service和Replication Controller运行的基础，为了将访问Service的请求转发给后端提供服务的多个容器，正是通过标识容器的labels来选择正确的容器。同样，Replication Controller也使用labels来管理通过pod 模板创建的一组容器，这样Replication Controller可以更加容易，方便地管理多个容器，无论有多少容器。
          
          
        
      </description>
    </item>
    
    <item>
      <title>Linux0.01内核源代码及注释</title>
      <link>https://www.crs811.com/archives/973/</link>
      <pubDate>Tue, 28 Mar 2017 04:42:29 +0000</pubDate>
      
      <guid>https://www.crs811.com/archives/973/</guid>
      <description>
        
          
            Linux0.01内核源代码
Linux0.01内核源码注释
《Linux0.01_内核分析与操作系统设计》
          
          
        
      </description>
    </item>
    
    <item>
      <title>systemd 与 sysVinit 彩版对照表</title>
      <link>https://www.crs811.com/archives/969/</link>
      <pubDate>Mon, 27 Mar 2017 05:01:36 +0000</pubDate>
      
      <guid>https://www.crs811.com/archives/969/</guid>
      <description>
        
          
            Linux作者Linus Torvalds在许多事情上以其鲜明的立场著称，但对于颇受争议的初始化系统Systemd，Torvalds的立场却是中立的。iTWire采访了Linux之父， 询问了Systemd、Git和IT教育等方面的问题。Torvalds说，他对Systemd没有特别的看法，事实上他的笔记本和台式机都运行 Systemd。Torvalds指出，传统的Unix哲学“程序应该只关注一个目标，并尽可能把它做好”并不是现实的反映，除非工作是流水线式的，复杂 系统很早就不采用“做一件事而且把它做得很好”的Unix模型。Unix的简化哲学在某种程度上仍然有用，但显而易见的是它没有真的描述多数的现实。对于 Git，他称核心部分没发生多少变化，他所惊讶的是它的流行。他认为平板是一种纯消费工具，认为教育的真正问题不是是否缺乏IT教育，而是优秀的教师。 Torvalds不称自己是项目经理，而是了解技术的技术负责人。
systemd是一个init程序。根据之前 Upstart的一些介绍大家应该简要了解了传统Sysvinit系统的不足之处。不过，这次的systemd的设计思想更为超前，也可以说是借鉴了OSX上launchd的思路。
          
          
        
      </description>
    </item>
    
    <item>
      <title>Python、Lua 和 Ruby</title>
      <link>https://www.crs811.com/archives/913/</link>
      <pubDate>Tue, 21 Mar 2017 07:46:26 +0000</pubDate>
      
      <guid>https://www.crs811.com/archives/913/</guid>
      <description>
        
          
            Python
1、站在解决问题的角度上看。python依靠自身越来越强大的库，让编程者能实现越来越多，越来越复杂的问题。lua本身则必须与其它的编译语言结合，才能解决问题。以C+++lua来举例。单独的C++，因为C++的复杂性，在其解决问题提供方便的同时，也给程序员带来了很大的麻烦，这些麻烦主要有两个方面：1，C++本身，特别是能用好C++，对程序员就来说就是一个很高的要求。2,在解决复杂问题时，C++程序结构的复杂性和逻辑实现的复杂性，给程序员对程序的改进和维护带来了很大的麻烦。而C++与Lua的结合，让C++可以只负责为lua提供各种基本的功能函数库，而Lua调用这些库来实现各种逻辑功能。这种分工可以让程序员将程序中的基本代码库和逻辑实现代码进行分离，使程序的效率和可维护有了很大的提高。所以，如果真的要站在解决问题的角度来对python和lua进行对比的话。实际上，是C++与python进行对比，而与lua无关。
2、python与C++对比，python与C++对比的优势就在于其所提供的基本库，大大的降低了程序复杂度与可维护性对程序员本身的要求。比如，同样的功能，如果是C++来做的话，可能其程序员必须具备三年的经验，如果是python来做，而python又有解决问题所需要的库的话，一个具有一年程序经验的程序员可能就能完成了。但是，同样的，如果是C++与Lua结合来解决问题的话，可能就只需要半个高级程序员和一个只有c语言一年经验的程序员就可以了。半个高级程序员负责提供lua的函数库，另一个程序员，只需要用这些代码库实现逻辑就行了。
综上所述，C+++lua的开发模式，和python源代码库开发+python脚本开发模式其实是一样的。但是站在程序员的角度上来说，C+++lua就更为简单一些，因为除去基本的lua解释代码外，C++可以为lua动态提供各种函数库。而python程序员则必须受制于python所提供的各种功能库。所以，如果解决一些具有普遍性和重复性的问题时，python是有优势的，因为有很多的代码可以不用重写，而C+++lua则必须重构。如果是解决一些非普遍的问题，如果python本身没有提供解决这些问题的库的话，python程序员，就必须走回C++的老路了，哈哈。
Python的优点：
1、Python比其它语言有更多扩展模块。
2、在网上可以找到很多Python教程。不仅如此，还有大量的英文书籍和资料。Python.org有很多为初学者准备的依主题组织的资料、教程和编程指南，此外还有很多链接和参考。
3、很多人都喜欢Python语言的语法，因为它清晰易读。
4、Python在支持库上大占优势，因为它有很多库，而且大部分都有完善的文档支持。
5、很多工具可以用于Python，但难以找到适用于Lua和Ruby的。
Python的不足：
1、现有的Python调试器诡异而且效率低下。在Macintosh（苹果计算机）和控制台下进行调试是一个梦魇。
2、Python难以与其它语言集成，它有太多的二进制DLL，而且Python带了巨大的标准发布包。
3、同样的，也有很多人不喜欢Python对空白符敏感的语法。
4、因为栈上的任何东西都是对象，所以Python有时候会慢得难以忍受。
Luain
Lua 是一种轻量小巧的脚本语言，用标准C语言编写并以源代码形式开放， 其设计目的是为了嵌入应用程序中，从而为应用程序提供灵活的扩展和定制功能。
Lua号称性能最高的脚本，用在很多需要性能的地方，比如：游戏脚本，nginx，wireshark的脚本
Lua 在游戏编程领域被广泛运用
Lua的优点：
1、Lua在这三种语言中是运行时速度最快而且占内在最少的
2、集成Lua只会增加极少的内存占用率。
3、Lua的C API有着完备着文档和很好的例子，可以容易地通过C集成在软件里。
Lua的不足：
1、尽管Lua的文档已经增进不少，但仍然有所不足。三种语言中，Lua可能是文档最少的（API方面是个例外），因为代码中极少注释，这也增加了学习的难度。另外，对Lua的本质也没有什么介绍。
2、 Lua内建的功能很少，并没有对创建大型的复杂应用程序提供足够支持。
3、 Lua应该使用更好的垃圾收集机制，Lua现在的GC仍然使用非常简单而且传统的“标记和清除”方式。
Rudy
Ruby 是一种开源的面向对象程序设计的服务器端脚本语言
Ruby的优点：
1、Ruby有极好的高级调试器。
2、Ruby是最彻底的面向对象语言，对于OOP狂热者和惯于使用OOP范式的程序员，他们将会发现Ruby是最适合他们的语言。
3、 Ruby的语法极为简单，没有让人出乎意料规则，特别适合OOP行家的习惯。
Ruby的不足：
1、英文文档极度缺乏。
2、与其它语言相比，在游戏方面所作的工作和实例都少得多。
          
          
        
      </description>
    </item>
    
    <item>
      <title>hash碰撞，生日攻击</title>
      <link>https://www.crs811.com/archives/1183/</link>
      <pubDate>Sat, 11 Mar 2017 02:19:18 +0000</pubDate>
      
      <guid>https://www.crs811.com/archives/1183/</guid>
      <description>
        
          
            这里有一个合同交易的故事。
假设Bob和Alice在谈一桩生意。最后两人把价格谈好了，100万美元。Bob为Alice起草了一份合同，合同的内容就是Alice从Bob那里以100万美元的价格买下一件产品。
按照通常的程序，如果双方都同意一份合同有效，这份合同就会先用一个安全系数很高的hash函数映射到一串长度为n的二进制值（也就是说hash值的理论个数为2^n）。然后Alice和Bob对这个hash值进行数字签名(digital signature)。
一个hash函数的特点就是可以把任意长度的文档（或二进制串，以下直接称文档）映射到长度为n的二进制值，这种映射是多对一和单向的。安全性好的hash函数H应当具备以下三个特点：
给定任意一个二进制串b，找到hash之前的文档t（也就是说使得H(t)=b）非常困难。这里的困难指的是如果用计算机枚举，将会花费大把时间，基本上在允许的时间范围内不可行。 给定任意一个文档 t1，找到另外一个文档 t2，使得用hash函数之后得到的两个二进制值相同（H(t1)=H(t2)）非常困难。 找到t1和t2，使得H(t1)=H(t2)非常困难。这个条件也称为hash碰撞。
由于密码学中的hash函数具有以上特点，人们经常对文档应用hash函数，用hash值来证明文档的存在性。
比如一个科学家在某个时间点发现了自然界一个重大规律，但是他又不想把这个规律公开给全世界，同时他得证明他确实发现了这个东西并记录到了一个文档中，防止今后有人发现同样的规律被抢了成果。那么他就可以对自己的文档应用hash函数，然后把hash值在某个时间点公布。以后有人要他证明之前已经发现了这个规律，他可以把自己的文档再用相同的hash函数求值，如果得到的hash值和之前公布的值一样，说明他的确很早以前发现了这个规律。这种技术称为time-stamp，在学术界应用广泛，比如上传到arxiv的文章都会关联到一个time-stamp。这种技术行得通的一个很重要原因就是从某个文档得到的hash值通常情况下只有再对这个文档应用hash函数才能得到相同的值。虽然理论上肯定有其他文档也具有同样的hash值，但是找到那些文档的计算复杂度相当高以至于基本不可行。 回到问题中，假如Bob和Alice暂时不想公开合同的内容（如果以后需要第三方的公证），他们就可以在合同的hash值上签字。合同的任何一方持有者可以对合同应用hash函数从而证明合同的合法性。
但是现在贪财而邪恶的Bob想骗取Alice为这件产品签下价格为1000万美元的合同。Bob目前手头有一台牛逼的计算机，他愿意付出O(2^(n/2))的计算时间去赢取那额外的900万美元（注意n是hash值的二进制长度）。而且实际情况是，Bob成功的机会非常高。那么他会怎么做？
现在暂时跳出这个问题，我们来看看怎样攻击hash函数的第三个特点。第三个特点比前面两个条件都宽松了许多，因为前面两个都是给定一个值，找到另一个hash值相同的。而第三个特点只要求我们找出存在的一对t1和t2，使得H(t1)=H(t2)。
相信大家都听过生日悖论(birthday paradox)。如果一个房间里有23个或23个以上的人，那么至少有两个人的生日相同的概率要大于50%。这个结果和直觉不太相符，不相信的人可以拿笔算算。这说明，如果我们挑选出了一组文档，那么其中至少有两个文档的hash值相同的概率将会大大提高（假设一个文档被映射到任何一个hash值的概率相同）。
现在来算一下一个例子。假设我们有两组文档X和Y，每一组里都有m=2^(n/2)个文档，那么X组里至少有一个文档会和Y组里某个文档发生hash碰撞的概率是：
对Y组里的第一个文档进行考察，它和X组里的第一个文档发生hash碰撞的概率是1-1/(2^n)。由于2^n &amp;gt;&amp;gt; 2^(n/2) （一般情况下对于一个安全的hash函数n&amp;gt;=128），因此Y组的第一个文档不和X组里任意文档发生碰撞的概率约为( 1-1/(2^n) )^m。那么Y组中所有文档都不和X组中文档发生碰撞的概率是( ( 1-1/(2^n) )^m )^m 约等于 e^-1。所以Y组中至少有一个文档和X中某个文档发生hash碰撞的概率是1-e^-1 = 0.63 &amp;gt; 0.5。
这个例子说明的问题就是，如果我们能枚举两组文档，每组文档的个数为2^(n/2)，其中n是hash值的二进制长度，那么两组文档发生hash碰撞的概率大于0.5。
有了这个关键的结论，现在我们来看看Bob怎么让 Alice签下1000万美元的合同。
首先Bob起草两份合同，一份上面写100万美元(A)，另一份上面写1000万美元(B)。这个时候如果用hash函数，这两份合同的hash值肯定不同。所以Bob不能直接让Alice签了A然后跑到法院去说她签了B，因为H(B)的值和当时两人签字的值H(A)不一样。
Bob现在拿出他的牛逼计算机，首先枚举一个长度为n/2的二进制串，枚举的复杂度为2^(n/2)。然后将这个二进制串转化为ASCII码。这样就可以得到一串比较奇怪但是很短小的字符串。然后把这2^(n/2)个字符串分别插入A和B中，得到2 * 2^(n/2)个变种合同，其中有2^(n/2)份上面写着100万美元（记为X组），另外2^(n/2)份上面写着1000万美元（记为Y组）。之后就可以进行生日攻击了，对所有的变种合同求hash值（2*2^(n/2)复杂度），根据之前计算的结果，有0.63的概率X组的某个合同和Y组的某个合同有相同的hash值。求完之后，对X和Y组里的hash值排序，则只需要2*2^(n/2)步就可以找到相同的hash值。
现在最关键的一步来了。Bob得到了写着100万美元的合同A&#39;，同时也有写着1000万美元的合同B&#39;，最为重要的是，我们知道H(A&#39;)=H(B&#39;)。那么他只需要给Alice看合同A&#39;。一般合同都是又长又臭，很多法律专业术语，Bob之前只插入了一个长度为n/16的ASCII字符串（我们假设n=128，那么这个字符串的长度只有8！，并且Bob可以分散字符串的内容将字符一个个插入不同的位置）。Alice在某个点忽略了那可疑的8个字符，签了100万美元的合同A&#39;。然后双方在hash值H(A&#39;)上签了字。
之后Bob就可以大摇大摆地拿着合同B&#39;去法院要求Alice支付1000万美元，因为他可以拿出合同B&#39;，上面写着1000万，然后应用hash函数，得到的hash值将会和他们两人当时签名时的hash值一样。
可怜的Alice！
          
          
        
      </description>
    </item>
    
    <item>
      <title>Linux: C  Makefile</title>
      <link>https://www.crs811.com/archives/1032/</link>
      <pubDate>Tue, 07 Feb 2017 22:48:58 +0000</pubDate>
      
      <guid>https://www.crs811.com/archives/1032/</guid>
      <description>
        
          
            作者: 陈皓 (CSDN) 概述
——
什么是makefile？或许很多Winodws的程序员都不知道这个东西，因为那些Windows的IDE都为你做了这个工作，但我觉得要作一个好的和professional的程序员，makefile还是要懂。这就好像现在有这么多的HTML的编辑器，但如果你想成为一个专业人士，你还是要了解HTML的标识的含义。特别在Unix下的软件编译，你就不能不自己写makefile了，会不会写makefile，从一个侧面说明了一个人是否具备完成大型工程的能力。
因为，makefile关系到了整个工程的编译规则。一个工程中的源文件不计数，其按类型、功能、模块分别放在若干个目录中，makefile定义了一系列的规则来指定，哪些文件需要先编译，哪些文件需要后编译，哪些文件需要重新编译，甚至于进行更复杂的功能操作，因为makefile就像一个Shell脚本一样，其中也可以执行操作系统的命令。
makefile带来的好处就是——“自动化编译”，一旦写好，只需要一个make命令，整个工程完全自动编译，极大的提高了软件开发的效率。make是一个命令工具，是一个解释makefile中指令的命令工具，一般来说，大多数的IDE都有这个命令，比如：Delphi的make，Visual C++的nmake，Linux下GNU的make。可见，makefile都成为了一种在工程方面的编译方法。
现在讲述如何写makefile的文章比较少，这是我想写这篇文章的原因。当然，不同产商的make各不相同，也有不同的语法，但其本质都是在“文件依赖性”上做文章，这里，我仅对GNU的make进行讲述，我的环境是RedHat Linux 8.0，make的版本是3.80。必竟，这个make是应用最为广泛的，也是用得最多的。而且其还是最遵循于IEEE 1003.2-1992 标准的（POSIX.2）。
在这篇文档中，将以C/C++的源码作为我们基础，所以必然涉及一些关于C/C++的编译的知识，相关于这方面的内容，还请各位查看相关的编译器的文档。这里所默认的编译器是UNIX下的GCC和CC。
关于程序的编译和链接
——————————
在此，我想多说关于程序编译的一些规范和方法，一般来说，无论是C、C++、还是pas，首先要把源文件编译成中间代码文件，在Windows下也就是 .obj 文件，UNIX下是 .o 文件，即 Object File，这个动作叫做编译（compile）。然后再把大量的Object File合成执行文件，这个动作叫作链接（link）。
编译时，编译器需要的是语法的正确，函数与变量的声明的正确。对于后者，通常是你需要告诉编译器头文件的所在位置（头文件中应该只是声明，而定义应该放在C/C++文件中），只要所有的语法正确，编译器就可以编译出中间目标文件。一般来说，每个源文件都应该对应于一个中间目标文件（O文件或是OBJ文件）。
链接时，主要是链接函数和全局变量，所以，我们可以使用这些中间目标文件（O文件或是OBJ文件）来链接我们的应用程序。链接器并不管函数所在的源文件，只管函数的中间目标文件（Object File），在大多数时候，由于源文件太多，编译生成的中间目标文件太多，而在链接时需要明显地指出中间目标文件名，这对于编译很不方便，所以，我们要给中间目标文件打个包，在Windows下这种包叫“库文件”（Library File)，也就是 .lib 文件，在UNIX下，是Archive File，也就是 .a 文件。
总结一下，源文件首先会生成中间目标文件，再由中间目标文件生成执行文件。在编译时，编译器只检测程序语法，和函数、变量是否被声明。如果函数未被声明，编译器会给出一个警告，但可以生成Object File。而在链接程序时，链接器会在所有的Object File中找寻函数的实现，如果找不到，那到就会报链接错误码（Linker Error），在VC下，这种错误一般是：Link 2001错误，意思说是说，链接器未能找到函数的实现。你需要指定函数的Object File.
好，言归正传，GNU的make有许多的内容，闲言少叙，还是让我们开始吧。
Makefile 介绍
———————
make命令执行时，需要一个 Makefile 文件，以告诉make命令需要怎么样的去编译和链接程序。
首先，我们用一个示例来说明Makefile的书写规则。以便给大家一个感兴认识。这个示例来源于GNU的make使用手册，在这个示例中，我们的工程有8个C文件，和3个头文件，我们要写一个Makefile来告诉make命令如何编译和链接这几个文件。我们的规则是：
1）如果这个工程没有编译过，那么我们的所有C文件都要编译并被链接。
2）如果这个工程的某几个C文件被修改，那么我们只编译被修改的C文件，并链接目标程序。
3）如果这个工程的头文件被改变了，那么我们需要编译引用了这几个头文件的C文件，并链接目标程序。
只要我们的Makefile写得够好，所有的这一切，我们只用一个make命令就可以完成，make命令会自动智能地根据当前的文件修改的情况来确定哪些文件需要重编译，从而自己编译所需要的文件和链接目标程序。
一、Makefile的规则
在讲述这个Makefile之前，还是让我们先来粗略地看一看Makefile的规则。
target ... : prerequisites ...
command
...
...
target也就是一个目标文件，可以是Object File，也可以是执行文件。还可以是一个标签（Label），对于标签这种特性，在后续的“伪目标”章节中会有叙述。
prerequisites就是，要生成那个target所需要的文件或是目标。
command也就是make需要执行的命令。（任意的Shell命令）
这是一个文件的依赖关系，也就是说，target这一个或多个的目标文件依赖于prerequisites中的文件，其生成规则定义在command中。说白一点就是说，prerequisites中如果有一个以上的文件比target文件要新的话，command所定义的命令就会被执行。这就是Makefile的规则。也就是Makefile中最核心的内容。
说到底，Makefile的东西就是这样一点，好像我的这篇文档也该结束了。呵呵。还不尽然，这是Makefile的主线和核心，但要写好一个Makefile还不够，我会以后面一点一点地结合我的工作经验给你慢慢到来。内容还多着呢。：）
二、一个示例
正如前面所说的，如果一个工程有3个头文件，和8个C文件，我们为了完成前面所述的那三个规则，我们的Makefile应该是下面的这个样子的。
          
          
        
      </description>
    </item>
    
    <item>
      <title>Linux C/C&#43;&#43;  .so .a 文件生成及使用</title>
      <link>https://www.crs811.com/archives/1023/</link>
      <pubDate>Tue, 07 Feb 2017 19:42:11 +0000</pubDate>
      
      <guid>https://www.crs811.com/archives/1023/</guid>
      <description>
        
          
            .so 文件 - 动态函数库
名字一般是libxxx.so，动态函数库在编译的时候 并没有被编译进目标代码中，程序执行到相关函数时才调用该函数库里的相应函数，因此动态函数库所产生的可执行文件比较小。由于函数库没有被整合进你的程序，而是程序运行时动态的申请并调用，所以程序的运行环境中必须提供相应的库。动态函数库的改变并不影响你的程序，所以动态函数库的升级比较方便。
linux系统有几个重要的目录存放相应的函数库，如/lib /usr/lib
动态函数库与Windows下的DLL类似，是在程序运行时动态连接，多个进程可以连接同一个共享库。
多个c文件编译成一个so文件命令是为：
$ gcc test_a.c test_b.c test_c.c -fPIC -shared -o libtest.so 选项:
-shared 该选项指定生成动态连接库（让连接器生成T类型的导出符号表，有时候也生成弱连接W类型的导出符号），不用该标志外部程序无法连接。相当于一个可执行文件
-fPIC：表示编译为位置独立的代码，不用此选项的话编译后的代码是位置相关的所以动态载入时是通过代码拷贝的方式来满足不同进程的需要，而不能达到真正代码段共享的目的。
-L.：表示要连接的库在当前目录中
-ltest：编译器查找动态连接库时有隐含的命名规则，即在给出的名字(test)前面加上lib，后面加上.so来确定库的名称: libtest.so
使用：
1、IDE(CodeBlocks)：在项目中添加所有函数库的头文件(.h)，在Linker setting 中添加.so文件.
2、命令行：将main.c与动态库libtest.so链接生成执行文件mainexc：
$ gcc main.c -L. -ltest -o mainexc .so文件路径
命令行下默认查找 .so 文件的路径基本为系统路径，lib或者usr/lib等，因此，执行./mainexc 会出现错误：
xx.so, cannot open shared object file: No such file or directory 解决方法：
$export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:. LD_LIBRARY_PATH：这个环境变量指示动态连接器可以装载动态库的路径。
如果有root权限，可以修改/etc/ld.so.conf文件，然后调用 /sbin/ldconfig来达到同样的目的 .a 文件 - 静态函数库
名字一般是libxxx.a；利用静态函数库编译成的文件比较大，因为整个函数库的所有数据都会被整合进目标代码中
优点是编译后的执行程序不需要外部的函数库支持，因为所有使用的函数都已经被编译进去了
缺点是如果静态函数库改变了，那么程序必须重新编译
.c 文件编译成 .o(.object)文件：
          
          
        
      </description>
    </item>
    
    <item>
      <title>Miracl 大数运算库的使用 – Windows, Linux</title>
      <link>https://www.crs811.com/archives/1017/</link>
      <pubDate>Sun, 05 Feb 2017 00:18:46 +0000</pubDate>
      
      <guid>https://www.crs811.com/archives/1017/</guid>
      <description>
        
          
            Windows XP - VC6.0
1、下载miracl5.4.zip
2、将压缩包中的所有文件解压并拷贝到同一个文件夹下
3、运行ms32doit.bat (x86系统) 或 ms64doit.bat (x64系统)，生成miracl.lib，有错误参见第2条
4、打开VC6，新建win32 console application &amp;gt; a simple application，将miracl中任意一个cpp文件(如ake6mntt.cpp)内容拷贝到main.cpp中
5、根据ake6mntt.cpp的声明，将ech.h, ecn3.h, zzn6.h及对应的cpp文件和 miracl.lib ，mnt.ecs 拷贝到工程根目录
6、VC &amp;gt; 左workspace &amp;gt; fileview &amp;gt; 右键项目 &amp;quot;add files to project&amp;quot;，将miracl.lib 和 所有.h, .cpp文件到工程中
7、若提示 pch 错误，需要设置所有cpp的预编译无效
project-&amp;gt;settings-&amp;gt; c/c++ Category，选择 pre compiled headers，点击： Not using precompiled header
8、编译执行，通过！！
Ubuntu 16 - CodeBlocks
1、根据 miracl_ReamMe.txt的要求：
Unzip the MIRACL.ZIP file using the unix utility unzip unzip -j -aa -L miracl.
          
          
        
      </description>
    </item>
    
    <item>
      <title>linux shell 正则表达式 (BREs,EREs,PREs) 差异比较</title>
      <link>https://www.crs811.com/archives/866/</link>
      <pubDate>Thu, 02 Feb 2017 17:57:12 +0000</pubDate>
      
      <guid>https://www.crs811.com/archives/866/</guid>
      <description>
        
          
            正则表达式简介 在计算机科学中，是指一个用来描述或者匹配一系列符合某个句法规则的字符串的单个字符串。
在很多文本编辑器或其他工具里，正则表达式通常被用来检索和/或替换那些符合某个模式的文本内容。
许多程序设计语言都支持利用正则表达式进行字符串操作。例如，在Perl中就内建了一个功能强大的正则表达式引擎。
正则表达式这个概念最初是由Unix中的工具软件（例如sed和grep）普及开的。
正则表达式通常缩写成“regex”，单数有regexp、regex，复数有regexps、regexes、regexen。这些是正则表达式的定义。 由于起源于unix系统，因此很多语法规则一样的。但是随着逐渐发展，后来扩展出以下几个类型。
一、正则表达式分类 1、基本的正则表达式（Basic Regular Expression 又叫 Basic RegEx 简称 BREs）
2、扩展的正则表达式（Extended Regular Expression 又叫 Extended RegEx 简称 EREs）
3、Perl 的正则表达式（Perl Regular Expression 又叫 Perl RegEx 简称 PREs）
说明：只有掌握了正则表达式，才能全面地掌握 Linux 下的常用文本工具（例如：grep、egrep、GUN sed、 Awk 等） 的用法
二、Linux 中常用文本工具与正则表达式的关系 常握 Linux 下几种常用文本工具的特点，对于我们更好的使用正则表达式是很有帮助的
grep , egrep 正则表达式特点： 1）grep 支持：BREs、EREs、PREs 正则表达式
grep 指令后不跟任何参数，则表示要使用 ”BREs“
grep 指令后跟 ”-E&amp;quot; 参数，则表示要使用 “EREs“
grep 指令后跟 “-P&amp;quot; 参数，则表示要使用 “PREs&amp;quot;
2）egrep 支持：EREs、PREs 正则表达式
egrep 指令后不跟任何参数，则表示要使用 “EREs”
          
          
        
      </description>
    </item>
    
    <item>
      <title>对一些大数库的简介</title>
      <link>https://www.crs811.com/archives/1009/</link>
      <pubDate>Mon, 30 Jan 2017 17:30:42 +0000</pubDate>
      
      <guid>https://www.crs811.com/archives/1009/</guid>
      <description>
        
          
            在网络安全技术领域中各种加密解密算法的软件实现上始终有一个共同的问题就是如何在普通的PC机上实现大数的运算。众所周知，我们现在日常生活中所普遍应用的计算机，即我们通常所说的PC机个人电脑大部分的机器内部字长还是32位的，最近才开始向64位的字长过渡，但是在各种加密解密的算法中为了达到一定的安全强度，都是要求在128位、512位或者是1024位这样的字长下进行加减乘除模逆等各种数学运算，我们称为大数运算。在这样的前提下，如何在PC机上快速高效的实现大数运算就很自然的成为了在PC机上实现加密解密算法最为基础和重要的问题。
为了解决大数运算的问题，世界各国的软件开发人员和研究学者都进行了很多的研究和实践。近年来，越来越多的开发人员开始重视软件工程的作用，为了减少重复劳动，提高软件的质量和代码复用，许多优秀的大数运算库随之出现：
GMP：GMP大数库是GNU项目的一部分，诞生于1991年。作为一个任意精度的大整数运算库，它包括了任意精度的带符号整数、有理数、浮点数的各种基本运算操作。它是一个c语言的库，但是官方提供了c++的包装类，主要的应用方向是密码学、网络安全、代数系统、计算科学等。GMP库的运行速度非常快的，它的官方网站上称自己为地球上最快的大数库，但是GMP库所提供的只是数学运算功能，并没有密码学相关的高级功能。 Miracl：Miracl库是Shamus Software Ltd开发的一个大数库，它的使用许可针对教育科学研究或者非商业目的地应用是免费的。在应用上它是一个c语言的库，同时提供了几个较为简单的c++包装类。在功能上它不但提供了高精度的大整数和分数的各种数学运算操作而且提供了很多密码学算法中的功能模块，如SHA、AES、DSA等中的一些底层操作。最为特别的是它还提供了很多椭圆曲线密码体制中的底层功能模块。由于Miracl库的内部实现采用了很多的汇编层的代码，故运行速度也非常快。 Crypto++：Crypto++库是一个开源项目，也是免费使用的。由于它是一个纯c++实现的库，所以应用非常的方便，库的结构清晰，使用方便，文档也很健全。Crypto++库提供了很多密码学算法的实现。 OpenSSL：OpenSSL是一个开放源代码的实现了SSL及相关加密技术的软件包，由加拿大的Eric Yang等发起编写的。它可以实现消息摘要、文件的加密和解密、数字证书、数字签名和随机数字等。 它的主要用途并不是大数库，而是SSL协议的实现和应用，但是其中也有一些关于大整数的功能，此外它也是基于c语言的。 
          
          
        
      </description>
    </item>
    
    <item>
      <title>MIRACL大数运算库使用手册</title>
      <link>https://www.crs811.com/archives/1007/</link>
      <pubDate>Mon, 30 Jan 2017 05:30:56 +0000</pubDate>
      
      <guid>https://www.crs811.com/archives/1007/</guid>
      <description>
        
          
            一．MIRACL简介
MIRACL(Multiprecision Integer and RationalArithmetic C/c++ Library)是一套由Shamus Software Ltd.所开发的一套关于大数运算函数库，用来设计与大数运算相关的密码学之应用，包含了RSA 公开密码学、Diffie-Hellman密钥交换(Key Exchange)、AES、DSA数字签名，还包含了较新的椭圆曲线密码学(Elliptic CurveCryptography)等等。运算速度快，并提供源代码。MIARCL是当前使用比较广泛的基于公钥加密算法保护实现的大数库之一，据说要使用该库用于商业软件，需要交纳一笔昂贵的授权费——1000$。
二．MIRACL常用函数调用手册
声明：此处只列出和大数相关的简单运算函数，以及产生大数随机数的函数调用手册，具体请查看manual.doc文档。不当之处，请大家批评指正！
函数原型: void absol(big x, big y);
功能说明: 取x的绝对值，y=|x|
函数原型: void add(big x, big y, big z);
功能说明: 两个大数相加，z=x+y
Example: add(x,x,x); // This doubles the value of x.
函数原型: void bigbits(int n, big x);
功能说明: 产生一个n位的大整数，初始化随机种子由irand函数实现
Example: bigbits(100,x); //This generates a 100 bitrandom number
函数原型: int cinstr(big x, char*s);
功能说明: 将大数字符串转换成大数
返回值: 输入字符数的个数
Example: mip-&amp;gt;IOBASE=16; // input large hex number into big x
          
          
        
      </description>
    </item>
    
    <item>
      <title>Linux – find命令</title>
      <link>https://www.crs811.com/archives/852/</link>
      <pubDate>Sat, 14 Jan 2017 23:48:35 +0000</pubDate>
      
      <guid>https://www.crs811.com/archives/852/</guid>
      <description>
        
          
            find命令用来在指定目录下查找文件。任何位于参数之前的字符串都将被视为欲查找的目录名。如果使用该命令时，不设置任何参数，则find命令将在当前目录下查找子目录与文件。并且将查找到的子目录和文件全部进行显示。
语法 find(选项)(参数) 选项 -amin&lt;分钟&gt;：查找在指定时间曾被存取过的文件或目录，单位以分钟计算；-anewer&lt;参考文件或目录&gt;：查找其存取时间较指定文件或目录的存取时间更接近现在的文件或目录；-atime&lt;24小时数&gt;：查找在指定时间曾被存取过的文件或目录，单位以24小时计算；-cmin&lt;分钟&gt;：查找在指定时间之时被更改过的文件或目录；-cnewer&lt;参考文件或目录&gt;查找其更改时间较指定文件或目录的更改时间更接近现在的文件或目录；-ctime&lt;24小时数&gt;：查找在指定时间之时被更改的文件或目录，单位以24小时计算；-daystart：从本日开始计算时间；-depth：从指定目录下最深层的子目录开始查找；-expty：寻找文件大小为0 Byte的文件，或目录下没有任何子目录或文件的空目录；-exec&lt;执行指令&gt;：假设find指令的回传值为True，就执行该指令；-false：将find指令的回传值皆设为False；-fls&lt;列表文件&gt;：此参数的效果和指定“-ls”参数类似，但会把结果保存为指定的列表文件；-follow：排除符号连接；-fprint&lt;列表文件&gt;：此参数的效果和指定“-print”参数类似，但会把结果保存成指定的列表文件；-fprint0&lt;列表文件&gt;：此参数的效果和指定“-print0”参数类似，但会把结果保存成指定的列表文件；-fprintf&lt;列表文件&gt;&lt;输出格式&gt;：此参数的效果和指定“-printf”参数类似，但会把结果保存成指定的列表文件；-fstype&lt;文件系统类型&gt;：只寻找该文件系统类型下的文件或目录；-gid&lt;群组识别码&gt;：查找符合指定之群组识别码的文件或目录；-group&lt;群组名称&gt;：查找符合指定之群组名称的文件或目录；-help或——help：在线帮助；-ilname&lt;范本样式&gt;：此参数的效果和指定“-lname”参数类似，但忽略字符大小写的差别；-iname&lt;范本样式&gt;：此参数的效果和指定“-name”参数类似，但忽略字符大小写的差别；-inum：查找符合指定的inode编号的文件或目录；-ipath&lt;范本样式&gt;：此参数的效果和指定“-path”参数类似，但忽略字符大小写的差别；-iregex&lt;范本样式&gt;：此参数的效果和指定“-regexe”参数类似，但忽略字符大小写的差别；-links&lt;连接数目&gt;：查找符合指定的硬连接数目的文件或目录；-iname&lt;范本样式&gt;：指定字符串作为寻找符号连接的范本样式；-ls：假设find指令的回传值为Ture，就将文件或目录名称列出到标准输出；-maxdepth&lt;目录层级&gt;：设置最大目录层级；-mindepth&lt;目录层级&gt;：设置最小目录层级；-mmin&lt;分钟&gt;：查找在指定时间曾被更改过的文件或目录，单位以分钟计算；-mount：此参数的效果和指定“-xdev”相同；-mtime&lt;24小时数&gt;：查找在指定时间曾被更改过的文件或目录，单位以24小时计算；-name&lt;范本样式&gt;：指定字符串作为寻找文件或目录的范本样式；-newer&lt;参考文件或目录&gt;：查找其更改时间较指定文件或目录的更改时间更接近现在的文件或目录；-nogroup：找出不属于本地主机群组识别码的文件或目录；-noleaf：不去考虑目录至少需拥有两个硬连接存在；-nouser：找出不属于本地主机用户识别码的文件或目录；-ok&lt;执行指令&gt;：此参数的效果和指定“-exec”类似，但在执行指令之前会先询问用户，若回答“y”或“Y”，则放弃执行命令；-path&lt;范本样式&gt;：指定字符串作为寻找目录的范本样式；-perm&lt;权限数值&gt;：查找符合指定的权限数值的文件或目录；-print：假设find指令的回传值为Ture，就将文件或目录名称列出到标准输出。格式为每列一个名称，每个名称前皆有“./”字符串；-print0：假设find指令的回传值为Ture，就将文件或目录名称列出到标准输出。格式为全部的名称皆在同一行；-printf&lt;输出格式&gt;：假设find指令的回传值为Ture，就将文件或目录名称列出到标准输出。格式可以自行指定；-prune：不寻找字符串作为寻找文件或目录的范本样式;-regex&lt;范本样式&gt;：指定字符串作为寻找文件或目录的范本样式；-size&lt;文件大小&gt;：查找符合指定的文件大小的文件；-true：将find指令的回传值皆设为True；-typ&lt;文件类型&gt;：只寻找符合指定的文件类型的文件；-uid&lt;用户识别码&gt;：查找符合指定的用户识别码的文件或目录；-used&lt;日数&gt;：查找文件或目录被更改之后在指定时间曾被存取过的文件或目录，单位以日计算；-user&lt;拥有者名称&gt;：查找符和指定的拥有者名称的文件或目录；-version或——version：显示版本信息；-xdev：将范围局限在先行的文件系统中；-xtype&lt;文件类型&gt;：此参数的效果和指定“-type”参数类似，差别在于它针对符号连接检查。 参数 起始目录：查找文件的起始目录。
实例 根据文件或者正则表达式进行匹配 在当前目录下搜索特定属性的文件：
find . -amin -10 # 查找在系统中最后10分钟访问的文件find .
          
          
        
      </description>
    </item>
    
    <item>
      <title>[转]block（闭包）一点也不神秘—如何利用block进行回调</title>
      <link>https://www.crs811.com/archives/761/</link>
      <pubDate>Thu, 22 Dec 2016 19:16:48 +0000</pubDate>
      
      <guid>https://www.crs811.com/archives/761/</guid>
      <description>
        
          
            原文：http://blog.csdn.net/mobanchengshuang/article/details/11751671
原文是OC, 对应 Swift 3 如下：
override func viewDidLoad() {super.viewDidLoad()// Do any additional setup after loading the view.print(&#34; === 我在玩手机&#34;)print(&#34; === 手机没电了&#34;)self.chargeMyIphone() {print(&#34; === 出去逛街了&#34;)}//self.perform(#selector(chargeMyIphone), with: nil, afterDelay: 3)print(&#34; === 我在看电视&#34;)}func chargeMyIphone(completion: @escaping ()-&gt;Void) {//Thread.sleep(forTimeInterval: 10)let delayInSeconds = 10.0let popTime = DispatchTime.now() + delayInSecondsDispatchQueue.main.asyncAfter(deadline: popTime, execute: {print(&#34; === 电充好了&#34;)completion()})}
          
          
        
      </description>
    </item>
    
    <item>
      <title>被误解的MVC和被神化的MVVM</title>
      <link>https://www.crs811.com/archives/798/</link>
      <pubDate>Mon, 19 Dec 2016 01:33:17 +0000</pubDate>
      
      <guid>https://www.crs811.com/archives/798/</guid>
      <description>
        
          
            被误解的 MVC MVC 的历史 MVC，全称是 Model View Controller，是模型 (model)－视图 (view)－控制器 (controller) 的缩写。它表示的是一种常见的客户端软件开发框架。
MVC 的概念最早出现在二十世纪八十年代的 施乐帕克 实验室中（对，就是那个发明图形用户界面和鼠标的实验室），当时施乐帕克为 Smalltalk 发明了这种软件设计模式。
现在，MVC 已经成为主流的客户端编程框架，在 iOS 开发中，系统为我们实现好了公共的视图类：UIView，和控制器类：UIViewController。大多数时候，我们都需要继承这些类来实现我们的程序逻辑，因此，我们几乎逃避不开 MVC 这种设计模式。
但是，几十年过去了，我们对于 MVC 这种设计模式真的用得好吗？其实不是的，MVC 这种分层方式虽然清楚，但是如果使用不当，很可能让大量代码都集中在 Controller 之中，让 MVC 模式变成了 Massive View Controller 模式。
Controller 的臃肿问题何解？ 很多人试图解决 MVC 这种架构下 Controller 比较臃肿的问题。我还记得半年前 InfoQ 搞了一次移动座谈会，当时 BeeFramework 和 Samurai-Native 的作者 老郭 问了我一句话：「什么样的内容才应该放到 Controller 中？」。但是当时因为时间不够，我没能展开我的观点，这次正好在这里好好谈谈我对于这个问题的想法。
我们来看看 MVC 这种架构的特点。其实设计模式很多时候是为了 Don&#39;t repeat yourself 原则来做的，该原则要求能够复用的代码要尽量复用，来保证重用。在 MVC 这种设计模式中，我们发现 View 和 Model 都是符合这种原则的。
对于 View 来说，你如果抽象得好，那么一个 App 的动画效果可以很方便地移植到别的 App 上，而 Github 上也有很多 UI 控件，这些控件都是在 View 层做了很好的封装设计，使得它能够方便地开源给大家复用。
          
          
        
      </description>
    </item>
    
    <item>
      <title>Shell 编程 3 – if条件字符串、数字比对，[[ ]]和[ ]区别</title>
      <link>https://www.crs811.com/archives/652/</link>
      <pubDate>Tue, 22 Nov 2016 01:05:57 +0000</pubDate>
      
      <guid>https://www.crs811.com/archives/652/</guid>
      <description>
        
          
            学习shell的时候总是被shell里的条件判断方式搞得头疼，经常不知道改 用[],[[]],(())还是test,let，而很少有书把它们的关系讲解的很清楚，今天重点说说它们的区别的使用时应该注意的地方。
1、先说[]和test，两者是一样的，在命令行里test expr和[ expr ]的效果相同。test的三个基本作用是判断文件、判断字符串、判断整数。支持使用与或非将表达式连接起来。要注意的有：
test中可用的比较运算符只有==和!=，两者都是用于字符串比较的，不可用于整数比较，整数比较只能使用-eq, -gt这种形式。无论是字符串比较还是整数比较都千万不要使用 &amp;gt; 和 &amp;lt; 。当然，如果实在想用也是可以的，对于字符串比较可以使用尖括号的转义形式， 如果比较&amp;quot;ab&amp;quot;和&amp;quot;bc&amp;quot;：[ ab &amp;lt; bc ]，结果为真，也就是返回状态为0.
2、然后是[[ ]]，这是内置在shell中的一个命令，它就比刚才说的test强大的多。支持字符串的模式匹配（使用=~操作符时甚至支持shell的正则表达 式）。简直强大的令人发指！逻辑组合可以不使用test的-a,-o而使用&amp;amp;&amp;amp;,||这样更亲切的形式(针对c、Java程序员)。当 然，也不用想的太复杂，基本只要记住：
字符串比较时可以把右边的作为一个模式（这是右边的字符串不加双引号的情况下。如果右边的字符串加了双引号，则认为是一个文本字符串。），而不仅仅是一个字符串，比如[[ hello == hell? ]]，结果为真。
另外要注意的是，使用[]和[[]]的时候不要吝啬空格，每一项两边都要有空格，[[ 1 == 2 ]]的结果为“假”，但[[ 1==2 ]]的结果为“真”！后一种显然是错的
3、最后就是let和(())，两者也是一样的(或者说基本上是一样的，双括号比let稍弱一些)。主要进行算术运算(上面的两个都不行)，也比较适合进 行整数比较，可以直接使用熟悉的&amp;lt;,&amp;gt;等比较运算符。可以直接使用变量名如var而不需要$var这样的形式。支持分号隔开的多个表达式
[] 与 [[ ]] 的比较
首先，尽管很相似，但是从概念上讲，二者是不同层次的东西。
&amp;quot;[[&amp;quot;，是关键字，许多shell(如ash bsh)并不支持这种方式。ksh, bash(据说从2.02起引入对[[的支持)等支持。
&amp;quot;[&amp;quot;是一条命令， 与test等价，大多数shell都支持。在现代的大多数sh实现中，&amp;quot;[&amp;quot;与&amp;quot;test&amp;quot;是内部(builtin)命令，换句话说执行&amp;quot;test&amp;quot;/&amp;quot;[&amp;quot;时不会调用/some/path/to/test这样的外部命令(如果有这样的命令的话)。
2.[[]]结构比Bash版本的[]更通用。在[[和]]之间的所有的字符都不会被文件扩展或是标记分割，但是会有参数引用和命令替换。 用[[ ... ]]测试结构比用[ ... ]更能防止脚本里的许多逻辑错误。比如说，&amp;amp;&amp;amp;,||,&amp;lt;和&amp;gt;操作符能在一个[[]]测试里通过，但在[]结构会发生错误。
3.(( ))结构扩展并计算一个算术表达式的值。如果表达式值为0，会返回1或假作为退出状态码。一个非零值的表达式返回一个0或真作为退出状态码。这个结构和先前test命令及[]结构的讨论刚好相反。
4.[ ... ]为shell命令，所以在其中的表达式应是它的命令行参数，所以串比较操作符&amp;quot;&amp;gt;&amp;quot; 与&amp;quot;&amp;lt;&amp;quot;必须转义，否则就变成IO改向操作符了(请参看上面2中的例子)。在[[中&amp;quot;&amp;lt;&amp;quot;与&amp;quot;&amp;gt;&amp;quot;不需转义；
由于&amp;quot;[[&amp;quot;是关键字，不会做命令行扩展，因而相对的语法就稍严格些。例如
在[ ... ]中可以用引号括起操作符，因为在做命令行扩展时会去掉这些引号，而在[[ ... ]]则不允许这样做。
5.[[ ... ]]进行算术扩展，而[ ... ]不做
6.[[ .
          
          
        
      </description>
    </item>
    
    <item>
      <title>Shell 编程 1 – grep sed awk</title>
      <link>https://www.crs811.com/archives/633/</link>
      <pubDate>Sun, 20 Nov 2016 00:11:57 +0000</pubDate>
      
      <guid>https://www.crs811.com/archives/633/</guid>
      <description>
        
          
            grep, sed 与 awk 相当有用 !
gerp 查找, sed 编辑, awk 根据内容分析并处理.
awk(关键字:分析&amp;amp;处理) 一行一行的分析处理 awk &#39;条件类型1{动作1}条件类型2{动作2}&#39; filename, awk 也可以读取来自前一个指令的 standard input
相对于sed常常用于一整行处理, awk则比较倾向于一行当中分成数个&amp;quot;字段&amp;quot;(区域)来处理, 默认的分隔符是空格键或tab键
例如:
last -n 5 | awk &#39;{print $1 &amp;quot;\t&amp;quot; $3}&#39; 这里大括号内$1&amp;quot;\t&amp;quot;$3 之间不加空格也可以, 不过最好还是加上个空格, 另外注意&amp;quot;\t&amp;quot;是有双引号的, 因为本身这些内容都在单引号内
$0 代表整行 $1代表第一个区域, 依此类推
awk的处理流程是:
读第一行, 将第一行资料填入变量 $0, $1... 等变量中 依据条件限制, 执行动作 接下来执行下一行
所以, AWK一次处理是一行, 而一次中处理的最小单位是一个区域
另外还有3个变量, NF: 每一行处理的字段数, NR 目前处理到第几行 FS 目前的分隔符
逻辑判断 &amp;gt; &amp;lt; &amp;gt;= &amp;lt;= == !== , 赋值直接使用=
          
          
        
      </description>
    </item>
    
    <item>
      <title>Shell 编程 0 – 基本语法</title>
      <link>https://www.crs811.com/archives/639/</link>
      <pubDate>Sat, 19 Nov 2016 23:50:16 +0000</pubDate>
      
      <guid>https://www.crs811.com/archives/639/</guid>
      <description>
        
          
            1.1 shell提示符及其环境 环境：Linux，Unix，Dos等等
Shell是一个解释执行命令的程序，所谓shell编程其实就是用一定的语法将各种基本的命令组合起来，让shell程序去解释执行。
同传统的编程语言一样，shell提供了很多特性，这些特性可以使你的shell script编程更为有用，如：数据变量、参数传递、判断、流程控制、数据输入和输出，子程序及以中断处理等。
1.2 如何执行shell程序 Shell程序后缀名： .sh，如 first.sh
执行shell三种方法：
1(1) bash first.sh## 1. 2 3(2) 4chmod u+x first.sh 5./first.sh 6 7(3) . first.sh 1.3 常量 字符串，例如“Hello World！”。
数字，例如755，23。
1.4 变量 shell中变量默认没有类型，简称弱类型，类似于PHP、Javascript、Swift中的变量，无类型声明
1STR=&amp;#34;Hello World!&amp;#34; #定义变量 STR 2echo $STR # $ 符号是获得变量STR的值 3 4HOME=&amp;#34;/home&amp;#34; 5a=123 6HOME_LIST=$( ls /home ) #把命令的执行结果赋值给变量 7ehco $HOME 8let a=a+1 #计算 注意：赋值时等号两边不能有空格
系统变量：
系统变量 含义 $0 Shell 脚本 的名字 $n Shell 脚本 的第n个参数值，n=1..9 $* Shell 脚本 的所有参数,此选项参数可超过9个。 $# Shell 脚本 的参数个数 $$ Shell 脚本 的PID(脚本运行的当前进程ID号) $!
          
          
        
      </description>
    </item>
    
    <item>
      <title>Docker 常用命令</title>
      <link>https://www.crs811.com/archives/627/</link>
      <pubDate>Sun, 13 Nov 2016 19:03:20 +0000</pubDate>
      
      <guid>https://www.crs811.com/archives/627/</guid>
      <description>
        
          
            查看docker信息（version、info） # 查看docker版本 $docker version # 显示docker系统的信息 $docker info 对image的操作（search、pull、images、rmi、history） # 检索image $docker search image_name # 下载image $docker pull image_name # 列出镜像列表; -a, --all=false Show all images; --no-trunc=false Don&#39;t truncate output; -q, --quiet=false Only show numeric IDs $docker images # 删除一个或者多个镜像; -f, --force=false Force; --no-prune=false Do not delete untagged parents $docker rmi image_name # 显示一个镜像的历史; --no-trunc=false Don&#39;t truncate output; -q, --quiet=false Only show numeric IDs $docker history image_name 启动容器（run） docker容器可以理解为在沙盒中运行的进程。这个沙盒包含了该进程运行所必须的资源，包括文件系统、系统类库、shell 环境等等。但这个沙盒默认是不会运行任何程序的。你需要在沙盒中运行一个进程来启动某一个容器。这个进程是该容器的唯一进程，所以当该进程结束的时候，容器也会完全的停止。
          
          
        
      </description>
    </item>
    
    <item>
      <title>云计算 Mesos</title>
      <link>https://www.crs811.com/archives/617/</link>
      <pubDate>Wed, 09 Nov 2016 01:11:03 +0000</pubDate>
      
      <guid>https://www.crs811.com/archives/617/</guid>
      <description>
        
          
            我讨厌“软件定义数据中心（SDDC）”这个词，并不是因为我质疑这个概念，而是我发现很多公司都对这个词有误用，他们甚至直接把这个词拿来套用， 并急于把自己定位为下一代数据中心的创新者。具体来说，我认为，在商用x86硬件上运行软件（应用）并不是什么SDDC解决方案，它也不具备虚拟化硬件到 资源池的能力。真正的SDDC底层基础架构应该可以从运行于其上的应用程序中抽象出来，并根据应用程序不断变化的需求，动态且自动地分配、重新分配应用程 序，然后运行于数据中心的不同组件之中。
这就是为什么我一直兴奋地要在后面介绍Mesos，一个Apache开源项目。为什么我对Mesos如此兴奋？回想x86虚拟化之初对数据中心曾经 的承诺：通过增加服务器利用率使其更高效，通过从物理基础架构抽象应用使其更敏捷。虽然收获颇丰，但是以虚拟机为单位，粒度仍不够精细，如果应用程序都过 于庞大，那就难以充分实现这一承诺。如今，飞速发展的容器技术、分布式应用程序和微服务技术正悄然改变着我们对数据中心的运行和管理方式。
试想，可否整合数据中心中的所有资源，并将它们放在一个大的虚拟池里，代替单独的物理服务器；然后开放诸如CPU、内存和I/O这些基本资源而不是 虚拟机？同样，可否把应用程序拆分成小的、隔离的任务单位，从而根据数据中心应用的需求，从虚拟数据中心池中动态分配任务资源？就像操作系统将PC的处理 器和RAM放入资源池，使其可以为不同的进程协调分配和释放资源。进一步讲，我们可以把Mesos作为操作系统内核，然后将数据中心看为PC。这也是正是 我想说的：Mesos正在改变数据中心，它让真正的SDDC成为现实。
接下来我先介绍下Mesos的历史。Mesos的起源于Google的数据中心资源管理系统Borg。你可以从WIRED杂志的这篇文章中 了解更多关于Borg起源的信息及它对Mesos影响。Twitter从Google的Borg系统中得到启发，然后就开发一个类似的资源管理系统来帮助 他们摆脱可怕的“失败之鲸”（译者注：见上图）。后来他们注意到加州大学伯克利分校AMPLab正在开发的名为Mesos的项目，这个项目的负责人是 Ben Hindman，Ben是加州大学伯克利分校的博士研究生。后来Ben Hindman加入了Twitter，负责开发和部署Mesos。现在Mesos管理着Twitter超过30,0000台服务器上的应用部署，“失败之 鲸”已成往事。其他公司纷至沓来，也部署了Mesos，比如Airbnb（空中食宿网）、eBay（电子港湾）和Netflix。
Mesos是如何让Twitter和Airbnb这样的公司，通过数据中心资源更高效的管理系统，扩展应用的呢？我们从一个相当简单但很优雅的两级调度架构开始说起。
上图修改自Apache Mesos网站上的图片，如图所示，Mesos实现了两级调度架构，它可以管理多种类型的应用程序。第一级调度是Master的守护进程，管理Mesos 集群中所有节点上运行的Slave守护进程。集群由物理服务器或虚拟服务器组成，用于运行应用程序的任务，比如Hadoop和MPI作业。第二级调度由被 称作Framework的“组件”组成。Framework包括调度器（Scheduler）和执行器（Executor）进程，其中每个节点上都会运行 执行器。Mesos能和不同类型的Framework通信，每种Framework由相应的应用集群管理。上图中只展示了Hadoop和MPI两种类型， 其它类型的应用程序也有相应的Framework。
Mesos Master协调全部的Slave，并确定每个节点的可用资源，
聚合计算跨节点的所有可用资源的报告，然后向注册到Master的Framework（作为Master的客户端）发出资源邀约。Framework可以 根据应用程序的需求，选择接受或拒绝来自master的资源邀约。一旦接受邀约，Master即协调Framework和Slave，调度参与节点上任 务，并在容器中执行，以使多种类型的任务，比如Hadoop和Cassandra，可以在同一个节点上同时运行。
我将在接下来的文章中，详细介绍Mesos的体系结构和工作流。我认为，Mesos使用的两级调度架构以及算法、隔离技术让在同一个节点上运行多种 不同类型的应用成为了现实，这才是数据中心的未来。正如我之前所述，这是到目前为止我所见过的，履行SDDC承诺最好的现成技术。
我希望这篇介绍让你受用并吊起你了解Mesos的胃口。接下来，我将带你深入技术细节，教你一些上手方法，还会告诉你如何加入社区。
源文 : 深入浅出Mesos（一）：为软件定义数据中心而生的操作系统
如何在超大规模环境下运行Docker容器？Apache Mesos也许是解决之道
          
          
        
      </description>
    </item>
    
    <item>
      <title>云计算 Docker – 2 [转]</title>
      <link>https://www.crs811.com/archives/622/</link>
      <pubDate>Tue, 08 Nov 2016 23:42:55 +0000</pubDate>
      
      <guid>https://www.crs811.com/archives/622/</guid>
      <description>
        
          
            本文导航: 第1页：dotCloud到Docker：低调奢华有内涵 第2页：如何定义Docker？ 第3页：Docker与虚拟化争锋 第4页：Docker解决了三大现存问题 第5页：Docker安全鉴定三方面 第6页：评说Docker 第7页：常用Docker命令 第8页：Docker最新版（1.8）下载地址 1dotCloud到Docker：低调奢华有内涵 &amp;lt;div class=&amp;quot;ad-box article-cont-ad&amp;quot;&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;p&amp;gt; 写在前面：放在两年前，你不认识Docker情有可原。但如果现在你还这么说，不好意思，我只能说你OUT了。你最好马上get起来，因为有可能你们公司很快就会引入Docker。今天就和大家讨论讨论这个备受好评的应用，让我们来揭开他的真面目！ &amp;lt;/p&amp;gt; &amp;lt;p&amp;gt; &amp;lt;img src=&amp;quot;https://www.crs811.com/uploads/2016/11/b88833d99ea68f0e64efbc5d8ba3f40d.png&amp;quot; /&amp;gt; &amp;lt;/p&amp;gt; &amp;lt;p&amp;gt; &amp;amp;nbsp; &amp;lt;/p&amp;gt; &amp;lt;p&amp;gt; &amp;lt;strong&amp;gt;　【一】从dotCloud到Docker--低调奢华有内涵&amp;lt;/strong&amp;gt; &amp;lt;/p&amp;gt; &amp;lt;p&amp;gt; &amp;lt;strong&amp;gt;　1、追根溯源：dotCloud&amp;lt;/strong&amp;gt; &amp;lt;/p&amp;gt; &amp;lt;p&amp;gt; 时间倒回到两年前，有一个名不见经传的小公司，他的名字叫做：dotCloud。dotCloud公司主要提供的是基于 PaaS（Platform as a Service，平台及服务）平台为开发者或开发商提供技术服务，并提供的开发工具和技术框架。 &amp;lt;/p&amp;gt; &amp;lt;p&amp;gt; 初创企业总是艰难的，dotCloud也是一样。在IBM，亚马逊，谷歌等大公司的挤压下，dotCloud举步维艰。即使2011年拿到了1000万美元的融资，可和上述大公司比起来，也不过是杯水车薪。 &amp;lt;/p&amp;gt; &amp;lt;p&amp;gt; 随着开源的洪流袭来，在2013年dotCloud 的创始人，28岁的Solomon Hykes做了一个艰难的决定：将dotCloud的核心引擎开源！然而一旦这个基于 LXC（Linux Container）技术的核心管理引擎开源，dotCloud公司就相当于走上了一条&amp;quot;不归路&amp;quot;。 &amp;lt;/p&amp;gt; &amp;lt;p&amp;gt; 可正是这个孤注一掷的举动，却带来了全球技术人员的热潮，众程序员惊呼：太方便了，太方便了。也正是这个决定，让所有的IT巨头也为之一颤。一个新的公司也随之出世，它就是：Docker。 &amp;lt;/p&amp;gt; &amp;lt;p&amp;gt; &amp;lt;strong&amp;gt;　2、Docker出世：从Docker0.1到Docker1.0&amp;lt;/strong&amp;gt; &amp;lt;/p&amp;gt; &amp;lt;p&amp;gt; &amp;lt;strong&amp;gt;　一个春秋，跨越了Docker的成名路。&amp;lt;/strong&amp;gt; &amp;lt;/p&amp;gt; &amp;lt;p&amp;gt; 在互联网时代，一夜成名早已不是什么新闻。Docker 这个技术公司，向我们证明了，成为一个&amp;quot;国际巨星&amp;quot;，只需要一个月。2013年2月决定开源，到2013年3月20日发布Docker0.1，只用了一个月的时间。 &amp;lt;/p&amp;gt; &amp;lt;p&amp;gt; 今后几乎每个一个月，Docker都会发布一个版本。而Docker0.1的发布像是一个宣言，昭示着一个Docker正在以一个新兴容器领导者的姿态迈进。 &amp;lt;/p&amp;gt; &amp;lt;p&amp;gt; 正如我们所知，从Docker0.
          
          
        
      </description>
    </item>
    
    <item>
      <title>云计算 Docker</title>
      <link>https://www.crs811.com/archives/615/</link>
      <pubDate>Tue, 08 Nov 2016 17:00:40 +0000</pubDate>
      
      <guid>https://www.crs811.com/archives/615/</guid>
      <description>
        
          
            Docker 是一个基于LXC 的高级容器引擎。简单地说，docker 是一个轻量级的虚拟解决方案，或者说 —— 一个超轻量级的虚拟机。你一定理解虚拟机是什么，那么，可以认为 docker 是一个秒级启动的虚拟机，可以轻易创建和删除。
docker 是一种集装箱式的工作方式。正如我们会将各种不同的货物统一打包成一个个集装箱，进行标准的管理和运输，在 docker 的世界里，我们把应用和应用所依赖的运行环境打包成一个个 image，然后分发到任意支持 docker 的平台，就可以在这些平台运行我们的应用，提供服务。
那支持 docker 的平台有哪些？因为 docker 是基于 linux 的，在任意的 linux 发行版我们都可以原生地支持 docker，只要对应的内核版本大于 3.10 并且是 64bit，而在 Windows 和 Mac 中，我们可以通过 boot2docker 来运行 docker，这几乎意味着，所有的主流平台都支持 docker 的运行 —— 从此不再需要为跨平台而苦恼。
vm 的理念是在宿主的系统之上，自己虚拟了一个硬件平台，然后运行一个不同的 OS。这意味着它要求很多的资源，在一台机器上，你最多就跑几个虚拟机吧。
而 docker 是依托于宿主机提供的内核，仅仅把一个不同的 linux 发行版本所需的特性打包成一个 image, 这样子当你运行一个 ubuntu 镜像，你会感觉就是在一个 ubuntu 的操作环境里，但实际调用的系统接口都是来源于宿主机。所以当你运行一些内核相关的命令时，你就会发现一些端倪，比如 uname -a, 这时给出的信息肯定是宿主机的。
因为共用宿主机的内核，所以 docker 所需的资源也很少，性能开销很小，通常可以在秒内启动，有些已经可以做到毫秒内启动了。在一台机器上，你完全可能做到同时运行上千个 docker 的容器。
docker 的运行方式也让我们对 VM 的理念产生质疑，假如我们需要虚拟一个不同的运行环境，是否需要一个完全新的系统？其实我们要的只是运行一个应用所需的依赖环境，不是吗？
总的来说，docker 抛弃传统 VM 试图模拟完整机器的思路，本着“面向应用”的核心理念，以应用为单元进行”集装封箱”。
          
          
        
      </description>
    </item>
    
    <item>
      <title>云计算 Container LXC</title>
      <link>https://www.crs811.com/archives/610/</link>
      <pubDate>Tue, 08 Nov 2016 05:14:49 +0000</pubDate>
      
      <guid>https://www.crs811.com/archives/610/</guid>
      <description>
        
          
            Container
Container技术和服务器虚拟化不是一样的技术，两者虽然都属于虚拟化的技术，目标都是为了将一套应用程序所需的执行环境打包起来，建立一个孤立环境，方便在不同的硬件中移动，但两者的运作思维截然不同。
简单来说，常见的传统虚拟化技术如 vSphere 或 Hyper-V 是以操作系统为中心，而 Container 技术则是一种以应用程序为中心的虚拟化技术。
传统虚拟化技术从操作系统层下手，目标是建立一个可以用来执行整套操作系统的沙盒独立执行环境，习惯以虚拟机（Virtual Machine）来称呼。而 Container 技术则是直接将一个应用程序所需的相关程序代码、函式库、环境配置文件都打包起来建立沙盒执行环境，为了和传统虚拟化技术产生的虚拟机区分，Container 技术产生的环境就称为 Container。
虚拟机和Container最明显的差别是虚拟机需要安装操作系统（安装 Guest OS）才能执行应用程序，而 Container 内不需要安装操作系统就能执行应用程序。Container 技术不是在 OS 外来建立虚拟环境，而是在 OS 内的核心系统层来打造虚拟执行环境，透过共享 Host OS 的作法，取代一个一个 Guest OS 的功用。Container 也因此被称为是 OS 层的虚拟化技术。
因为 Container 技术采取共享 Host OS 的作法，而不需在每一个 Container 内执行 Guest OS，因此建立 Container 不需要等待操作系统开机时间，不用 1 分钟或几秒钟就可以启用，远比需要数分钟甚至数十分钟才能开启的传统虚拟机来的快。
Container技术非常适用于分布式应用框架中，这意味着底层的Container基础架构必须是模块化和非常灵活的； 以下所探讨的核心概念，很多来源于如今的虚拟化架构，比如服务发现（Service Discovery），集群管理（Cluster Management）和资源调度（Resource Scheduling）； 围绕整个container技术架构的公司生态也在快速发展，多数情况下，他们都从单一的工具开始，慢慢发展为一个全栈服务。 下面是对整个技术栈自下而上的分析：
DevOps工具叫“开发工具”和“运维工具”更加直观，他们运行在本地机器上，用来启动Container，虚拟机或初始化应用包。
Hashicorp Vagrant，Docker Machine，VMware AppCatalyst 物理宿主机（或VM）Container实际运行的机器，可能是一个本地的笔记本电脑，一个数据服务器或一个公有云实例。
VMware ESX，Microsoft Hyper-V，KVM，LXD Container OS负责和底层物理宿主机交互的操作系统（Linux或Windows），还负责提供所有container共享的OS级别的服务。
CoreOS，RedHat Atomic，RancherOS，Canonical Snappy，VMware Photo Container Runtime创建、启动、停止、销毁Container的软件层。
          
          
        
      </description>
    </item>
    
    <item>
      <title>云计算 vShpere Hyper-V KVM Openstack</title>
      <link>https://www.crs811.com/archives/607/</link>
      <pubDate>Tue, 08 Nov 2016 04:52:02 +0000</pubDate>
      
      <guid>https://www.crs811.com/archives/607/</guid>
      <description>
        
          
            Hypervisor
hypervisor 之于操作系统 类似于 操作系统之于进程。
虚拟化 就是通过某种方式隐藏底层物理硬件的过程，从而让多个操作系统可以透明地使用和共享它。
Hypervisor是一种运行在物理服务器和操作系统之间的中间软件层,可允许多个操作系统和应用共享一套基础物理硬件，因此也可以看作是虚拟环境中的“元”操作系统，它可以协调访问服务器上的所有物理设备和虚拟机，也叫虚拟机监视器（Virtual Machine Monitor）
服务器虚拟化
服务器虚拟化技术日渐成熟，越来越多的企业开始考虑将应用程序和操作系统的部署从底层硬件分离出来，进而简化繁琐的运维操作。当前最普遍的模式，便是通过VMware虚拟化基础架构平台，为不同的业务应用分配专有计算资源，将硬件服务器作为资源池进行管理，从而构建架构灵活、管理便捷、处理高效的虚拟化数据中心。
常见的hypervisor
1、VMWare
VMWare 虚拟化：
VMWare 虚拟化架构：
2、Hyper-V
Hyper-V与VMware的ESXi
微软的Hyper-V与VMware的ESXi在架构上有众多不同，然而很多虚拟化管理员并未意识到这些差异。而且很多管理员同样对Hyper-V是在主机操作系统上运行感到困惑。
有关微软Hyper-V的一个常见的误解就是安装Hyper-V需要使用Windows操作系统，Hyper-V运行在主机操作系统之上而不是直接安装在裸机上。有必要指出一旦Hyper-V角色通过Server Manager启用，hypervisor代码实际上是被配置为在Windows 内核空间内启动。运行在内核空间的组件能够直接访问硬件，这同样适用于Hyper-V。另一方面，VMware的ESXi采用了完全不同的方式，ESXi hypervisor被封装为一个单独的ISO文件，它实际上是一个Linux内核操作系统。
Hyper-V和ESXi都是 Type 1 hypervisor。 Type 1 hypervisor直接运行在硬件之上，从设计上能够将Type 1 hypervisor进一步划分为两类：microkernelized和monolithic。microkernelized设计与monolithic设计有一些细微的差异。两类设计唯一的差异就是设备驱动的位置以及控制功能。
在monolithic设计中，驱动被作为hypervisor的一部分包括在内。VMware ESXi使用monolithic设计实现所有的虚拟化功能，包括虚拟化设备驱动。自从首次推出虚拟化产品起，VMware一直在使用monolithic设计。由于设备驱动包含在了hypervisor中，在hypervisor代码的帮助下，运行ESXi主机之上的虚拟机能够与物理硬件直接通信，不再依赖中间设备。
微软Hyper-V 架构使用了microkernelized设计，hypervisor代码运行时没有包括设备驱动。设备驱动安装在主机操作系统内，虚拟机访问硬件设备的请求交由操作系统处理。换句话说由主机操作系统控制对硬件的访问
3、KVM
kvm基本结构有2个部分构成：
kvm 驱动，现在已经是linux kernel的一个模块了。其主要负责虚拟机的创建，虚拟内存的分配，VCPU寄存器的读写以及VCPU的运行。
另个组成是Qemu，用于模拟虚拟机的用户空间组件，提供I/O设备模型，访问外设的途径。
左侧部分是一个标准的Linux操作系统，可以是RHEL、Fedora、Ubuntu等。KVM内核模块在运行时按需加载进入内核空间运行。KVM本身不执行任何设备模拟，需要用户空间程序QEMU通过/dev/kvm接口设置一个虚拟客户机的地址空间，向它提供模拟的I/O设备，并将它的视频显示映射回宿主机的显示屏。
4、OpenStack
DashBoard Horizon 提供WEB界面 Computer Nova 计算也就是虚拟机 Networking Neutron 提供给nova网络支持 Object Storage Swift 提供对象存储 Block Storage Cinder 提供云硬盘给nova，同时备份到Swift Identity Sservice Keystone 提供所有组件的认证 Image Service Glance 提供给nova镜像服务 Telemetry Service Cellometer 监控 cinder,neutron,nova,glance Orchestration Service Heat 与AWS cloud兼容 整个OpenStack由控制节点，计算节点，网络节点，存储节点四大部分组成
          
          
        
      </description>
    </item>
    
    <item>
      <title>云计算 – x as a Service</title>
      <link>https://www.crs811.com/archives/601/</link>
      <pubDate>Tue, 08 Nov 2016 04:12:29 +0000</pubDate>
      
      <guid>https://www.crs811.com/archives/601/</guid>
      <description>
        
          
            云计算服务大约分为三个层次，IaaS、PaaS、SaaS。
简单说来，所谓IaaS，即Infrastructure（基础设施）-as-a- Service、Platform（平台）-as-a-Service和Software（软件）-as-a-Service，三个层次的服务也是下端-中端-顶端的明显区别
IaaS
IaaS全拼是Infrastructure as a Service,基础设置即服务,消费者通过Internet可以从完善的计算机基础设施获得服务。例如AWS、OpenStack，CloudStack提供的虚拟机计算服务。通过这种模式，用户可以从供应商那里获得他所需要的虚拟机或者存储资源来装载相关应用，同时这些基础设置的繁琐的管理工作将由IaaS供应商来处理。IaaS能通过它上面对虚拟机支持众多的应用。IaaS主要的用户是系统管理员。
产品
主要包括：Amazon EC2，Linode，Joyent，Rackspace，IBM Blue Cloud和Cisco UCS等。
功能
IaaS云有哪些功能呢？在《虚拟化和云计算》中列出了Iaas的七个基本功能：
资源抽象：使用资源抽象的方法，能更好的调度和管理物理资源。
负载管理：通过负载管理，不仅能使部署在基础上设施上的应用运能更好地应对突发情况，而且还能更好的利用系统资源。
数据管理：对云计算而言，数据的完整性，可靠性和可管理性是对Iaas的基本要求。
资源部署：也就是将整个资源从创建到使用的流程自动化。
安全管理：IaaS的安全管理的主要目标时保证基础设置和其提供资源被合法地访问和使用。
计费管理：通过细致的计费管理能使用户更灵活地使用资源。
SaaS
SaaS全拼是Software-as-a-service ，国内通常叫做软件运营服务模式，简称为软营模式，提供的是软件服务，例如office365等，通过互联网就直接能使用这个软件应用，不需要本地安装。
用户只需要接上网络，并通过浏览器，就能直接使用在云端上运行应用，而不需要考虑类似安装等琐事，并且免去初期高昂的软硬件投入。SaaS主要面对的是普通用户。
主要的产品
salesforce sales cloud，Google Apps，Zimbra，Zoho和IBM Lotus Live等，也包括像网页番茄类似的软件。
功能
要把你的产品做成SaaS服务给别人使用，需要完成那些功能？
随时随地访问：在任何时候，任何地点，只要接上网络，用户就能访问这个SaaS服务。
支持公开协议：通过支持公开协议（比如Html4/5），能够方便用户使用。
安全保障：SaaS供应商需要提供一定的安全机制，不仅要使存储在云端的用户数据处于绝对安全的境地，而且也也要在客户端实施一定的安全机制（比如Https）来保护用户。
多用户：（Multi-Tenant）机制，通过多用户机制，不仅能更经济地支持庞大的用户规模，而且能提供一定的可指定性以满足用户的特殊需求。
PaaS
PaaS是Platform-as-a-Service的缩写，意识是平台即服务。通过Paas这种模式，用户可以在一个包括SDK，文档和测试环境等内的开发平台上非常方便的编写应用，而且不论是在部署，或者在运行无需为服务器，操作系统，网络和存储等资源管理操心，这些繁琐的工作都由PaaS供应商负责处理，而且PaaS在整合率上面是非常惊人，比如一台运行Google App Engine的服务器能够支撑成千上万的应用，也就是说，PaaS是非常经济的。PaaS主要的用户是开发人员。把服务器平台作为一种服务提供的商业模式。例如Sea，通过互联网就直接能使用的开发平台，不需要本地安装各类的开发环境。
产品
google App engine , force.com,heroku 和windows Azure Platform等。
作为PaaS的服务功能需求包括：
有好的开发环境：通过SDK和IDE等工具来让用户能在本地方便地进行应用的开发和测试。
丰富的服务：PaaS平台会以API的形式经各种各样的服务提供给上层应用。
自动的资源调度：也就是可伸缩特性，它不仅能优化系统资源，而且能自动调整资源来帮助运行于其上的应用更好地应对突发流量。
精细的管理和监控：通过PaaS能够提供应用层的管理和监控，比如，能够观察应用运行的情况和具体数值（比如吞吐量和反映时间）来更好地衡量应用的运行状态，还有能够通过精确计量应用使用所消耗的资源来更好的计费。
三者服务关系？
三者服务之间没有必然的联系，只是三种不同的服务模式，都是基于互联网，按需按时付费，就像水电、煤气一样，不能说有什么联系，又不能说完全没有联系。
但是在实际的商业模式中，Paas的发展确实促进了SaaS的发展，因为提供了开发平台后，SaaS的开发难度降低了。
从用户体验角度而言，他们之间的关系是独立的，因为他们面对的是不同的用户。
从技术角度而言，他们并不是简单的继承关系，因为SaaS可以是基于PaaS或者直接部署于IaaS之上，其次PaaS可以构建与IaaS之上，也可以直接构建在物理资源之上。
他们之间的关系如下图所示：
1：
2：
          
          
        
      </description>
    </item>
    
    <item>
      <title>iptables详解</title>
      <link>https://www.crs811.com/archives/596/</link>
      <pubDate>Mon, 07 Nov 2016 15:20:04 +0000</pubDate>
      
      <guid>https://www.crs811.com/archives/596/</guid>
      <description>
        
          
            一：前言 防火墙，其实说白了讲，就是用于实现Linux下访问控制的功能的，它分为硬件的或者软件的防火墙两种。无论是在哪个网络中，防火墙工作的地方一定是在网络的边缘。而我们的任务就是需要去定义到底防火墙如何工作，这就是防火墙的策略，规则，以达到让它对出入网络的IP、数据进行检测。 目前市面上比较常见的有3、4层的防火墙，叫网络层的防火墙，还有7层的防火墙，其实是代理层的网关。 对于TCP/IP的七层模型来讲，我们知道第三层是网络层，三层的防火墙会在这层对源地址和目标地址进行检测。但是对于七层的防火墙，不管你源端口或者目标端口，源地址或者目标地址是什么，都将对你所有的东西进行检查。所以，对于设计原理来讲，七层防火墙更加安全，但是这却带来了效率更低。所以市面上通常的防火墙方案，都是两者结合的。而又由于我们都需要从防火墙所控制的这个口来访问，所以防火墙的工作效率就成了用户能够访问数据多少的一个最重要的控制，配置的不好甚至有可能成为流量的瓶颈。 二：iptables 的历史以及工作原理 1.iptables的发展: iptables的前身叫ipfirewall （内核1.x时代）,这是一个作者从freeBSD上移植过来的，能够工作在内核当中的，对数据包进行检测的一款简易访问控制工具。但是ipfirewall工作功能极其有限(它需要将所有的规则都放进内核当中，这样规则才能够运行起来，而放进内核，这个做法一般是极其困难的)。当内核发展到2.x系列的时候，软件更名为ipchains，它可以定义多条规则，将他们串起来，共同发挥作用，而现在，它叫做iptables，可以将规则组成一个列表，实现绝对详细的访问控制功能。 他们都是工作在用户空间中，定义规则的工具，本身并不算是防火墙。它们定义的规则，可以让在内核空间当中的netfilter来读取，并且实现让防火墙工作。而放入内核的地方必须要是特定的位置，必须是tcp/ip的协议栈经过的地方。而这个tcp/ip协议栈必须经过的地方，可以实现读取规则的地方就叫做 netfilter.(网络过滤器) 作者一共在内核空间中选择了5个位置， 1.内核空间中：从一个网络接口进来，到另一个网络接口去的 2.数据包从内核流入用户空间的 3.数据包从用户空间流出的 4.进入/离开本机的外网接口 5.进入/离开本机的内网接口 2.iptables的工作机制 从上面的发展我们知道了作者选择了5个位置，来作为控制的地方，但是你有没有发现，其实前三个位置已经基本上能将路径彻底封锁了，但是为什么已经在进出的口设置了关卡之后还要在内部卡呢？ 由于数据包尚未进行路由决策，还不知道数据要走向哪里，所以在进出口是没办法实现数据过滤的。所以要在内核空间里设置转发的关卡，进入用户空间的关卡，从用户空间出去的关卡。那么，既然他们没什么用，那我们为什么还要放置他们呢？因为我们在做NAT和DNAT的时候，目标地址转换必须在路由之前转换。所以我们必须在外网而后内网的接口处进行设置关卡。 这五个位置也被称为五个钩子函数（hook functions）,也叫五个规则链。 1.PREROUTING (路由前) 2.INPUT (数据包流入口) 3.FORWARD (转发管卡) 4.OUTPUT(数据包出口) 5.POSTROUTING（路由后） 这是NetFilter规定的五个规则链，任何一个数据包，只要经过本机，必将经过这五个链中的其中一个链。 3.防火墙的策略 防火墙策略一般分为两种，一种叫“通”策略，一种叫“堵”策略，通策略，默认门是关着的，必须要定义谁能进。堵策略则是，大门是洞开的，但是你必须有身份认证，否则不能进。所以我们要定义，让进来的进来，让出去的出去，所以通，是要全通，而堵，则是要选择。当我们定义的策略的时候，要分别定义多条功能，其中：定义数据包中允许或者不允许的策略，filter过滤的功能，而定义地址转换的功能的则是nat选项。为了让这些功能交替工作，我们制定出了“表”这个定义，来定义、区分各种不同的工作功能和处理方式。 我们现在用的比较多个功能有3个： 1.filter 定义允许或者不允许的 2.nat 定义地址转换的 3.mangle功能:修改报文原数据 我们修改报文原数据就是来修改TTL的。能够实现将数据包的元数据拆开，在里面做标记/修改内容的。而防火墙标记，其实就是靠mangle来实现的。 小扩展: 对于filter来讲一般只能做在3个链上：INPUT ，FORWARD ，OUTPUT 对于nat来讲一般也只能做在3个链上：PREROUTING ，OUTPUT ，POSTROUTING 而mangle则是5个链都可以做：PREROUTING，INPUT，FORWARD，OUTPUT，POSTROUTING iptables/netfilter（这款软件）是工作在用户空间的，它可以让规则进行生效的，本身不是一种服务，而且规则是立即生效的。而我们iptables现在被做成了一个服务，可以进行启动，停止的。启动，则将规则直接生效，停止，则将规则撤销。 iptables还支持自己定义链。但是自己定义的链，必须是跟某种特定的链关联起来的。在一个关卡设定，指定当有数据的时候专门去找某个特定的链来处理，当那个链处理完之后，再返回。接着在特定的链中继续检查。 注意：规则的次序非常关键，谁的规则越严格，应该放的越靠前，而检查规则的时候，是按照从上往下的方式进行检查的。 三．规则的写法: iptables定义规则的方式比较复杂: 格式：iptables [-t table] COMMAND chain CRETIRIA -j ACTION -t table ：3个filter nat mangle COMMAND：定义如何对规则进行管理 chain：指定你接下来的规则到底是在哪个链上操作的，当定义策略的时候，是可以省略的 CRETIRIA:指定匹配标准 -j ACTION :指定如何进行处理 比如：不允许172.
          
          
        
      </description>
    </item>
    
    <item>
      <title>ubuntu 作 NAT 连接内外网</title>
      <link>https://www.crs811.com/archives/582/</link>
      <pubDate>Sat, 05 Nov 2016 04:25:20 +0000</pubDate>
      
      <guid>https://www.crs811.com/archives/582/</guid>
      <description>
        
          
            系统架构：vShpere 6.0
装3个虚拟机：
准备用ubuntu作NAT，winserver 和 CentOS 以ubuntu作出口
winserver 配置:
ip: 192.168.0.101/24
gateway: 192.168.0.1
centos7 的配置:
Ubuntu配置:
内部：192.168.0.1
外部：10.0.0.15
配置 NAT ：
1、
sudo vi /etc/sysctl.conf修改#net.ipv4.ip_forward=1如下：net.ipv4.ip_forward=1 保存退出，并执行下面的命令来生效它： sysctl -p 2、
外对内：
sudo iptables -t nat -A PREROUTING -d 10.0.0.15 -p tcp --dport 8880 -j DNAT --to 192.168.0.101:80 内对外：
sudo iptables -t nat -A POSTROUTING -s 192.168.0.101 -o eth0 -j MASQUERADE 设置开机启动并自动保存：
修改脚本 /etc/network/interfaces，使系统能自动应用这些规则pre-up iptables-restore &lt; /etc/iptables.up.rulespost-down iptables-restore &gt; /etc/iptables.
          
          
        
      </description>
    </item>
    
    <item>
      <title>Windows 下常用的小工具推荐</title>
      <link>https://www.crs811.com/archives/520/</link>
      <pubDate>Sat, 24 Sep 2016 08:57:47 +0000</pubDate>
      
      <guid>https://www.crs811.com/archives/520/</guid>
      <description>
        
          
            1、Listary
Listary Pro 是一款系统加强即时搜索软件，强调对搜索结果的各种处理，提高文件浏览体验，当开始输入文件名字时，将显示结果列表，弥补了系统搜索人性化的不足之处。可以从打开/保存文件对话框，文件管理器和其他应用程序即时访问最喜爱的文件夹和最近的文档
下载 &amp;gt;&amp;gt;
2、Everything
Everything是速度最快的专业文件搜索软件。其速度之快令人震惊，百G 硬盘几十万个文件，可以在几秒钟之内完成索引；文件名搜索瞬间呈现结果。
下载：http://www.voidtools.com/
3、CCleaner
一款免费的系统优化和隐私保护工具。CCleaner的主要用来清除Windows系统不再使用的垃圾文件，以腾出更多硬盘空间。它的另一大功能是清除使用者的上网记录。
CCleanerBT的体积小，运行速度极快，可以对文件夹、历史记录、回收站等进行垃圾清理，并可对注册表进行垃圾项扫描、清理。附带软件卸载功能。 同时支持IE、Firefox。免费使用，不含任何间谍软件和垃圾程序。支持包括简体中文在内的26国语言界面！
4、Cmder
作为一个程序员，即使是在windows工作环境，cmd也是我们必不可少的使用工具。
然而，windows发展了这么多年，cmd还是一如既往、毫无改进。
下面先列举cmd几大不能忍的“特性”
1.窗口size不能便捷缩放
2.复制文本，不能直接用鼠标拷贝，还需要多一道菜单操作；而且，还只能块状拷贝，而不是按行字符，极其不便
3.不支持多Tab页，多窗口管理不便
此外，cmd界面丑陋，只有黑白界面，而且不支持文字颜色区分。
Cmder是一款Windows环境下非常简洁美观易用的cmd替代者,它支持了大部分的Linux命令
从官网下载下来一个zip安装包，解压之后运行根目录的Cmder.exe即可。
有一个mini版本，几M大小，用来替代windows的cmd，上述几点诟病已经能够解决。
有一个full版本，100多M，模拟了一些常用Linux命令（比如ls、cat、more、cp、mv、rm、find、grep等），自带Git,而且自带vim。
下载：http://cmder.net
5、截图工具 Snipaste (支持高分屏)
主要功能是截图和贴图，以及取色
这款软件由国人Levie历时三年开发而成，完全免费使用，并且无广告，体积仅有12M！功能却逆天的强大，实乃居家旅行，办公学习必备利器！
4个实用功能:
1)、无需联网即可截图
按下截图快捷键【F1】即可截图，无需联网，光是这点就比QQ强。截图后你可以对图像进行划框、打马赛克、输入文字等操作
2)、贴图
贴图这个功能实在太强大了，我们先来看看最简单的使用方法！按【F1】截图，接着点击图钉的按钮（或者按快捷键F3），就可以把刚刚的截图“钉”在桌面上
3)、取色
这个功能对设计师们来说简直是福音
a.假如我们在网上看到了一个喜欢的颜色，你只需先按下【F1】键截图；
b.再把鼠标对准你要吸取的颜色，并按下【C】键，此时这个颜色就已经被记录下来了；
c.最后按下【F3】，你会发现桌面上多了个方框，这个方框里面就是这个颜色的各种格式的色值！
d.右击这个方框，你可以复制上面任意一种色值的数字。
4)、标注
截图后，可以方便的添加各种框，箭头，文字，非常方便
下载：Snipaste
6、任务栏工具 7 Taskbar Tweaker
Taskbar Tweaker是一个好用的小软件，它能够用来调整windows 7及以上系统的任务栏，通过添加功能，任务栏会变得更加的好用和符合你的使用习惯，整个调整过程十分简单，并且立刻生效
Taskbar Tweaker还可以调整windows 8,windowns 10左侧任务栏的宽度
默认：
调整后：（高级选项 &amp;gt;&amp;gt; no_width_limit &amp;gt;&amp;gt; 1）
能够对Windows 的任务栏做如下调整：
1、如果你不喜欢或者不习惯Windows 7的jump list功能，可以用它来转化为标准窗口菜单模式；
2、中键点击可新建程序实例，也可以设定为关闭或者激活新窗口；
3、可根据文件路径或者程序ID禁用窗口分组；
          
          
        
      </description>
    </item>
    
    <item>
      <title>Vim 常用快捷键和配置</title>
      <link>https://www.crs811.com/archives/512/</link>
      <pubDate>Mon, 19 Sep 2016 01:06:53 +0000</pubDate>
      
      <guid>https://www.crs811.com/archives/512/</guid>
      <description>
        
          
            vi有3个模式：插入模式、命令模式、末行模式
1）插入模式：在此模式下可以输入字符，按ESC将回到命令模式。
2）命令模式：可以移动光标、删除字符等。
3）末行模式：可以保存文件、退出vi、设置vi、查找等功能(低行模式也可以看作是命令模式里的)。
进入vi的命令
vi filename :打开或新建文件，并将光标置于第一行首
vi +n filename ：打开文件，并将光标置于第n行首
vi + filename ：打开文件，并将光标置于最后一行首
vi +/pattern filename：打开文件，并将光标置于第一个与pattern匹配的串处
vi -r filename ：在上次正用vi编辑时发生系统崩溃，恢复filename
vi -o/O filename1 filename2 ... ：打开多个文件，依次进行编辑
vi 关闭文件
:wq 保存修改并退出
ZZ 快捷键，保存修改并退出(前面没有冒号) :q! 不保存退出
:wq! 强行保存退出，(文件所属者科忽略文件的制度属性)
:w 保存不退出
:wqa 保存所有文件
:w new_filename 另存为指定文件
首先练习移动光标
H、L 向前，向后
J、K 向上，向下
w 移动光标到下一个单词.
b 移动光标到上一个单词.
0 移动光标到本行最开头.
$ 移动光标到本行结尾处.
H 移动光标到屏幕的首行.
M 移动光标到屏幕的中间一行.
L 移动光标到屏幕的尾行.
gg 移动光标到文档首行. G 移动光标到文档尾行. nG 移动光标到第n行，n是你代码的行号
          
          
        
      </description>
    </item>
    
    <item>
      <title>[转]留学硕士经历美国高等教育：学生勤奋程度远超中国</title>
      <link>https://www.crs811.com/archives/509/</link>
      <pubDate>Thu, 15 Sep 2016 14:04:43 +0000</pubDate>
      
      <guid>https://www.crs811.com/archives/509/</guid>
      <description>
        
          
            国内教育界总是在提改革高考制度，我们的高校应该实行西方那种宽进严出的政策，我在国内也听了多年了，但是对于“宽进严出”的印象只是一个名词罢了，并没有什么特别深的感触，而且也一直认为虽然西方宽 进严出，但是他们的学习还是太容易太简单了，我们国家的学生还是最强的。但是真正到了美国上了研究生后，才真正理解了什么叫做宽进严出，也认识到了我们与西方国家高等教育的差距。
在去美国之前，我想大部分国人和我一样认为，美国的教育都是人性化的教育，教育方式和观念都以人为本什么的。感觉美国的教育都是让学生一边玩，一边 学，一点也不痛苦，学生有很多课外业余爱好。总之一句话，他们是素质教育，我们是应试教育。而在好多人眼中，美国人都不怎么爱学习。学习很次，中国是个人 去了就可以称王等等。到这里学了以后，发现以前感觉的完全是扯淡的。美国的高等教育比中国还应试，美国的学生平均学习刻苦程度是中国学生不能比的。
我这学期学选了3门课，分别是经济学家数学，高级微观经济学，高级计量经济学。在开学初我在网上买的课本(这里的课本特别的贵，我都买的二手的书，还都100多美元 一本，有的学生买不起干脆复印)，需要运送几天，所以头一周，没有看书。微观经济学一上来为了检测我们的数学基础，就给我们发了一张数学卷子，里面涵盖了 本科阶段所有的数学课程：微积分，线性代数，概率论和数理统计，而且几乎每个知识点都有。
我由于大二学完数学到今年6年没有用过，所以忘得差不多了。所以我在周末两天草草看了一遍4本数学课本，然后比猫画虎的把题做了。当时听老师课上意思就是看看同学的数学水平，不怎么重要，就当作业留了。
在我的观念里，到了中学，尤其是高中，因为学习的比较难了，作业是可以不做了，严格说是不会的可以不做的，因为老师不收，大家在家只要努力做了，做不出来没关系，第二天老师会在课上讲。所以作业都是良心活，好学生都自觉完成了，实在不会的就放着。
我开始还是拿这个观念去对待美国老师的作业。当时看完书已经晚上10点多了，第二天要上这门课，我本来认为估计老师上课对对答案，有问题问问就可以， 估计没做完也没事。不过我还是凭着国内学习养成的老师给的良心活必做的习惯，坚持把题做完了。当时写到了半夜2点半多，其中好几次想放弃睡觉算了，不过最 后还是写完了。
我当时还说第一周就写到半夜两点半，当时觉得以后不会这样，这是我自己给自己施加的压力罢了。结果没想到，第二天上课，老师就真都把作业收了，亏了我 把卷子都写完了，否则就傻眼了。当时老师说收的时候，我心想还真收啊?后来逐渐才明白原来美国作业是计成绩的，每次作业都会给你按照对错打分，记出成绩， 最后和所有平时考试期末考试一起算最后的总成绩。
而且最让人接受不了的是，题你要是不会做，你不写，或者写错了，你就不得分，最后就会影响你的总成绩。在中国是，平时允许你犯错，允许你不会，你不会可以 空着，听老师讲，最后考试时会做就可以。因为从高中以后学得就比较难了，作业有不会做的很正常，老师是允许的。但是在美国就不一样了，老师每周都会给你留 一大堆作业，你在下周上课前要交上来，如果有不会的，你要在交作业前去自己去问老师，老师不会在课上给你讲的。如果到交作业时还没有问老师，因为不会不做 或者做错了，那么你就要承担这个责任，老师不会因为你实在不会就手下留情的，你的作业就会被扣分。每次作业老师都会记录的，最后会一起给你算总成绩的。
这样每周的作业都相当于一次考试，因为得的分数直接影响你最后的总成绩。第一次数学作业我和我们系的那个中国同学就因为没明白留没留作业而没交。我们 当时下课还问了留没留作业，老师说没留。结果第一次就没写也没交，好在好几个同学都没听懂，老师允许我们在第二天10点之前补交就可以。
最痛苦的是第一次计量经济学作业。计量经济学是我们这里面最难的课，基本就是统计学在经济学中的应用，而且这门课是最近几十年才兴起的，国内教得很 浅。虽然我本科学了经济应用统计学，数理统计学，计量经济学，三门统计计量相关的课程，但是学得实在是太浅了。以至于我一值认为统计学是门比较好学的课 程，因为我所学的统计学无非就是求求平均数，方差，各个统计指标，指标体系，即期，长期，同比，环比，GDP，GNP这些概念，最后最难的就是用最小二乘 法求一求线性回归。而且公式都是现成的，背背就可以了。计量无非就是多个误差项。数理统计就是求一求假设检验，都是程序化，模式化的东西。
但是在申请美国大学的过程中在论坛经常听他们说外国的经济学要求数学非常高，其中最难的就是计量经济学，还有统计学。数学和统计学最好申请，因为太 难，外国人没人去学。当时还不理解，为什么统计学这么难学，现在终于知道了。我们老师用了1堂多课就把前4章讲完了，前四章就涵盖了我本科学的最难的一元 线性回归和假设检验的所有内容。然后就留作业了。
到快交作业的前几天，我才拿到课本，于是赶紧做。由于本科学的早就忘光了，而且当时学数理统计的那一学期前半段出去背英语了，后半段给系里做网站呢， 那个老师又是个研究生，声音很小，彻底听不见，所以也就是到最后才把书看了看，然后按照背过的那个假设检验的程序做得期末考试题，就这样还过了，所以没有 怎么理解检验的机理，而且那门课讲了很多随机分布，正态分布，t分布，卡方分布，F分布等都不明白怎么回事，也就是记住了这几个名词可以去跟没学过的吓唬 吓唬人。但这都是检验的基础，所以心里一直觉得这一部分没有学扎实。以至于我在工作的四年中晚上经常做同一个噩梦，就是上大二最后一学期要考数理统计时， 我什么都不会，非常焦虑的情景。当时每次我都自己对自己说你已经上班了，以后不会再有考试了，这个情况永远也不可能发生了，这只是梦。但是还是一直在做这个噩梦。
现在感觉到这个噩梦快成现实了。为了做作业，用了几天把本科的概率论和数理统计又看了一遍，感觉还是没怎么看懂，然后就做作业，一点一点抠到凌晨5点 多，实在做不下去了，然后就交了。结果第二天发现老师留的截止日期是他上课的这一天晚上12点截止，而我在前一天以为是在他上课前需要要交，所以我还有一 晚上的时间，把昨天不会的给补上。
晚上和我们系的那个中国同学一起做的这个作业。他还好本科毕业后直接就来上硕士了，所以都没有忘。而且他本科是学生物的，生物虽然对数学要求不高，不 过对统计学要求很高，他的毕业论文就是用统计建立模型求的，而且他那篇论文还上了美国的SCI索引。(能上SCI的就很了不起了，整个我们省就没几个人能 上这个，我们学校还把能上这个的教授作为模范来对待)所以他还是比较懂，一边给我讲，一边看书才似懂非懂的(比本科时懂多了，但是感觉还是理解不太透彻)把这次作业做完。
后来发了作业，20分满分得了16分。看似分还可以但是仔细想想16分意味着什么?每个老师第一节课都会把这门这学期怎么学，有多少考试，有多少作业，考试 和作业各占最后总成绩的百分比列一个教学大纲告诉你。计量经济学这门课第一次期中考试占20%，第二次期中考试占20%，期末考试占20%，平时作业占 40%。(因为这门课主要是看你实际运用能力，而实际去通过最小二乘法估计模型需要大量繁琐的运算，要运用计算机程序配合才能完成。这个放在考试中是不现 实的，所以作业占了很大的部分。)
最后总成绩按照ABCD给你评分，90-100评A，80-90评B，70-8*河蟹*C，70以下D或者不及格。本身不及格的线就比国内60分提高了。 而且硕士研究生毕业有一项成绩要求就是每学期平均分不能低于B，否则下学期你就留校察看，如果再不行就被开除了。也就是硕士研究生的及格分数是平均80以 上。
如果是十分简单的学科考80分以上不算很难，关键是现在学得都是非常难的，作业和考试很难。所以如果保证所有科平均80以上，不是一件容易的事情。在 国内都知道如果是一门很难的课程，考80分就是相当不错了(不说数学这种难的课程，就拿英语来说，我们学校多少学生为了英语四级过60而奋斗四年，四级考 85分以上，六级考80分以上就算优秀了，好多同学都不敢奢望六级考试，我记得我有个同学考六级61分过了，就认为自己英语学的很不错了，然后就开始替别 人去考四级了，别人问他英语怎么样，他很自豪的说我都过6级了，别人一听也觉得，嗯，不错都过六级了，其实六级是个什么英语水平，六级的61分是个什么水 平，我给你个对比你就知道了，我的六级当时比他高了近20分，然后第一次做美国的托福听力，50个道题我就做上了7个。而要上美国研究生就要考GRE考 试，这个考试又比托福高出很多，被国内学生认为是上帝读的书(god read english)，以至于考完GRE再考托福的人不用复习就可以拿高分。
我考完GRE以后乐观的认为我把天下最难的考试考完了。以后什么都不怕了。结果我来了美国上课以后发现，GRE考试相对于现在学的这些东西简直太简单 了。在美国没有人去炫耀GRE考试成绩，他们认为这个不足挂齿。就在这个难度下，要保持科科80以上是个什么水平?这个水平就是美国硕士研究生的最低及格 线。低于它你就可以考虑回家了。
而且我估计了一下，难课程如果都保持80分左右就不错了，所以最后很有可能的结果是大部分都是B，然后如果都是B的话，只要有一科是C，那么平均就是 B以下，那么就可以走人了。而如果得C的这一科是因为平时考试和作业都是刚好80分或平均刚好80分，恰好有一次作业得79分(在中国，如果比较难的课程 这个成绩也算是好成绩了)，那么这一门课可能就因为这一次作业的80以下，造成最后这门课B以下(或者说C)，如果恰好其他课又都是B，那你很有可能平时 表现都不错就因为这一次作业的一分而被开除走人。
当然你要说哪里有这么恰好的事情，我说这个已经是很好的情况了，很有可能你的考试和作业会很多次上不了80分。我这次作业就是在悬崖边上：16 分，20分满分，看似不错，实际上16除以20等于0.8，也就是80分，已经是最低可以接受的分了。所以我以后作业必须要拿尽可能多的80分以上才能避 免因为有80分以下而最后失足的情况。所以这次只是刚刚及格。说完这三次不是很成功的第一次作业，再说说美国的考试。
我在国内时看学校主页上的这学期学习安排，说是10月7日左右期中考试。当时很紧张，认为那时自己到美国不到一个半月，语言估计都没过关怎么考试?然 后自己安慰自己也许是学科不同，可能有不同的安排吧。估计我们这个文科专业应该不会有期中考试的吧。期中考试对我来说已经8年没有遇到了，因为上了大学以 后，好像就没有期中考试，也许工科的同学有，不过我们经济这种文科的学科就没有了。期中成绩老师大多是以出勤率来计算，而且占30%，期末考试才是大头 70%，最多就是中期可能会有一片论文当作成绩参考。
所以我来之前一直有我们专业不会有期中考试的侥幸心理。结果上了第一周课我就傻了，所有3科都有期中考试，而且期中考试都不只一次，有的课是2次，有 的课是3次，加上期末考试，基本上每个月每门课都会有一次考试，这个我们在应试教育的中学感受过，不过那个叫做月考，或者小测，不计入最后成绩，而且那个 最后成绩对你也没有用，因为最后要看你的高考和中考成绩。而美国这个考试基本上是所有考试各占20%，作业占20%(有三次期中考试的比如我们这学期的数 学)，没有轻重。或者都是25%(有两次期中考试的)等，或者老师对这个评分比例进行微调，反正权重基本都是一样的，而且所有的这些平时成绩最后折算成的 总成绩会跟你一辈子，找工作时，用人单位会让你出示所有高等教育的平时成绩，因此你那次都不能马虎，包括作业。
          
          
        
      </description>
    </item>
    
    <item>
      <title>闭包(Closures) 4 – 理解Swift的闭包</title>
      <link>https://www.crs811.com/archives/497/</link>
      <pubDate>Fri, 02 Sep 2016 14:30:04 +0000</pubDate>
      
      <guid>https://www.crs811.com/archives/497/</guid>
      <description>
        
          
            我们可用swift的闭包来定义变量的值。 先来一个简单的例子大家先感受感受。
定义一个字符串的变量的方法：
直接赋值
var str=&amp;quot;JobDeer&amp;quot;
还可以用闭包的方式定义：
var str:String={
return &amp;quot;JobDeer&amp;quot;
}()
闭包还可以这么定义，省略了等号和括号：
var str:String{
return &amp;quot;JobDeer&amp;quot;
}
闭包中可以定义get方法。
var str:String{
get{
return &amp;quot;JobDeer&amp;quot;
}
}
既然用可以用get方法， 那么能用set方法吗？
可以的：
var str:String{
get{
return &amp;quot;JobDeer&amp;quot;
}
set{
println(&amp;quot;set ok&amp;quot;)
}
}
我们在用 willSet 和didSet方法试一试， 注意 用 willSet /didSet不能和get/set共同使用的， 在使用willSet /didSet时，变量需要有初始值。 所以这么使用：
var str:String=&amp;quot;JobDeer&amp;quot;{
willSet{
println(&amp;quot;newValue:(newValue)&amp;quot;)
}
didSet{
println(&amp;quot;oldValue:(oldValue)&amp;quot;)
}
}
str=&amp;quot;new value&amp;quot;
通过上面这个例子， 我们感觉闭包的表达实现形式很多。 下面系统总结一下。
最全的定义形式是 ：
{
(arguments) -&amp;gt;returnType in
          
          
        
      </description>
    </item>
    
    <item>
      <title>闭包(Closures) 3 – 图解闭包</title>
      <link>https://www.crs811.com/archives/493/</link>
      <pubDate>Thu, 01 Sep 2016 15:16:16 +0000</pubDate>
      
      <guid>https://www.crs811.com/archives/493/</guid>
      <description>
        
          
            说到 闭包 ，这是js不得不提的一个特性，很多传统语言都不具备这样的特性，比如JAVA C等等。
之前看书的时候，总是理解不好什么是闭包！下面就通过手绘一张原理图，来理解一下：
首先基本上所有的编程语言都有类似的特性，局部方法可以访问外部父类方法的属性，也就是说，子类或子方法可以访问父类的资源。
1var num = 11; 2function func1(){ 3console.log(num); 4} 5func1(); 因此上面的这段代码，我们可以获取到num的值。
父类能否获取到子方法内部的值呢？
1function func2(){ 2var num1 = 22; 3num2 = 33; 4} 5func2(); 6&amp;lt;!--console.log(num1); 会报错！--&amp;gt; 7 8console.log(num2); &amp;lt;!--可以获取到num2的值，因为不使用var定义变量时，默认是全局变量 --&amp;gt; 当然是不可以的，因为子方法的变量作用域仅仅是子方法的范围，外部是无法获取到的。
那么如何才能在外部获取到子方法的局部变量呢！
如果是java，一个类的私有属性，可以通过公共的get方法来获取，比如：
1class Person{ 2private String name; 3public String getName(){ 4return name; 5} 6} 通过上面的方式可以获取到一个类内部的私有属性，同样的，在js中可以通过某个方法来获取这个方法的局部变量，然后通过这个方法内的方法来读取想要的变量值。
1function func3(){ 2var num3 = 44; 3function func4(){ 4return num3; 5} 6return func4; 7} 8var func = func3(); 9console.log(func()); 参考下面的图解：
          
          
        
      </description>
    </item>
    
    <item>
      <title>闭包(Closures) – js中的闭包 2</title>
      <link>https://www.crs811.com/archives/490/</link>
      <pubDate>Thu, 01 Sep 2016 15:13:10 +0000</pubDate>
      
      <guid>https://www.crs811.com/archives/490/</guid>
      <description>
        
          
            理解 Javascript闭包:
越来越觉得国内没有教书育人的氛围，为了弄懂JS的闭包，我使出了我英语四级吃奶的劲去google上搜寻着有关闭包的解释，当我看到stackoverflow上这一篇解答，我脑中就出现了一句话：就是这货没跑了！
不才译文见下，见笑了。
Peter Mortensen问：
就像老Albert所说的，“如果你不能向一个六岁的孩子解释清楚，那么其实你自己根本就没弄懂。”好吧，我试着向一个27岁的朋友就是JS闭包（JavaScript closure）却彻底失败了。
你们会怎么把它解释给一个充满好奇心的六岁孩子听呢？
注：我看过StackOverflow上给出的示例，但根本没用。
Ali的回答：
当function里嵌套function时，内部的function可以访问外部function里的变量。
1function foo(x) { 2var tmp = 3; 3function bar(y) { 4alert(x + y + (++tmp)); 5} 6bar(10); 7} 8foo(2) 不管执行多少次，都会alert 16，因为bar能访问foo的参数x，也能访问foo的变量tmp。
但，这还不是闭包。当你return的是内部function时，就是一个闭包。内部function会close-over外部function的变量直到内部function结束。
1function foo(x) { 2var tmp = 3; 3return function (y) { 4alert(x + y + (++tmp)); 5} 6} 7var bar = foo(2); // bar 现在是一个闭包 8bar(10); 上面的脚本最终也会alert 16，因为虽然bar不直接处于foo的内部作用域，但bar还是能访问x和tmp。
但是，由于tmp仍存在于bar闭包的内部，所以它还是会自加1，而且你每次调用bar时它都会自加1.
（考虑到六岁这个限制：我们其实可以建立不止一个闭包方法，比如return它们的数组，也可以把它们设置为全局变量。它们全都指向相同的x和相同的tmp，而不是各自有一份副本。）
注：现在来整点儿七岁的内容。
上面的x是一个字面值（值传递），和JS里其他的字面值一样，当调用foo时，实参x的值被复制了一份，复制的那一份作为了foo的参数x。
那么问题来了，JS里处理object时是用到引用传递的，那么，你调用foo时传递一个object，foo函数return的闭包也会引用最初那个object！
1function foo(x) { 2var tmp = 3; 3return function (y) { 4alert(x + y + tmp); 5x.
          
          
        
      </description>
    </item>
    
    <item>
      <title>[转]程序员与线性代数 相关资源</title>
      <link>https://www.crs811.com/archives/537/</link>
      <pubDate>Mon, 29 Aug 2016 10:29:12 +0000</pubDate>
      
      <guid>https://www.crs811.com/archives/537/</guid>
      <description>
        
          
            关于线性代数学习的文章：
陈晓鸣（http://weibo.com/acumon），前百度资深工程师，终身学习者。
“文艺复兴记”（http://weibo.com/weidagang）。
文章的线索，先看到了《程序观点下的线性代数》。从应用的角度，该文把线性代数视为一门DSL。线性代数在初等数学基础上建立了向量模型，定义了一套语法和语义，符合程序语言的语言契约。向量模型具有坐标系无关性和线性性，它是整个线性代数的核心，是解决线性空间问题的最佳模型。
孟岩（http://blog.csdn.net/myan/）的《理解矩阵（一）》和《理解矩阵（二）》，指出线性代数属于“第二代数学模型”，试图引导读者品味其在表述方式和抽象性方面的全面进化。
还有一本书《线性代数应该这样学》，看豆瓣，该是学线性代数中的一本很好的参考书。
          
          
        
      </description>
    </item>
    
    <item>
      <title>[转] 理解矩阵</title>
      <link>https://www.crs811.com/archives/539/</link>
      <pubDate>Wed, 29 Jun 2016 20:00:26 +0000</pubDate>
      
      <guid>https://www.crs811.com/archives/539/</guid>
      <description>
        
          
            原文： http://blog.csdn.net/myan/article/details/647511
前不久chensh出于不可告人的目的，要充当老师，教别人线性代数。于是我被揪住就线性代数中一些务虚性的问题与他讨论了几次。很明显，chensh觉得，要让自己在讲线性代数的时候不被那位强势的学生认为是神经病，还是比较难的事情。
可怜的chensh，谁让你趟这个地雷阵？！色令智昏啊！
线性代数课程，无论你从行列式入手还是直接从矩阵入手，从一开始就充斥着莫名其妙。比如说，在全国一般工科院系教学中应用最广泛的同济线性代数教材（现在到了第四版），一上来就介绍逆序数这个“前无古人，后无来者”的古怪概念，然后用逆序数给出行列式的一个极不直观的定义，接着是一些简直犯傻的行列式性质和习题——把这行乘一个系数加到另一行上，再把那一列减过来，折腾得那叫一个热闹，可就是压根看不出这个东西有嘛用。大多数像我一样资质平庸的学生到这里就有点犯晕：连这是个什么东西都模模糊糊的，就开始钻火圈表演了，这未免太“无厘头”了吧！于是开始有人逃课，更多的人开始抄作业。这下就中招了，因为其后的发展可以用一句峰回路转来形容，紧跟着这个无厘头的行列式的，是一个同样无厘头但是伟大的无以复加的家伙的出场——矩阵来了！多年之后，我才明白，当老师犯傻似地用中括号把一堆傻了吧叽的数括起来，并且不紧不慢地说：“这个东西叫做矩阵”的时候，我的数学生涯掀开了何等悲壮辛酸、惨绝人寰的一幕！自那以后，在几乎所有跟“学问”二字稍微沾点边的东西里，矩阵这个家伙从不缺席。对于我这个没能一次搞定线性代数的笨蛋来说，矩阵老大的不请自来每每搞得我灰头土脸，头破血流。长期以来，我在阅读中一见矩阵，就如同阿Q见到了假洋鬼子，揉揉额角就绕道走。
事实上，我并不是特例。一般工科学生初学线性代数，通常都会感到困难。这种情形在国内外皆然。瑞典数学家Lars Garding在其名著Encounter with Mathematics中说：“如果不熟悉线性代数的概念，要去学习自然科学，现在看来就和文盲差不多。”，然而“按照现行的国际标准，线性代数是通过公理化来表述的，它是第二代数学模型，...，这就带来了教学上的困难。”事实上，当我们开始学习线性代数的时候，不知不觉就进入了“第二代数学模型”的范畴当中，这意味着数学的表述方式和抽象性有了一次全面的进化，对于从小一直在“第一代数学模型”，即以实用为导向的、具体的数学模型中学习的我们来说，在没有并明确告知的情况下进行如此剧烈的paradigm shift，不感到困难才是奇怪的。
大部分工科学生，往往是在学习了一些后继课程，如数值分析、数学规划、矩阵论之后，才逐渐能够理解和熟练运用线性代数。即便如此，不少人即使能够很熟练地以线性代数为工具进行科研和应用工作，但对于很多这门课程的初学者提出的、看上去是很基础的问题却并不清楚。比如说：
* 矩阵究竟是什么东西？向量可以被认为是具有n个相互独立的性质（维度）的对象的表示，矩阵又是什么呢？我们如果认为矩阵是一组列（行）向量组成的新的复合向量的展开式，那么为什么这种展开式具有如此广泛的应用？特别是，为什么偏偏二维的展开式如此有用？如果矩阵中每一个元素又是一个向量，那么我们再展开一次，变成三维的立方阵，是不是更有用？
* 矩阵的乘法规则究竟为什么这样规定？为什么这样一种怪异的乘法规则却能够在实践中发挥如此巨大的功效？很多看上去似乎是完全不相关的问题，最后竟然都归结到矩阵的乘法，这难道不是很奇妙的事情？难道在矩阵乘法那看上去莫名其妙的规则下面，包含着世界的某些本质规律？如果是的话，这些本质规律是什么？
* 行列式究竟是一个什么东西？为什么会有如此怪异的计算规则？行列式与其对应方阵本质上是什么关系？为什么只有方阵才有对应的行列式，而一般矩阵就没有（不要觉得这个问题很蠢，如果必要，针对m x n矩阵定义行列式不是做不到的，之所以不做，是因为没有这个必要，但是为什么没有这个必要）？而且，行列式的计算规则，看上去跟矩阵的任何计算规则都没有直观的联系，为什么又在很多方面决定了矩阵的性质？难道这一切仅是巧合？
* 矩阵为什么可以分块计算？分块计算这件事情看上去是那么随意，为什么竟是可行的？
* 对于矩阵转置运算AT，有(AB)T = BTAT，对于矩阵求逆运算A-1，有(AB)-1 = B-1A-1。两个看上去完全没有什么关系的运算，为什么有着类似的性质？这仅仅是巧合吗？
* 为什么说P-1AP得到的矩阵与A矩阵“相似”？这里的“相似”是什么意思？
* 特征值和特征向量的本质是什么？它们定义就让人很惊讶，因为Ax =λx，一个诺大的矩阵的效应，竟然不过相当于一个小小的数λ，确实有点奇妙。但何至于用“特征”甚至“本征”来界定？它们刻划的究竟是什么？
这样的一类问题，经常让使用线性代数已经很多年的人都感到为难。就好像大人面对小孩子的刨根问底，最后总会迫不得已地说“就这样吧，到此为止”一样，面对这样的问题，很多老手们最后也只能用：“就是这么规定的，你接受并且记住就好”来搪塞。然而，这样的问题如果不能获得回答，线性代数对于我们来说就是一个粗暴的、不讲道理的、莫名其妙的规则集合，我们会感到，自己并不是在学习一门学问，而是被不由分说地“抛到”一个强制的世界中，只是在考试的皮鞭挥舞之下被迫赶路，全然无法领略其中的美妙、和谐与统一。直到多年以后，我们已经发觉这门学问如此的有用，却仍然会非常迷惑：怎么这么凑巧？
我认为，这是我们的线性代数教学中直觉性丧失的后果。上述这些涉及到“如何能”、“怎么会”的问题，仅仅通过纯粹的数学证明来回答，是不能令提问者满意的。比如，如果你通过一般的证明方法论证了矩阵分块运算确实可行，那么这并不能够让提问者的疑惑得到解决。他们真正的困惑是：矩阵分块运算为什么竟然是可行的？究竟只是凑巧，还是说这是由矩阵这种对象的某种本质所必然决定的？如果是后者，那么矩阵的这些本质是什么？只要对上述那些问题稍加考虑，我们就会发现，所有这些问题都不是单纯依靠数学证明所能够解决的。像我们的教科书那样，凡事用数学证明，最后培养出来的学生，只能熟练地使用工具，却欠缺真正意义上的理解。
自从1930年代法国布尔巴基学派兴起以来，数学的公理化、系统性描述已经获得巨大的成功，这使得我们接受的数学教育在严谨性上大大提高。然而数学公理化的一个备受争议的副作用，就是一般数学教育中直觉性的丧失。数学家们似乎认为直觉性与抽象性是矛盾的，因此毫不犹豫地牺牲掉前者。然而包括我本人在内的很多人都对此表示怀疑，我们不认为直觉性与抽象性一定相互矛盾，特别是在数学教育中和数学教材中，帮助学生建立直觉，有助于它们理解那些抽象的概念，进而理解数学的本质。反之，如果一味注重形式上的严格性，学生就好像被迫进行钻火圈表演的小白鼠一样，变成枯燥的规则的奴隶。
对于线性代数的类似上述所提到的一些直觉性的问题，两年多来我断断续续地反复思考了四、五次，为此阅读了好几本国内外线性代数、数值分析、代数和数学通论性书籍，其中像前苏联的名著《数学：它的内容、方法和意义》、龚昇教授的《线性代数五讲》、前面提到的Encounter with Mathematics（《数学概观》）以及Thomas A. Garrity的《数学拾遗》都给我很大的启发。不过即使如此，我对这个主题的认识也经历了好几次自我否定。比如以前思考的一些结论曾经写在自己的blog里，但是现在看来，这些结论基本上都是错误的。因此打算把自己现在的有关理解比较完整地记录下来，一方面是因为我觉得现在的理解比较成熟了，可以拿出来与别人探讨，向别人请教。另一方面，如果以后再有进一步的认识，把现在的理解给推翻了，那现在写的这个snapshot也是很有意义的。
因为打算写得比较多，所以会分几次慢慢写。也不知道是不是有时间慢慢写完整，会不会中断，写着看吧。
--------------------------------------------------------------------------
今天先谈谈对线形空间和矩阵的几个核心概念的理解。这些东西大部分是凭着自己的理解写出来的，基本上不抄书，可能有错误的地方，希望能够被指出。但我希望做到直觉，也就是说能把数学背后说的实质问题说出来。
首先说说空间(space)，这个概念是现代数学的命根子之一，从拓扑空间开始，一步步往上加定义，可以形成很多空间。线形空间其实还是比较初级的，如果在里面定义了范数，就成了赋范线性空间。赋范线性空间满足完备性，就成了巴那赫空间；赋范线性空间中定义角度，就有了内积空间，内积空间再满足完备性，就得到希尔伯特空间。
总之，空间有很多种。你要是去看某种空间的数学定义，大致都是“存在一个集合，在这个集合上定义某某概念，然后满足某些性质”，就可以被称为空间。这未免有点奇怪，为什么要用“空间”来称呼一些这样的集合呢？大家将会看到，其实这是很有道理的。
我们一般人最熟悉的空间，毫无疑问就是我们生活在其中的（按照牛顿的绝对时空观）的三维空间，从数学上说，这是一个三维的欧几里德空间，我们先不管那么多，先看看我们熟悉的这样一个空间有些什么最基本的特点。仔细想想我们就会知道，这个三维的空间：1. 由很多（实际上是无穷多个）位置点组成；2. 这些点之间存在相对的关系；3. 可以在空间中定义长度、角度；4. 这个空间可以容纳运动，这里我们所说的运动是从一个点到另一个点的移动（变换），而不是微积分意义上的“连续”性的运动，
上面的这些性质中，最最关键的是第4条。第1、2条只能说是空间的基础，不算是空间特有的性质，凡是讨论数学问题，都得有一个集合，大多数还得在这个集合上定义一些结构（关系），并不是说有了这些就算是空间。而第3条太特殊，其他的空间不需要具备，更不是关键的性质。只有第4条是空间的本质，也就是说，容纳运动是空间的本质特征。
认识到了这些，我们就可以把我们关于三维空间的认识扩展到其他的空间。事实上，不管是什么空间，都必须容纳和支持在其中发生的符合规则的运动（变换）。你会发现，在某种空间中往往会存在一种相对应的变换，比如拓扑空间中有拓扑变换，线性空间中有线性变换，仿射空间中有仿射变换，其实这些变换都只不过是对应空间中允许的运动形式而已。
因此只要知道，“空间”是容纳运动的一个对象集合，而变换则规定了对应空间的运动。
下面我们来看看线性空间。线性空间的定义任何一本书上都有，但是既然我们承认线性空间是个空间，那么有两个最基本的问题必须首先得到解决，那就是：
1. 空间是一个对象集合，线性空间也是空间，所以也是一个对象集合。那么线性空间是什么样的对象的集合？或者说，线性空间中的对象有什么共同点吗？
2. 线性空间中的运动如何表述的？也就是，线性变换是如何表示的？
我们先来回答第一个问题，回答这个问题的时候其实是不用拐弯抹角的，可以直截了当的给出答案。线性空间中的任何一个对象，通过选取基和坐标的办法，都可以表达为向量的形式。通常的向量空间我就不说了，举两个不那么平凡的例子：
L1. 最高次项不大于n次的多项式的全体构成一个线性空间，也就是说，这个线性空间中的每一个对象是一个多项式。如果我们以x, x1, ..., xn为基，那么任何一个这样的多项式都可以表达为一组n+1维向量，其中的每一个分量ai其实就是多项式中x(i-1)项的系数。值得说明的是，基的选取有多种办法，只要所选取的那一组基线性无关就可以。这要用到后面提到的概念了，所以这里先不说，提一下而已。
L2. 闭区间[a, b]上的n阶连续可微函数的全体，构成一个线性空间。也就是说，这个线性空间的每一个对象是一个连续函数。对于其中任何一个连续函数，根据魏尔斯特拉斯定理，一定可以找到最高次项不大于n的多项式函数，使之与该连续函数的差为0，也就是说，完全相等。这样就把问题归结为L1了。后面就不用再重复了。
所以说，向量是很厉害的，只要你找到合适的基，用向量可以表示线性空间里任何一个对象。这里头大有文章，因为向量表面上只是一列数，但是其实由于它的有序性，所以除了这些数本身携带的信息之外，还可以在每个数的对应位置上携带信息。为什么在程序设计中数组最简单，却又威力无穷呢？根本原因就在于此。这是另一个问题了，这里就不说了。
下面来回答第二个问题，这个问题的回答会涉及到线性代数的一个最根本的问题。
线性空间中的运动，被称为线性变换。也就是说，你从线性空间中的一个点运动到任意的另外一个点，都可以通过一个线性变化来完成。那么，线性变换如何表示呢？很有意思，在线性空间中，当你选定一组基之后，不仅可以用一个向量来描述空间中的任何一个对象，而且可以用矩阵来描述该空间中的任何一个运动（变换）。而使某个对象发生对应运动的方法，就是用代表那个运动的矩阵，乘以代表那个对象的向量。
          
          
        
      </description>
    </item>
    
    <item>
      <title>[转] 程序观点下的线性代数</title>
      <link>https://www.crs811.com/archives/542/</link>
      <pubDate>Wed, 29 Jun 2016 13:15:12 +0000</pubDate>
      
      <guid>https://www.crs811.com/archives/542/</guid>
      <description>
        
          
            原文：http://www.cnblogs.com/weidagang2046/p/linear-algebra-from-programming-perspective.html
线性代数是什么？ 在大学数学学科中，线性代数是最为抽象的一门课，从初等数学到线性代数的思维跨度比微积分和概率统计要大得多。很多人学过以后一直停留在知其然不知其所以然的阶段，若干年之后接触图形编程或机器学习等领域才发现线性代数的应用无处不在，但又苦于不能很好地理解和掌握。的确，多数人很容易理解初等数学的各种概念，函数、方程、数列一切都那么的自然，但是一进入线性代数的世界就好像来到了另一个陌生的世界，在各种奇怪的符号和运算里迷失了。
线性代数是什么？ 在大学数学学科中，线性代数是最为抽象的一门课，从初等数学到线性代数的思维跨度比微积分和概率统计要大得多。很多人学过以后一直停留在知其然不知其所以然的阶段，若干年之后接触图形编程或机器学习等领域才发现线性代数的应用无处不在，但又苦于不能很好地理解和掌握。的确，多数人很容易理解初等数学的各种概念，函数、方程、数列一切都那么的自然，但是一进入线性代数的世界就好像来到了另一个陌生的世界，在各种奇怪的符号和运算里迷失了。
我在初接触线性代数的时候简直感觉这是一门天外飞仙的学科，一个疑问在我脑子里浮现出来：
线性代数到底是一种客观的自然规律还是人为的设计？
如果看到这个问题，你的反应是“这还用问，数学当然是客观的自然规律了”，我一点儿都不觉得奇怪，我自己也曾这样认为。从中学的初等数学和初等物理一路走来，很少人去怀疑一门数学学科是不是自然规律，当我学习微积分、概率统计时也从来没有怀疑过，唯独线性代数让我产生了怀疑，因为它的各种符号和运算规则太抽象太奇怪，完全对应不到生活经验。所以，我还真要感谢线性代数，它引发了我去思考一门数学学科的本质。其实，不止是学生，包括很多数学老师都不清楚线性代数到底是什么、有什么用，不仅国内如此，在国外也是这样，国内的孟岩写过《理解矩阵》，国外的Sheldon Axler教授写过《线性代数应该这样学》，但都还没有从根本上讲清楚线性代数的来龙去脉。对于我自己来讲，读大学的时候没有学懂线性代数，反而是后来从编程的角度理解了它。很多人说数学好可以帮助编程，我恰好反过来了，对程序的理解帮助了我理解数学。
本文的目标读者是程序员，下面我就带各位做一次程序员在线性代数世界的深度历险！既然是程序员，在进入线性代数的领域之前，我们不妨先从考察一番程序世界，请思考这样一个问题：
计算机里面有汇编、C/C++、Java、Python等通用语言，还有Makefile、CSS、SQL等DSL，这些语言是一种客观的自然规律还是人为的设计呢？
为什么要问这样一个看起来很蠢的问题呢？因为它的答案显而易见，大家对天天使用的程序语言的认识一定胜过抽象的线性代数，很显然程序语言虽然包含了内在的逻辑，但它们本质上都是人为的设计。所有程序语言的共同性在于：建立了一套模型，定义了一套语法，并将每种语法映射到特定的语义。程序员和语言实现者之间遵守语言契约：程序员保证代码符合语言的语法，编译器/解释器保证代码执行的结果符合语法相应的语义。比如，C++规定用new A()语法在堆上构造对象A，你这样写了C++就必须保证相应的执行效果，在堆上分配内存并调用A的构造函数，否则就是编译器违背语言契约。
从应用的角度，我们能不能把线性代数视为一门程序语言呢？答案是肯定的，我们可以用语言契约作为标准来试试。假设你有一个图像，你想把它旋转60度，再沿x轴方向拉伸2倍；线性代数告诉你，“行！你按我的语法构造一个矩阵，再按矩阵乘法规则去乘你的图像，我保证结果就是你想要的”。实际上，线性代数和SQL这样的DSL非常相似，下面来作一些类比：
模型和语义：SQL是在低级语言之上建立了关系模型，核心语义是关系和关系运算；线性代数在初等数学之上建立了向量模型，核心语义是向量和线性变换
语法：SQL为每种语义定义了相应的语法，如select, where, join等；线性代数也定义了向量、矩阵、矩阵乘法等语义概念相应的语法
编译/解释：SQL可以被编译/解释为C语言；线性代数相关概念和运算规则可以由初等数学知识来解释
实现：我们可以在MySQL、Oracle等关系数据库上进行SQL编程；我们也可以在MATLAB、Mathematica等数学软件上进行线性代数编程
所以，从应用的角度看，线性代数是一种人为设计的领域特定语言(DSL)，它建立了一套模型并通过符号系统完成语法和语义的映射。实际上，向量、矩阵、运算规则的语法和语义都是人为的设计，这和一门语言中的各种概念性质相同，它是一种创造，但是前提是必须满足语言契约。
为什么要有线性代数？ 可能有人对把线性代数当成一门DSL不放心，我给你一个矩阵，你就把我的图形旋转了60度沿x轴拉伸了2倍，我总感觉不踏实啊，我都不知道你“底层”是怎么做！其实，这就像有的程序员用高级语言不踏实，觉得底层才是程序的本质，老是想知道这句话编译成汇编是什么样？那个操作又分配了多少内存？别人在Shell里直接敲一个wget命令就能取下一个网页，他非要用C语言花几十分钟来写一堆代码才踏实。其实，所谓底层和上层只是一种习惯性的说法，并不是谁比谁更本质。程序的编译和解释本质上是不同模型间的语义映射，通常情况下是高级语言映射为低级语言，但是完全也可以把方向反过来。Fabrice Bellard用JavaScript写了一个虚拟机，把Linux跑在JavaScript虚拟机上，这就是把机器模型往JavaScript模型上映射。
建立新模型肯定依赖于现有的模型，但这是建模的手段而不是目的，任何一种新模型的目的都为了更简单地分析和解决某一类问题。线性代数在建立的时候，它的各种概念和运算规则依赖于初等数学的知识，但是一旦建立起来这层抽象模型之后，我们就应该习惯于直接利用高层次的抽象模型去分析和解决问题。说到线性代数是为了比初等数学更容易地分析和解决问题，下面我们通过一个例子来实际感受一下它的好处：
给定三角形的顶点(x1, y1), (x2, y2), (x3, y3)，求三角形的面积。
初等数学中三角形面积最著名的计算公式是area = 1/2 * base * height ，当三角形有一条边恰好在坐标轴上时我们就很容易算出它的面积。但是，假如同样一个三角形我们把坐标轴旋转一下，让它的边不在坐标轴上，怎么办？我们还能得到它的底和高吗？答案肯定是可以的，但是就明显复杂了，而且还要分很多种情况去分别讨论。
相反，如果我们用线性代数知识来解决这个问题就非常轻松。在线性代数中两个向量a，b的叉积(Cross Product)是一个向量，其方向与a，b垂直，其大小等于a，b构成的平行四边形的面积:
我们可以把三角形的边视为向量，所以三角形的面积等于两个边向量的叉积向量的长度除以二：
area = 1/2 * length(cross_product((x2 - x1, y2 - y1), (x3 - x1, y3 - y1)))注：length表示取向量长度，cross_product表示两个向量的叉积。
这样一个在初等数学里面有点儿小难的问题在线性代数中瞬间搞定！可能有人会说，你直接基于叉积来做，当然简单了，但是叉积本身不是也挺复杂的吗？你把它展开试试看呢？是的，模型的作用就是把一部分复杂性隐藏到模型中，使得模型的使用者可以更加简单地解决问题。曾经有人质疑C++太复杂，C++之父Bjarne Stroustrup这样回答：
Complexity will go somewhere: if not the language then the application code.
          
          
        
      </description>
    </item>
    
    <item>
      <title>P问题、NP问题、NPC问题、NP难问题的概念</title>
      <link>https://www.crs811.com/archives/524/</link>
      <pubDate>Tue, 28 Jun 2016 02:24:03 +0000</pubDate>
      
      <guid>https://www.crs811.com/archives/524/</guid>
      <description>
        
          
            ** **澄清P问题、NP问题、NPC问题的概念
这或许是众多OIer最大的误区之一。
你会经常看到网上出现“这怎么做，这不是NP问题吗”、“这个只有搜了，这已经被证明是NP问题了”之类的话。你要知道，大多数人此时所说的NP问题其实都是指的NPC问题。他们没有搞清楚NP问题和NPC问题的概念。NP问题并不是那种“只有搜才行”的问题，NPC问题才是。好，行了，基本上这个误解已经被澄清了。下面的内容都是在讲什么是P问题，什么是NP问题，什么是NPC问题，你如果不是很感兴趣就可以不看了。接下来你可以看到，把NP问题当成是NPC问题是一个多大的错误。
还是先用几句话简单说明一下时间复杂度。时间复杂度并不是表示一个程序解决问题需要花多少时间，而是当问题规模扩大后，程序需要的时间长度增长得有多快。也就是说，对于高速处理数据的计算机来说，处理某一个特定数据的效率不能衡量一个程序的好坏，而应该看当这个数据的规模变大到数百倍后，程序运行时间是否还是一样，或者也跟着慢了数百倍，或者变慢了数万倍。不管数据有多大，程序处理花的时间始终是那么多的，我们就说这个程序很好，具有O(1)的时间复杂度，也称常数级复杂度；数据规模变得有多大，花的时间也跟着变得有多长，这个程序的时间复杂度就是O(n)，比如找n个数中的最大值；而像冒泡排序、插入排序等，数据扩大2倍，时间变慢4倍的，属于O(n^2)的复杂度。还有一些穷举类的算法，所需时间长度成几何阶数上涨，这就是O(a^n)的指数级复杂度，甚至O(n!)的阶乘级复杂度。不会存在O(2n^2)的复杂度，因为前面的那个“2”是系数，根本不会影响到整个程序的时间增长。同样地，O(n^3+n^2)的复杂度也就是O(n^3)的复杂度。因此，我们会说，一个O(0.01n^3)的程序的效率比O(100*n^2)的效率低，尽管在n很小的时候，前者优于后者，但后者时间随数据规模增长得慢，最终O(n^3)的复杂度将远远超过O(n^2)。我们也说，O(n^100)的复杂度小于O(1.01^n)的复杂度。
容易看出，前面的几类复杂度被分为两种级别，其中后者的复杂度无论如何都远远大于前者：一种是O(1),O(log(n)),O(n^a)等，我们把它叫做多项式级的复杂度，因为它的规模n出现在底数的位置；另一种是O(a^n)和O(n!)型复杂度，它是非多项式级的，其复杂度计算机往往不能承受。当我们在解决一个问题时，我们选择的算法通常都需要是多项式级的复杂度，非多项式级的复杂度需要的时间太多，往往会超时，除非是数据规模非常小。
自然地，人们会想到一个问题：会不会所有的问题都可以找到复杂度为多项式级的算法呢？很遗憾，答案是否定的。有些问题甚至根本不可能找到一个正确的算法来，这称之为“不可解问题”(Undecidable Decision Problem)。The Halting Problem就是一个著名的不可解问题，在我的MSN Space上有过专门的介绍和证明。再比如，输出从1到n这n个数的全排列。不管你用什么方法，你的复杂度都是阶乘级，因为你总得用阶乘级的时间打印出结果来。有人说，这样的“问题”不是一个“正规”的问题，正规的问题是让程序解决一个问题，输出一个“YES”或“NO”（这被称为判定性问题），或者一个什么什么的最优值（这被称为最优化问题）。那么，根据这个定义，我也能举出一个不大可能会有多项式级算法的问题来： Hamilton回路。问题是这样的：给你一个图，问你能否找到一条经过每个顶点一次且恰好一次（不遗漏也不重复）最后又走回来的路（满足这个条件的路径叫做Hamilton回路）。这个问题现在还没有找到多项式级的算法。事实上，这个问题就是我们后面要说的NPC问题。
下面引入P类问题的概念：如果一个问题可以找到一个能在多项式的时间里解决它的算法，那么这个问题就属于P问题。P是英文单词多项式的第一个字母。哪些问题是P类问题呢？通常NOI和NOIP不会出不属于P类问题的题目。我们常见到的一些信息奥赛的题目都是P问题。道理很简单，一个用穷举换来的非多项式级时间的超时程序不会涵盖任何有价值的算法。
接下来引入NP问题的概念。这个就有点难理解了，或者说容易理解错误。在这里强调（回到我竭力想澄清的误区上），NP问题不是非P类问题。NP问题是指可以在多项式的时间里验证一个解的问题。NP问题的另一个定义是，可以在多项式的时间里猜出一个解的问题。比方说，我RP很好，在程序中需要枚举时，我可以一猜一个准。现在某人拿到了一个求最短路径的问题，问从起点到终点是否有一条小于100个单位长度的路线。它根据数据画好了图，但怎么也算不出来，于是来问我：你看怎么选条路走得最少？我说，我RP很好，肯定能随便给你指条很短的路出来。然后我就胡乱画了几条线，说就这条吧。那人按我指的这条把权值加起来一看，嘿，神了，路径长度98，比100小。于是答案出来了，存在比100小的路径。别人会问他这题怎么做出来的，他就可以说，因为我找到了一个比100小的解。在这个题中，找一个解很困难，但验证一个解很容易。验证一个解只需要O(n)的时间复杂度，也就是说我可以花O(n)的时间把我猜的路径的长度加出来。那么，只要我RP好，猜得准，我一定能在多项式的时间里解决这个问题。我猜到的方案总是最优的，不满足题意的方案也不会来骗我去选它。这就是NP问题。当然有不是NP问题的问题，即你猜到了解但是没用，因为你不能在多项式的时间里去验证它。下面我要举的例子是一个经典的例子，它指出了一个目前还没有办法在多项式的时间里验证一个解的问题。很显然，前面所说的Hamilton回路是NP问题，因为验证一条路是否恰好经过了每一个顶点非常容易。但我要把问题换成这样：试问一个图中是否不存在Hamilton回路。这样问题就没法在多项式的时间里进行验证了，因为除非你试过所有的路，否则你不敢断定它“没有Hamilton回路”。
之所以要定义NP问题，是因为通常只有NP问题才可能找到多项式的算法。我们不会指望一个连多项式地验证一个解都不行的问题存在一个解决它的多项式级的算法。相信读者很快明白，信息学中的号称最困难的问题——“NP问题”，实际上是在探讨NP问题与P类问题的关系。
很显然，所有的P类问题都是NP问题。也就是说，能多项式地解决一个问题，必然能多项式地验证一个问题的解——既然正解都出来了，验证任意给定的解也只需要比较一下就可以了。关键是，人们想知道，是否所有的NP问题都是P类问题。我们可以再用集合的观点来说明。如果把所有P类问题归为一个集合P中，把所有NP问题划进另一个集合NP中，那么，显然有P属于NP。现在，所有对NP问题的研究都集中在一个问题上，即究竟是否有P=NP？通常所谓的“NP问题”，其实就一句话：证明或推翻P=NP。
NP问题一直都是信息学的巅峰。巅峰，意即很引人注目但难以解决。在信息学研究中，这是一个耗费了很多时间和精力也没有解决的终极问题，好比物理学中的大统一和数学中的歌德巴赫猜想等。
目前为止这个问题还“啃不动”。但是，一个总的趋势、一个大方向是有的。人们普遍认为，P=NP不成立，也就是说，多数人相信，存在至少一个不可能有多项式级复杂度的算法的NP问题。人们如此坚信P≠NP是有原因的，就是在研究NP问题的过程中找出了一类非常特殊的NP问题叫做NP-完全问题，也即所谓的NPC问题。C是英文单词“完全”的第一个字母。正是NPC问题的存在，使人们相信P≠NP。下文将花大量篇幅介绍NPC问题，你从中可以体会到NPC问题使P=NP变得多么不可思议。
为了说明NPC问题，我们先引入一个概念——约化(Reducibility，有的资料上叫“归约”)。
简单地说，一个问题A可以约化为问题B的含义即是，可以用问题B的解法解决问题A，或者说，问题A可以“变成”问题B。《算法导论》上举了这么一个例子。比如说，现在有两个问题：求解一个一元一次方程和求解一个一元二次方程。那么我们说，前者可以约化为后者，意即知道如何解一个一元二次方程那么一定能解出一元一次方程。我们可以写出两个程序分别对应两个问题，那么我们能找到一个“规则”，按照这个规则把解一元一次方程程序的输入数据变一下，用在解一元二次方程的程序上，两个程序总能得到一样的结果。这个规则即是：两个方程的对应项系数不变，一元二次方程的二次项系数为0。按照这个规则把前一个问题转换成后一个问题，两个问题就等价了。同样地，我们可以说，Hamilton回路可以约化为TSP问题(Travelling Salesman Problem，旅行商问题)：在Hamilton回路问题中，两点相连即这两点距离为0，两点不直接相连则令其距离为1，于是问题转化为在TSP问题中，是否存在一条长为0的路径。 Hamilton回路存在当且仅当TSP问题中存在长为0的回路。
“问题A可约化为问题B”有一个重要的直观意义：B的时间复杂度高于或者等于A的时间复杂度。也就是说，问题A不比问题B难。这很容易理解。既然问题A能用问题B来解决，倘若B的时间复杂度比A的时间复杂度还低了，那A的算法就可以改进为B的算法，两者的时间复杂度还是相同。正如解一元二次方程比解一元一次方程难，因为解决前者的方法可以用来解决后者。
很显然，约化具有一项重要的性质：约化具有传递性。如果问题A可约化为问题B，问题B可约化为问题C，则问题A一定可约化为问题C。这个道理非常简单，就不必阐述了。
现在再来说一下约化的标准概念就不难理解了：如果能找到这样一个变化法则，对任意一个程序A的输入，都能按这个法则变换成程序B的输入，使两程序的输出相同，那么我们说，问题A可约化为问题B。
当然，我们所说的“可约化”是指的可“多项式地”约化(Polynomial-time Reducible)，即变换输入的方法是能在多项式的时间里完成的。约化的过程只有用多项式的时间完成才有意义。
好了，从约化的定义中我们看到，一个问题约化为另一个问题，时间复杂度增加了，问题的应用范围也增大了。通过对某些问题的不断约化，我们能够不断寻找复杂度更高，但应用范围更广的算法来代替复杂度虽然低，但只能用于很小的一类问题的算法。再回想前面讲的P和NP问题，联想起约化的传递性，自然地，我们会想问，如果不断地约化上去，不断找到能“通吃”若干小NP问题的一个稍复杂的大NP问题，那么最后是否有可能找到一个时间复杂度最高，并且能“通吃”所有的NP问题的这样一个超级NP问题？答案居然是肯定的。也就是说，存在这样一个NP问题，所有的NP问题都可以约化成它。换句话说，只要解决了这个问题，那么所有的NP问题都解决了。这种问题的存在难以置信，并且更加不可思议的是，这种问题不只一个，它有很多个，它是一类问题。这一类问题就是传说中的NPC问题，也就是NP-完全问题。NPC问题的出现使整个NP问题的研究得到了飞跃式的发展。我们有理由相信，NPC问题是最复杂的问题。再次回到全文开头，我们可以看到，人们想表达一个问题不存在多项式的高效算法时应该说它“属于NPC问题”。此时，我的目的终于达到了，我已经把NP问题和NPC问题区别开了。到此为止，本文已经写了近5000字了，我佩服你还能看到这里来，同时也佩服一下自己能写到这里来。
NPC问题的定义非常简单。同时满足下面两个条件的问题就是NPC问题。首先，它得是一个NP问题；然后，所有的NP问题都可以约化到它。证明一个问题是NPC问题也很简单。先证明它至少是一个NP问题，再证明其中一个已知的NPC问题能约化到它（由约化的传递性，则NPC问题定义的第二条也得以满足；至于第一个NPC问题是怎么来的，下文将介绍），这样就可以说它是NPC问题了。
既然所有的NP问题都能约化成NPC问题，那么只要任意一个NPC问题找到了一个多项式的算法，那么所有的NP问题都能用这个算法解决了，NP也就等于P了。因此，给NPC找一个多项式算法太不可思议了。因此，前文才说，“正是NPC问题的存在，使人们相信P≠NP”。我们可以就此直观地理解，NPC问题目前没有多项式的有效算法，只能用指数级甚至阶乘级复杂度的搜索。
顺便讲一下NP-Hard问题。NP-Hard问题是这样一种问题，它满足NPC问题定义的第二条但不一定要满足第一条（就是说，NP-Hard问题要比NPC问题的范围广）。NP-Hard问题同样难以找到多项式的算法，但它不列入我们的研究范围，因为它不一定是NP问题。即使NPC问题发现了多项式级的算法，NP-Hard问题有可能仍然无法得到多项式级的算法。事实上，由于NP-Hard放宽了限定条件，它将有可能比所有的NPC问题的时间复杂度更高从而更难以解决。
不要以为NPC问题是一纸空谈。NPC问题是存在的。确实有这么一个非常具体的问题属于NPC问题。下文即将介绍它。
下文即将介绍逻辑电路问题。这是第一个NPC问题。其它的NPC问题都是由这个问题约化而来的。因此，逻辑电路问题是NPC类问题的“鼻祖”。
逻辑电路问题是指的这样一个问题：给定一个逻辑电路，问是否存在一种输入使输出为True。
什么叫做逻辑电路呢？一个逻辑电路由若干个输入，一个输出，若干“逻辑门”和密密麻麻的线组成。看下面一例，不需要解释你马上就明白了。
这是个较简单的逻辑电路，当输入1、输入2、输入3分别为True、True、False或False、True、False时，输出为True。
有输出无论如何都不可能为True的逻辑电路吗？有。下面就是一个简单的例子。
上面这个逻辑电路中，无论输入是什么，输出都是False。我们就说，这个逻辑电路不存在使输出为True的一组输入。
回到上文，给定一个逻辑电路，问是否存在一种输入使输出为True，这即逻辑电路问题。
逻辑电路问题属于NPC问题。这是有严格证明的。它显然属于NP问题，并且可以直接证明所有的NP问题都可以约化到它（不要以为NP问题有无穷多个将给证明造成不可逾越的困难）。证明过程相当复杂，其大概意思是说任意一个NP问题的输入和输出都可以转换成逻辑电路的输入和输出（想想计算机内部也不过是一些0和1的运算），因此对于一个NP问题来说，问题转化为了求出满足结果为True的一个输入（即一个可行解）。
有了第一个NPC问题后，一大堆NPC问题就出现了，因为再证明一个新的NPC问题只需要将一个已知的NPC问题约化到它就行了。后来，Hamilton回路成了NPC问题，TSP问题也成了NPC问题。现在被证明是NPC问题的有很多，任何一个找到了多项式算法的话所有的NP问题都可以完美解决了。因此说，正是因为NPC问题的存在，P=NP变得难以置信。P=NP问题还有许多有趣的东西，有待大家自己进一步的挖掘。攀登这个信息学的巅峰是我们这一代的终极目标。现在我们需要做的，至少是不要把概念弄混淆了。
--------------------------------------------------------------------------
1。有解但无算法的问题：
比如圆周率Pi的小数点后面是否有连续的100万个0。因为Pi是一个客观存在的实数，所以Pi的值是确定的，因此这个问题的解也是存在的。要么是yes,要么是no，虽然我们不知道他到底是什么，但他是客观存在的，不随时间改变，不随人的认识而改变。但是没有算法可以计算这个问题的答案。当然，可以用一种苯办法来解决这个问题，就是不停地计算Pi的小数点后面的值，如果发现了有连续的100万个0，则这个问题的答案就是yes，但是如果没有发现，我们必须一直计算下去，而且永远无法停止~~，所以这种苯办法根本称不上是算法，因为他不满足算法在有限步内终止的条件。所以这个问题是没有算法的（至少目前认为如此，也许以后可以从数论中找到某种方法来求出小数点后面是否有连续的k个0，或从概率的角度计算Pi的小数点后面的值的分布等等等等）。
2.无解也无算法的问题：
例如，给定任意一个命题，是否存在一种算法判断这个命题是真是假？这就是著名的图灵停机问题。如果存在这个算法，那么我们只要找到这个算法就可以一劳永逸了，以后无论拿到什么新的命题，都可以用这个算法来验证一下，立刻就知道该命题是真是假，这样我们就掌握了整个宇宙的终极真理：）。但是图灵已经证明了这样的算法是不存在的，这个问题也是无解的。（证明中主要利用了康托尔对角线删除法，就是用来证明实数和自然数不等势的那种对角线删除法）
3。可计算与不可计算：
根据图灵-丘奇论题，：
1。可计算的问题就是能被图灵机计算的问题；（图灵的定义）
2。可计算的问题就是使用lamda演算系统可以计算的问题；(丘奇的定义)图灵丘奇论题与其说是定理，不如说是算法的定义。因为算法本身就是一个不精确的概念，到底什么是算法，以前一直没有确切的定义。而图灵-丘奇论题则从数学上给出了算法的形式定义。 图灵说：所有的图灵机能计算的问题都是有算法的（也就是可计算的），所有有算法的问题都可以用图灵机计算。这个论题本身是无法证明的，它就像物理中的光速不变定律一样，是一条自然定律，不能加以逻辑上的证明，只能用实验来检验。而目前来看，图灵命题也和光速不变一样，经得住历史和时间的检验，现在即使发展到了量子计算机，还是没有摆脱图灵机的约束，量子计算机上可计算的问题也是普通的图灵机上可计算的问题，只不过计算效率不同而已。不可计算的问题的两个例子前面已经说过了，一个是Pi的例子，另一个是图灵停机问题。4。可证明性与不可证明性
在一个公里系统中，有若干条公里，有一些推导规则，在系统中进行定理的证明，就是从公理出发，利用这些规则推导出新的定理。如果最终能得到我们需要证明的命题，则该命题为真；如果最终得到了和我们需要证明的命题相违背的命题，则我们要证明的命题为假。如果把系统中所有的定理看作图中的节点，假如从定理i1,i2,..ik根据系统的规则可以推导出定理j，则从i1,i2,...ik分别连接一条到j的有向边。这样整个公理系统构造成了一个有向图。定理的证明过程事实上是在公理系统中从公理表示的节点出发，构造一颗到达目标命题节点的“证明树”。因而定理的证明就和图论中的路经搜索类似（BTW，这就是定理自动化证明的基本原理）。
超级天才歌德尔在25岁的时候提出了著名的歌德尔不完备性定理。哥德尔证明：任何无矛盾的公理体系，只要包含初等算术的陈述，则必定存在一个不可判定命题，用这组公理不能判定其真假。也就是说，“无矛盾”和“完备”是不能同时满足的！这便是闻名于世的哥德尔不完全性定理。
所谓存在着矛盾，就是可以证明命题A成立，也可以证明命题A的否命题成立，这就自相矛盾了。
所谓不完备，是指系统中存在着一些命题，无法证明它成立，也无法证明它不成立。这就好像在一个图中存在着某些孤立点，从基本的公理节点出发永远无法访问到这些孤立点。
歌德尔在“不完备性定理”的证明过程中构造出了一个无法证明是真是伪的定理。具体说起来比较麻烦，我根据自己的理解将其简化为下述的简单形式：
命题A = “命题A不成立”
现在问命题A是否成立。如果命题A成立，则根据命题A的内容，命题A应该不成立；如果命题A不成立，则根据命题A的内容，命题A又应该成立。
这个例子很不严谨，因为它事实上混淆了语法和语义层次。但我觉得这个例子可以作为歌德尔的例子的一个简化版本。歌德的那个例子要比这个严谨和复杂得多，但实质上是差不多的，也是利用了逻辑中的悖论。
罗素等人所提倡的解决这种悖论的方法就是给谓词逻辑分层次，从而产生了一阶谓词逻辑、二阶谓词逻辑等。像上面的例子，罗素认为命题A的内容描述了命题A本身的性质，这就超出了命题A所能表达的范围，他认为这样的A不是合法的命题。
          
          
        
      </description>
    </item>
    
    <item>
      <title>jQuery快速入门</title>
      <link>https://www.crs811.com/archives/410/</link>
      <pubDate>Sat, 16 Apr 2016 15:16:41 +0000</pubDate>
      
      <guid>https://www.crs811.com/archives/410/</guid>
      <description>
        
          
            jQuery是目前使用最广泛的javascript函数库。
据统计，全世界排名前100万的网站，有46%使用jQuery，远远超过其他库。微软公司甚至把jQuery作为他们的官方库。
对于网页开发者来说，学会jQuery是必要的。因为它让你了解业界最通用的技术，为将来学习更高级的库打下基础，并且确实可以很轻松地做出许多复杂的效果。
虽然jQuery上手简单，比其他库容易学会，但是要全面掌握，却不轻松。因为它涉及到网页开发的方方面面，提供的各种方法和内部变化有上千种之多。初学者常常感到，入门很方便，提高很困难。
目前，互联网上最好的jQuery入门教材，是Rebecca Murphey写的《jQuery基础》（jQuery Fundamentals）。在Google里搜索&amp;quot;jQuery 培训&amp;quot;，此书排在第一位。jQuery官方团队已经同意，把此书作为官方教程的基础。
这本书虽然是入门教材，但也足足有100多页。我对它做了一个详细的笔记，试图理清jQuery的设计思想，找出学习的脉络。我的目标是全面掌握jQuery，遇到问题的时候，心里有底，基本知道使用它的哪一个功能，然后可以迅速从手册中找到具体的写法。
下面就是我的笔记，它应该是目前网上不多的jQuery中文教程之一。你只需要一点javascript语言的基本知识，就能看懂它，在最短的时间里，掌握jQuery的所有主要方面（除了ajax和插件开发）。
===========================================
jQuery设计思想
原文网址：http://jqfundamentals.com/book/
阮一峰 翻译整理
【目录】
一、选择网页元素
二、改变结果集
三、链式操作
四、元素的操作：取值和赋值
五、元素的操作：移动
六、元素的操作：复制、删除和创建
七、工具方法
八、事件操作
九、特殊效果
【正文】
一、选择网页元素
jQuery的基本设计思想和主要用法，就是**&amp;quot;选择某个网页元素，然后对其进行某种操作&amp;quot;**。这是它区别于其他Javascript库的根本特点。
使用jQuery的第一步，往往就是将一个选择表达式，放进构造函数jQuery()（简写为$），然后得到被选中的元素。
选择表达式可以是CSS选择器：
$(document) //选择整个文档对象$(&#39;#myId&#39;) //选择ID为myId的网页元素$(&#39;div.myClass&#39;) // 选择class为myClass的div元素$(&#39;input[name=first]&#39;) // 选择name属性等于first的input元素 也可以是jQuery特有的表达式：
$(&#39;a:first&#39;) //选择网页中第一个a元素$(&#39;tr:odd&#39;) //选择表格的奇数行$(&#39;#myForm :input&#39;) // 选择表单中的input元素$(&#39;div:visible&#39;) //选择可见的div元素$(&#39;div:gt(2)&#39;) // 选择所有的div元素，除了前三个$(&#39;div:animated&#39;) // 选择当前处于动画状态的div元素 二、改变结果集
jQuery设计思想之二，就是提供各种强大的过滤器，对结果集进行筛选，缩小选择结果。
$(&#39;div&#39;).has(&#39;p&#39;); // 选择包含p元素的div元素$(&#39;div&#39;).not(&#39;.myClass&#39;); //选择class不等于myClass的div元素$(&#39;div&#39;).filter(&#39;.myClass&#39;); //选择class等于myClass的div元素$(&#39;div&#39;).first(); //选择第1个div元素$(&#39;div&#39;).eq(5); //选择第6个div元素 有时候，我们需要从结果集出发，移动到附近的相关元素，jQuery也提供了在DOM树上的移动方法：
          
          
        
      </description>
    </item>
    
    <item>
      <title>Python 开发的 10 个小技巧</title>
      <link>https://www.crs811.com/archives/390/</link>
      <pubDate>Sun, 10 Apr 2016 09:57:42 +0000</pubDate>
      
      <guid>https://www.crs811.com/archives/390/</guid>
      <description>
        
          
            下面是十个Python中很有用的技巧。其中一些是初学这门语言常常会犯的错误。
注意：假设我们都用的是Python 3
1 列表推导式
你有一个list：bag = [1, 2, 3, 4, 5]
现在你想让所有元素翻倍，让它看起来是这个样子：[2, 4, 6, 8, 10]
大多初学者，根据之前语言的经验会大概这样来做
1bag = [1, 2, 3, 4, 5] 2for i in range(len(bag)): 3bag[i] = bag[i] * 2 但是有更好的方法：
1bag = [elem * 2 for elem in bag] 很简洁对不对？这叫做Python的列表推导式。
点击[Trey Hunner’s tutorial][1]查看更多关于列表推导式的介绍。
2 遍历列表
继续，还是上面的列表。
如果可能尽量避免这样做：
1bag = [1, 2, 3, 4, 5] 2for i in range(len(bag)): 3print(bag[i]) 取而代之的应该是这样：
1bag = [1, 2, 3, 4, 5] 2for i in bag: 3print(i) 如果x是一个列表，你可以对它的元素进行迭代。多数情况下你不需要各元素的索引，但如果你非要这样做，那就用enumerate函数。它像下边的样子：
          
          
        
      </description>
    </item>
    
    <item>
      <title>搭建PHP开发环境 – windows</title>
      <link>https://www.crs811.com/archives/328/</link>
      <pubDate>Tue, 29 Mar 2016 08:15:28 +0000</pubDate>
      
      <guid>https://www.crs811.com/archives/328/</guid>
      <description>
        
          
            PHP网站的开发步骤一般是：
一、准备环境：搭建开发环境
二、开发网站：团队协作开发
三、发布网站：上传网站和数据库到远程Linux
Windows下搭建PHP开发环境的步骤是：
1、搭建网站运行环境
1.1、下载XAMPP
到XAMPP官网 下载 XAMPP for Windows
1.2、安装XAMPP，安装路径设置为 D:\xampp
1.3、运行并测试
运行xampp，打开xampp控制面板，点击 Apache, Mysql 右侧的Start, Stop即可开始或停止服务
点击Apache右侧Config，其中第一个httpd.conf可以更改网站默认目录
网站默认目录地址：D:\xampp\htdocs
打开浏览器，输入localhost，如出现XAMPP则说明安装成功
2、搭建语言开发环境
2.1、下载 vscode，并安装
https://code.visualstudio.com
2.2 安装开发所需要插件：
Better Align #对齐用的，设置一下快捷键 Ctrl + Alt + =,对块自动等号对齐 Auto Close Tag #自动标签闭合 Auto Rename Tag #自动标签重命名 Code Outline #函数变量列表 （目前有点小问题，显示的函数列表是双份的） ftp-simple #FTP远程同步工具 HTML CSS Support # CSS支持工具 HTML Snippets # HTML小片段工具 IntelliSense for CSS class names # CSS类名工具 JavaScript code snippets JS-CSS-HTML Formatter #这个慎用，最好不加吧，每次保存自动格式化 jshint #js代码检查工具 MetaGO #类是easymotion ，可以用键盘快速移动的工具 npt Intellisense #其他软件需要这个辅助工具，（具体不是很清楚） Path Intellisense #路径管理工具 PHP Debug PHP Extension Pack #PHP扩展包 PHP Intellisense #PHP自动补全工具 PHP Intellisense -Crane #PHP自动补全工具 Project Manager #多个项目之间切换的工具 Typing Installer # 不是很清楚，但很有用 vscode-icons #给不同的文件类型添加图标 发现一个非常详细的介绍： https://segmentfault.
          
          
        
      </description>
    </item>
    
    <item>
      <title>链表及链表嵌套的操作</title>
      <link>https://www.crs811.com/archives/963/</link>
      <pubDate>Fri, 25 Mar 2016 03:25:00 +0000</pubDate>
      
      <guid>https://www.crs811.com/archives/963/</guid>
      <description>
        
          
            1#include &amp;lt;stdio.h&amp;gt; 2#include &amp;lt;string.h&amp;gt; 3#include &amp;lt;stdlib.h&amp;gt; 4 5typedef struct childLink 6{ 7char nm[100]; 8struct childLink *next; 9}CHILDNODE; 10 11typedef struct linkTable 12{ 13int birthYear; 14CHILDNODE *mz; 15struct linkTable *next; 16}LINKNODE; 17 18LINKNODE * insert(LINKNODE *head, LINKNODE *input); 19CHILDNODE * insert_nm(CHILDNODE *head_c, CHILDNODE *input_nm); 20void print(LINKNODE *head); 21 22/************************************************************************/ 23/* main 24/************************************************************************/ 25void main() 26{ 27LINKNODE *head, *input; 28CHILDNODE *head_c, *input_c; 29head = NULL; 30head_c = NULL; 31 32while(1) 33{ 34if ((input=(LINKNODE *)malloc(sizeof(*input))) == NULL) 35{ 36printf(&amp;#34;malloc fail!
          
          
        
      </description>
    </item>
    
    <item>
      <title>递归 16进制转10进制</title>
      <link>https://www.crs811.com/archives/961/</link>
      <pubDate>Fri, 25 Mar 2016 03:23:11 +0000</pubDate>
      
      <guid>https://www.crs811.com/archives/961/</guid>
      <description>
        
          
             1//16&amp;gt;&amp;gt;10 2#include &amp;lt;stdio.h&amp;gt; 3#include &amp;lt;stdlib.h&amp;gt; 4#include &amp;lt;string.h&amp;gt; 5 6int fun(char *p); 7 8void main() 9{ 10 char *pstr = &amp;#34;AE5&amp;#34;; //16进制的数 11 printf(&amp;#34;hex: %s\n&amp;#34;, pstr); 12 printf(&amp;#34;dec: %d\n&amp;#34;, fun(pstr)); 13} 14 15//16&amp;gt;&amp;gt;10 16int fun(char *p) 17{ 18 int j=0, k=1, iDec; 19 20 int n=strlen(p); 21 22 if(*p&amp;gt;=&amp;#39;A&amp;#39; &amp;amp;&amp;amp; *p&amp;lt;=&amp;#39;E&amp;#39;) 23 { 24 iDec = (*p-&amp;#39;A&amp;#39;+10); 25 } 26 else if(*p&amp;gt;=&amp;#39;a&amp;#39; &amp;amp;&amp;amp; *p&amp;lt;=&amp;#39;e&amp;#39;) 27 { 28 iDec = (*p-&amp;#39;a&amp;#39;+10); 29 } 30 else 31 { 32 iDec = *p-&amp;#39;0&amp;#39;; 33 } 34 35 printf(&amp;#34;char=%c, iDec=%-4d, n=%-2d\n&amp;#34;,*p,iDec,n); 36 37 if (n == 1) 38 { 39 return iDec; 40 } 41 else 42 { 43 for (j=0; j&amp;lt;n-1; j++) 44 { 45 k*=16; 46 } 47 return iDec*k + fun(p+1); 48 } 49} 
          
          
        
      </description>
    </item>
    
    <item>
      <title>程序员技术练级攻略 [转自酷壳]</title>
      <link>https://www.crs811.com/archives/959/</link>
      <pubDate>Fri, 25 Mar 2016 03:21:44 +0000</pubDate>
      
      <guid>https://www.crs811.com/archives/959/</guid>
      <description>
        
          
            月光博客6月12日发表了《写给新手程序员的一封信》，翻译自《An open letter to those who want to start programming》，我的朋友（他在本站的id是Mailper）告诉我，他希望在酷壳上看到一篇更具操作性的文章。因为他也是喜欢编程和技术的家伙，于是，我让他把他的一些学习Python和Web编程的一些点滴总结一下。于是他给我发来了一些他的心得和经历，我在把他的心得做了不多的增改，并根据我的经历增加了“进阶”一节。这是一篇由新手和我这个老家伙根据我们的经历完成的文章。
我的这个朋友把这篇文章取名叫Build Your Programming Technical Skills，我实在不知道用中文怎么翻译，但我在写的过程中，我觉得这很像一个打网游做任务升级的一个过程，所以取名叫“技术练级攻略”，题目有点大，呵呵，这个标题纯粹是为了好玩。这里仅仅是在分享Mailper和我个人的学习经历。（注：省去了我作为一个初学者曾经学习过的一些技术(今天明显过时了)，如：Delphi/Power builder，也省去了我学过的一些我觉得没意思的技术Lotus Notes/ActiveX/COM/ADO/ATL/.NET ……）
前言
你是否觉得自己从学校毕业的时候只做过小玩具一样的程序？ 走入职场后哪怕没有什么经验也可以把以下这些课外练习走一遍（朋友的抱怨：学校课程总是从理论出发， 作业项目都看不出有什么实际作用，不如从工作中的需求出发）
建议：
不要乱买书，不要乱追新技术新名词， 基础的东西经过很长时间积累而且还会在未来至少10年通用。
回顾一下历史，看看历史上时间线上技术的发展，你才能明白明天会是什么样。
一定要动手，例子不管多么简单， 建议至少自己手敲一遍看看是否理解了里头的细枝末节。
一定要学会思考，思考为什么要这样，而不是那样。还要举一反三地思考。
注：你也许会很奇怪为什么下面的东西很偏Unix/Linux，这是因为我觉得Windows下的编程可能会在未来很没有前途，原因如下：
现在的用户界面几乎被两个东西主宰了，1）Web，2）移动设备iOS或Android。Windows的图形界面不吃香了。
越来越多的企业在用成本低性能高的Linux和各种开源技术来构架其系统，Windows的成本太高了。
微软的东西变得太快了，很不持久，他们完全是在玩弄程序员。详情参见《Windows编程革命史》
所以，我个人认为以后的趋势是前端是Web+移动，后端是Linux+开源。开发这边基本上没Windows什么事。
启蒙入门
1、 学习一门脚本语言，例如Python/Ruby
可以让你摆脱对底层语言的恐惧感，脚本语言可以让你很快开发出能用得上的小程序。实践项目:
处理文本文件，或者csv (关键词 python csv, python open, python sys) 读一个本地文件，逐行处理（例如 word count，或者处理log）
遍历本地文件系统 (sys, os, path)，例如写一个程序统计一个目录下所有文件大小并按各种条件排序并保存结果
跟数据库打交道 (python sqlite)，写一个小脚本统计数据库里条目数量
学会用各种print之类简单粗暴的方式进行调试
学会用Google (phrase, domain, use reader to follow tech blogs)
为什么要学脚本语言，因为他们实在是太方便了，很多时候我们需要写点小工具或是脚本来帮我们解决问题，你就会发现正规的编程语言太难用了。
2、 用熟一种程序员的编辑器(不是IDE) 和一些基本工具
          
          
        
      </description>
    </item>
    
    <item>
      <title>一些有意思的算法代码</title>
      <link>https://www.crs811.com/archives/957/</link>
      <pubDate>Fri, 25 Mar 2016 03:19:46 +0000</pubDate>
      
      <guid>https://www.crs811.com/archives/957/</guid>
      <description>
        
          
            Keith Schwarz是一个斯坦福大学计算机科学系的讲师。他对编程充满了热情。他的主页上他自己正在实现各种各样的有意思的算法和数据结构
主页地址
http://www.keithschwarz.com/interesting/
部分算法说明：
          
          
        
      </description>
    </item>
    
    <item>
      <title>合并字符串中的空格</title>
      <link>https://www.crs811.com/archives/954/</link>
      <pubDate>Fri, 25 Mar 2016 03:16:19 +0000</pubDate>
      
      <guid>https://www.crs811.com/archives/954/</guid>
      <description>
        
          
            1#include &amp;#34;stdio.h&amp;#34; 2#include &amp;#34;string.h&amp;#34; 3#include &amp;#34;stdlib.h&amp;#34; 4 5char* mergeblank(char str[]); 6 7int main() 8{ 9 char str[]= &amp;#34;hello world this is a \&amp;#34;t e s t\&amp;#34;this is a test&amp;#34;; 10 printf(&amp;#34;str_old: %s\n&amp;#34;, str); 11 char *p = mergeblank(str); 12 printf(&amp;#34;str_new: %s\n&amp;#34;, p); 13 system(&amp;#34;pause&amp;#34;); 14 return 0; 15} 16 17char* mergeblank(char str[]) 18{ 19 int iBlank = 0, iPos = 0; 20 int i = 0, j=0; 21 int bYH = 0; 22 for (i=0; str[i]!
          
          
        
      </description>
    </item>
    
    <item>
      <title>删除C语言源程序文件中的所有注释</title>
      <link>https://www.crs811.com/archives/951/</link>
      <pubDate>Fri, 25 Mar 2016 03:13:53 +0000</pubDate>
      
      <guid>https://www.crs811.com/archives/951/</guid>
      <description>
        
          
            1#include &amp;lt;stdio.h&amp;gt; 2#include &amp;lt;stdlib.h&amp;gt; 3#include &amp;lt;string.h&amp;gt; 4 5#define STR_LEN 400 6 7void main() 8{ 9 FILE *fpr, *fpw; 10 char ch, strline[STR_LEN + 1]; 11 12 int i=0,p=0,q=0; 13 bool bFind = false, bEnd = false; 14 15 if ((fpr=fopen(&amp;#34;c:\\c.c&amp;#34;,&amp;#34;r&amp;#34;)) == NULL) 16 { 17 printf(&amp;#34;open file fail!&amp;#34;); 18 exit(0); 19 } 20 if ((fpw=fopen(&amp;#34;c:\\c_new.c&amp;#34;,&amp;#34;w&amp;#34;)) == NULL) 21 { 22 printf(&amp;#34;write file fail!&amp;#34;); 23 exit(0); 24 } 25 26/* 27判断文件结束 用 while(!
          
          
        
      </description>
    </item>
    
    <item>
      <title>找出二维数组的“鞍点”</title>
      <link>https://www.crs811.com/archives/948/</link>
      <pubDate>Fri, 25 Mar 2016 03:10:19 +0000</pubDate>
      
      <guid>https://www.crs811.com/archives/948/</guid>
      <description>
        
          
            1//找出一个二维数组的“鞍点”，即该位置上的元素在该行上最大，在该列上最小。也可能没有鞍点。 2 3//(1)二维数组有鞍点： 4 int a[3][4]={{9,80,205,40},{90,-60,96,1},{210,-3,101,89}}; 5 6 //(2)二维数组没有鞍点： 7 int b[4][4]={{9,80,205,40},{90,-60,196,1},{210,-3,101,89},{45,54,156,7}}; 8 9 AnDian(a, 3); 10 AnDian(b, 4); 11 12/* 13查找鞍点函数 14注意：二维数组作参数，一定要给出列的维度 15*/ 16void AnDian(int arr[][4], int len) 17{ 18 int i, j, k; 19 int rowMaxIndex, iRAn=-1, iCAn=-1, iAn=-1; 20 int iTemp; 21 bool bAn = true; 22 23 printf(&amp;#34;\n---------------------------------\n\n&amp;#34;); 24 for (i=0; i&amp;lt;len; i++) 25 { 26 for (j=0; j&amp;lt;4; j++) 27 { 28 printf(&amp;#34;%-5d &amp;#34;,arr[i][j]); 29 } 30 printf(&amp;#34;\n\n&amp;#34;); 31 } 32 //------------------------------ 33 //find max number in row 34 for (i=0; i&amp;lt;len; i++)//Row 35 { 36 bAn = true; 37 iTemp = arr[i][0]; 38 rowMaxIndex = 0; 39 for (j=0; j&amp;lt;4; j++)//Col 40 { 41 if (iTemp &amp;lt; arr[i][j]) 42 { 43 iTemp = arr[i][j]; 44 rowMaxIndex = j; 45 } 46 } 47 48 //judge wether iTemp is min number in Cols 49 for (k=0; k&amp;lt;len; k++)//Row 50 { 51 if (iTemp &amp;gt; arr[k][rowMaxIndex]) 52 { 53 bAn = false; 54 break; 55 } 56 } 57 if (bAn) 58 { 59 iRAn = i; 60 iCAn = rowMaxIndex; 61 iAn = iTemp; 62 } 63 }// for (i=0; i&amp;lt;len; i++)//Row 64 if (iRAn !
          
          
        
      </description>
    </item>
    
    <item>
      <title>各种内部排序方法的比较讨论</title>
      <link>https://www.crs811.com/archives/946/</link>
      <pubDate>Fri, 25 Mar 2016 03:09:24 +0000</pubDate>
      
      <guid>https://www.crs811.com/archives/946/</guid>
      <description>
        
          
            对于这些内部排序方法之间的比较，主要从以下几个方面综合考虑：时间复杂度、空间复杂度、算法稳定性、算法简单性、待排序记录数n的大小、记录本身的信息量等
1 时间复杂度 选择n个整数组成一些随机排序，各种内部排序方法的实际时间如图7-10所示。
从时间复杂度看，所有内部排序方法可以分为两类。插入排序、选择排序和起泡排序这三种简单排序方法属于第一类，其时间复杂度为O(n^2)；堆排序、快速排序和归并排序这三种排序方法属于第二类，其时间复杂度为O(nlog2n)。这是就平均情况而言的，如果从最好的情况考虑，则插入排序和起泡排序的时间复杂度最好，为O(n)，而其他算法的最好情况同平均情况大致相同。如果从最坏的情况考虑，快速排序的时间复杂度为O(n^2)，插入排序和起泡排序虽然同平均情况相同，但系数大约增加一倍，运行速度降低一半，而选择排序、堆排序和归并排序则影响不大。
总之，在平均情况下，快速排序最快；在最好情况下，插入排序和起泡排序最快；在最坏情况下，堆排序和归并排序最快。
2 空间复杂度 从空间复杂度看，归并排序属于第一类，其空间复杂度为O(n)；快速排序属于第二类，其空间复杂度为O(nlog2n)；其它排序方法归为第三类，其空间复杂度为O(1)。所以，第三类算法的空间复杂度最好，第二类次之，第一类最差。
3 算法稳定性 从算法稳定性看，所有内部排序方法可以分为两类。插入排序、起泡排序和归并排序属于第一类，是稳定的排序方法；选择排序、快速排序和堆排序属于第二类，是不稳定的排序方法。相对而言，后者的时间性能较好。
由于大多数情况下排序是按照记录的主关键字进行的，则所用的排序方法是否稳定无关紧要。但是如果排序是按照记录的次关键字进行的，则应根据问题需要慎重选择排序方法及其描述算法。
4 算法简单性 从算法简单性看，一类是简单算法，一般包括插入排序、选择排序和起泡排序，这些算法都比较简单和直接，易于理解；另一类是改进后的算法，一般包括堆排序、快速排序和归并排序，这些算法都比较复杂。当序列中的记录基本有序或者n值较小时，直接插入排序是最佳的排序方法，因此常常将它和其他的排序方法结合使用。
5 待排序记录数n的大小 从待排序的记录数n的大小看，n越小，n2和nlog2n越接近，采用简单排序方法越合适；n越大，采用改进排序方法越合适。另外，简单算法的输入和调试比改进算法的输入和调试要少用许多时间，如果也考虑这些时间，则n较小时选用简单算法比改进算法要节省时间。当n越大时，n2和nlog2n的差距越大，因此选用改进算法效果更明显。
6记录本身的信息量 从记录本身的信息量看，信息量越大占用的存储空间越大，移动记录时花费的时间越多，所以对记录的移动次数较多的算法不利。例如，在三种简单排序算法中，选择排序移动记录的次数为O(n)，其他两种为O(n^2)。所以当记录本身的信息量较大时，对选择排序有利，而对其他两种算法不利。在三种改进算法中，记录本身的信息量较大时，对归并排序不利。
以上从六个方面对各种内部排序方法进行了分析和比较，那么在实际的排序问题中应如何考虑它们的主次呢？一般来说，首先考虑算法的稳定性，如果排序要求稳定，则只能在稳定的方法中选择，否则就可以选择任何的排序方法；其次要考虑待排序的记录数的大小，如果n较大，则在改进算法中选择，否则在简单算法中选择；然后再考虑其他的因素。
          
          
        
      </description>
    </item>
    
    <item>
      <title>C 字符串的输入</title>
      <link>https://www.crs811.com/archives/944/</link>
      <pubDate>Fri, 25 Mar 2016 03:03:23 +0000</pubDate>
      
      <guid>https://www.crs811.com/archives/944/</guid>
      <description>
        
          
            1#include &amp;#34;stdio.h&amp;#34; 2#include &amp;#34;string.h&amp;#34; 3 4#define STR_LEN 5 5 6int main() 7{ 8 char str[STR_LEN + 1], *p; 9 p = str; 10 11 printf(&amp;#34;Input String: &amp;#34;); 12 13 //方法一：容易被空格 Tab 等截断 14 //scanf(&amp;#34;%s&amp;#34;, str); 15 16 //方法二：容易溢出 17 //gets(str); 18 19 //方法三：C推荐的用法 20 //fgets会指定大小(一般小于1024)，如果超出数组大小 21 //会自动根据定义数组的长度截断。 22 //fgets(str, sizeof(str), stdin); 23 24 //方法四：自己写函数 25 read_line(str, STR_LEN); 26 27 printf(&amp;#34;\nOuput String: %s&amp;#34;, p); 28 29 /**********************************/ 30 return 1; 31} 32/* 33Read string 34*/ 35int read_line(char str[], int ilen) 36{ 37 char ch; 38 int i = 0; 39 while((ch = getchar()) !
          
          
        
      </description>
    </item>
    
    <item>
      <title>按序合并链表</title>
      <link>https://www.crs811.com/archives/942/</link>
      <pubDate>Fri, 25 Mar 2016 03:02:12 +0000</pubDate>
      
      <guid>https://www.crs811.com/archives/942/</guid>
      <description>
        
          
            1#include &amp;#34;stdio.h&amp;#34; 2#include &amp;#34;string.h&amp;#34; 3#include &amp;#34;stdlib.h&amp;#34; 4 5typedef struct student 6{ 7 int stuno; 8 int age; 9 struct student *next; 10}; 11 12int num; 13student* createLink(); 14student* merge(student *pA, student *pB); 15void sort(student *head, int num); 16void print(student *head); 17 18/************************************************************************/ 19/* main 20/************************************************************************/ 21int main() 22{ 23 num = 0; 24 student *head_A, *head_B, *head_C; 25 head_A=head_B=head_C=NULL; 26 27 head_A = createLink(); 28 head_B = createLink(); 29 30 printf(&amp;#34;link list A:\n&amp;#34;); 31 print(head_A); 32 printf(&amp;#34;link list B:\n&amp;#34;); 33 print(head_B); 34 35 head_C = merge(head_A, head_B); 36 printf(&amp;#34;merge A with B:\n&amp;#34;); 37 print(head_C); 38 39 sort(head_C, num); 40 printf(&amp;#34;merge A with B (sort with ASC):\n&amp;#34;); 41 print(head_C); 42 return 0; 43} 44/************************************************************************/ 45/* create link list 46/************************************************************************/ 47student* createLink() 48{ 49 student *head, *p1, *p2; 50 head=p1=p2=NULL; 51 52 printf(&amp;#34;************************\n stuno:0 will exit:\n************************\n&amp;#34;); 53 54 while(1) 55 { 56 p1 = (student *)malloc(sizeof(*p1)); 57 if (p1== NULL) 58 { 59 printf(&amp;#34;malloc fail!
          
          
        
      </description>
    </item>
    
    <item>
      <title>链表的排序</title>
      <link>https://www.crs811.com/archives/940/</link>
      <pubDate>Fri, 25 Mar 2016 03:00:48 +0000</pubDate>
      
      <guid>https://www.crs811.com/archives/940/</guid>
      <description>
        
          
            1/* 2========================== 3 功能：选择排序(由小到大) 4 返回：指向链表表头的指针 5========================== 6*/ 7/* 8 选择排序的基本思想就是反复从还未排好序的那些节点中， 9 选出键值（就是用它排序的字段，我们取学号num为键值）最小的节点， 10 依次重新组合成一个链表。 11 12 我认为写链表这类程序，关键是理解： 13 head存储的是第一个节点的地址，head-&amp;gt;next存储的是第二个节点的地址； 14 任意一个节点p的地址，只能通过它前一个节点的next来求得。 15 16单向链表的选择排序图示： 17 18----&amp;gt;[1]----&amp;gt;[3]----&amp;gt;[2]...----&amp;gt;[n]----&amp;gt;[NULL]（原链表） 19head 1-&amp;gt;next 3-&amp;gt;next 2-&amp;gt;next n-&amp;gt;next 20 21----&amp;gt;[NULL]（空链表） 22first 23tail 24 25----&amp;gt;[1]----&amp;gt;[2]----&amp;gt;[3]...----&amp;gt;[n]----&amp;gt;[NULL]（排序后链表） 26first 1-&amp;gt;next 2-&amp;gt;next 3-&amp;gt;next tail-&amp;gt;next 27 28有N个节点的链表选择排序 29 301、先在原链表中找最小的，找到一个后就把它放到另一个空的链表中； 312、空链表中安放第一个进来的节点，产生一个有序链表,并且让它在原链表中分离出来（此时要注意原链表中出来的是第一个节点还是中间其它节点）； 323、继续在原链表中找下一个最小的，找到后把它放入有序链表的尾指针的next,然后它变成其尾指针； 33*/ 34 35struct student *SelectSort(struct student *head) 36{ 37 struct student *first; /*排列后有序链的表头指针*/ 38 struct student *tail; /*排列后有序链的表尾指针*/ 39 struct student *p_min; /*保留键值更小的节点的前驱节点的指针*/ 40 struct student *min; /*存储最小节点*/ 41 struct student *p; /*当前比较的节点*/ 42 43 first = NULL; 44 while (head !
          
          
        
      </description>
    </item>
    
    <item>
      <title>VC 钩子</title>
      <link>https://www.crs811.com/archives/938/</link>
      <pubDate>Fri, 25 Mar 2016 02:56:24 +0000</pubDate>
      
      <guid>https://www.crs811.com/archives/938/</guid>
      <description>
        
          
            钩子是Windows操作系统中非常重要的一种系统接口，用它可以轻松截获并处理在其他应用程序之间传递的消息，并由此可以完成一些普通应用程序难以实现的特殊功能。基于钩子在消息拦截处理中的强大功能.本文即以VC++ 6.0为编程背景对钩子的基本概念及其实现过程展开讨论。为方便理解，在文章最后还给出了一个简单的有关鼠标钩子的应用示例。
钩子的基本原理
钩子的本质是一段用以处理系统消息的程序，通过系统调用，将其挂入到系统。钩子的种类有很多，每一种钩子负责截获并处理相应的消息。钩子机制允许应用程序截获并处理发往指定窗口的消息或特定事件，其监视的窗口即可以是本进程内的也可以是由其他进程所创建的。在特定的消息发出，并在到达目的窗口之前，钩子程序先行截获此消息并得到对其的控制权。此时在钩子函数中就可以对截获的消息进行各种修改处理，甚至强行终止该消息的继续传递。
任何一个钩子都由系统来维护一个指针列表（钩子链表），其指针指向钩子的各个处理函数。最近安装的钩子放在链的开始，最早安装的钩子则放在最后，当钩子监视的消息出现时，操作系统调用链表开始处的第一个钩子处理函数进行处理，也就是说最后加入的钩子优先获得控制权。在这里提到的钩子处理函数必须是一个回调函数（callback function），而且不能定义为类成员函数，必须定义为普通的C函数。在使用钩子时可以根据其监视范围的不同将其分为全局钩子和线程钩子两大类，其中线程钩子只能监视某个线程，而全局钩子则可对在当前系统下运行的所有线程进行监视。显然，线程钩子可以看作是全局钩子的一个子集，全局钩子虽然功能强大但同时实现起来也比较烦琐：其钩子函数的实现必须封装在动态链接库中才可以使用。
钩子的安装与卸载
由于全局钩子具有相当的广泛性而且在功能上完全覆盖了线程钩子，因此下面就主要对应用较多的全局钩子的安装与使用进行讨论。前面已经提过，操作系统是通过调用钩子链表开始处的第一个钩子处理函数而进行消息拦截处理的。因此，为了设置钩子，只需将回调函数放置于链首即可，操作系统会使其首先被调用。在具体实现时由函数SetWindowsHookEx()负责将回调函数放置于钩子链表的开始位置。SetWindowsHookEx()函数原型声明如下:
HHOOK SetWindowsHookEx(int idHook;
HOOKPROC lpfn;
HINSTANCE hMod;
DWORD dwThreadId);
其中：参数idHook 指定了钩子的类型，总共有如下13种：
WH_CALLWNDPROC 系统将消息发送到指定窗口之前的&amp;quot;钩子&amp;quot;
WH_CALLWNDPROCRET 消息已经在窗口中处理的&amp;quot;钩子&amp;quot;
WH_CBT 基于计算机培训的&amp;quot;钩子&amp;quot;
WH_DEBUG 差错&amp;quot;钩子&amp;quot;
WH_FOREGROUNDIDLE 前台空闲窗口&amp;quot;钩子&amp;quot;
WH_GETMESSAGE 接收消息投递的&amp;quot;钩子&amp;quot;
WH_JOURNALPLAYBACK 回放以前通过WH_JOURNALRECORD&amp;quot;钩子&amp;quot;记录的输入消息
WH_JOURNALRECORD 输入消息记录&amp;quot;钩子&amp;quot;
WH_KEYBOARD 键盘消息&amp;quot;钩子&amp;quot;
WH_MOUSE 鼠标消息&amp;quot;钩子&amp;quot;
WH_MSGFILTER 对话框、消息框、菜单或滚动条输入消息&amp;quot;钩子&amp;quot;
WH_SHELL 外壳&amp;quot;钩子&amp;quot;
WH_SYSMSGFILTER 系统消息&amp;quot;钩子&amp;quot;
参数lpfn为指向钩子处理函数的指针，即回调函数的首地址；参数hMod则标识了钩子处理函数所处模块的句柄；第四个参数dwThreadId 指定被监视的线程，如果明确指定了某个线程的ID就只监视该线程，此时的钩子即为线程钩子；如果该参数被设置为0，则表示此钩子为监视系统所有线程的全局钩子。此函数在执行完后将返回一个钩子句柄。
虽然对于线程钩子并不要求其象全局钩子一样必须放置于动态链接库中，但是推荐其也在动态链接库中实现。因为这样的处理不仅可使钩子可为系统内的多个进程访问，也可以在系统中被直接调用，而且对于一个只供单进程访问的钩子，还可以将其钩子处理过程放在安装钩子的同一个线程内，此时SetWindowsHookEx()函数的第三个参数也就是该线程的实例句柄。
在 SetWindowsHookEx()函数完成对钩子的安装后，如果被监视的事件发生，系统马上会调用位于相应钩子链表开始处的钩子处理函数进行处理，每一个钩子处理函数在进行相应的处理时都要考虑是否需要把事件传递给下一个钩子处理函数。如果要传递，就通过函数CallNestHookEx()来解决。尽管如此，在实际使用时还是强烈推荐无论是否需要事件传递而都在过程的最后调用一次CallNextHookEx( )函数，否则将会引起一些无法预知的系统行为或是系统锁定。该函数将返回位于钩子链表中的下一个钩子处理过程的地址，至于具体的返回值类型则要视所设置的钩子类型而定。该函数的原型声明如下：
LRESULT CallNextHookEx(HHOOK hhk;int nCode;WPARAM wParam;LPARAM lParam);
其中，参数hhk为由SetWindowsHookEx()函数返回的当前钩子句柄；参数nCode为传给钩子过程的事件代码；参数wParam和lParam 则为传给钩子处理函数的参数值，其具体含义同设置的钩子类型有关。
最后，由于安装钩子对系统的性能有一定的影响，所以在钩子使用完毕后应及时将其卸载以释放其所占资源。释放钩子的函数为 UnhookWindowsHookEx()，该函数比较简单只有一个参数用于指定此前由SetWindowsHookEx()函数所返回的钩子句柄，原型声明如下：
BOOL UnhookWindowsHookEx(HHOOK hhk);
          
          
        
      </description>
    </item>
    
    <item>
      <title>DLL编写教程</title>
      <link>https://www.crs811.com/archives/935/</link>
      <pubDate>Fri, 25 Mar 2016 02:55:24 +0000</pubDate>
      
      <guid>https://www.crs811.com/archives/935/</guid>
      <description>
        
          
            半年不能上网，最近网络终于通了，终于可以更新博客了，写点什么呢？决定最近写一个编程技术系列，其内容是一些通用的编程技术。例如DLL，COM，Socket，多线程等等。这些技术的特点就是使用广泛，但是误解很多；网上教程很多，但是几乎没有什么优质良品。我以近几个月来的编程经验发现，很有必要好好的总结一下这些编程技术了。一来对自己是总结提高，二来可以方便光顾我博客的朋友。
好了，废话少说，言归正传。第一篇就是《DLL编写教程》，为什么起这么土的名字呢？为什么不叫《轻轻松松写DLL》或者《DLL一日通》呢？或者更nb的《深入简出DLL》呢？呵呵，常常上网搜索资料的弟兄自然知道。
本文对通用的DLL技术做了一个总结，并提供了源代码打包下载，下载地址为：
http://www.blogjava.net/Files/wxb_nudt/DLL_SRC.rar
DLL的优点 简单的说，dll有以下几个优点：
1) 节省内存。同一个软件模块，若是以源代码的形式重用，则会被编译到不同的可执行程序中，同时运行这些exe时这些模块的二进制码会被重复加载到内存中。如果使用dll，则只在内存中加载一次，所有使用该dll的进程会共享此块内存（当然，像dll中的全局变量这种东西是会被每个进程复制一份的）。
2) 不需编译的软件系统升级，若一个软件系统使用了dll，则该dll被改变（函数名不变）时，系统升级只需要更换此dll即可，不需要重新编译整个系统。事实上，很多软件都是以这种方式升级的。例如我们经常玩的星际、魔兽等游戏也是这样进行版本升级的。
3) Dll库可以供多种编程语言使用，例如用c编写的dll可以在vb中调用。这一点上DLL还做得很不够，因此在dll的基础上发明了COM技术，更好的解决了一系列问题。
最简单的dll 开始写dll之前，你需要一个c/c++编译器和链接器，并关闭你的IDE。是的，把你的VC和C++ BUILDER之类的东东都关掉，并打开你以往只用来记电话的记事本程序。不这样做的话，你可能一辈子也不明白dll的真谛。我使用了VC自带的cl编译器和link链接器，它们一般都在vc的bin目录下。（若你没有在安装vc的时候选择注册环境变量，那么就立刻将它们的路径加入path吧）如果你还是因为离开了IDE而害怕到哭泣的话，你可以关闭这个页面并继续去看《VC++技术内幕》之类无聊的书了。
最简单的dll并不比c的helloworld难，只要一个DllMain函数即可，包含objbase.h头文件（支持COM技术的一个头文件）。若你觉得这个头文件名字难记，那么用windows.H也可以。源代码如下：dll_nolib.cpp
#include #include BOOL APIENTRY DllMain(HANDLE hModule, DWORD dwReason, void* lpReserved){HANDLE g_hModule;switch(dwReason){case DLL_PROCESS_ATTACH:cout&lt;&lt;&#34;Dll is attached!
          
          
        
      </description>
    </item>
    
    <item>
      <title>基于工厂模式的三层架构</title>
      <link>https://www.crs811.com/archives/933/</link>
      <pubDate>Fri, 25 Mar 2016 02:52:50 +0000</pubDate>
      
      <guid>https://www.crs811.com/archives/933/</guid>
      <description>
        
          
            普通的三层结构：UI / BLL / DAL ，数据实体使用 Model 封装。这种“三层结构”之间是顺序的调用关系，UI 调用 BLL ，BLL 将操作组织并安排 DAL 层，DAL 层操作数据库，每层之间的关系都很紧密，所以协同开发时互相的依赖性较强，项目结构耦合度大。
基于高内聚低耦合的原则，层和层之间的调用考虑引入接口 IDAL 进行规范和分割。BLL 层要求 DAL 层实现的功能先定义好接口 IDAL ，BLL 层就可以借用这些接口去完成业务流程，不必关心实现细节。而 DAL 层只需要按照 IDAL 接口中的定义的操作分别实现，就可以满足 BLL 的要求。这样，使用接口对层和层之间的调用实现分离，设计时都互相不需要了解细节，而在程序运行时，只需要让 BLL 层的接口引用指向对应的实际 DAL 对象，程序自然调用实现好的 DAL 中的功能。
程序通过接口实现了更灵活的分层，但毕竟接口引用哪个 DAL 层对象还是要在 BLL 层进行管理。在数据库表很多，DAL 对象也就会很多的情况下，BLL 层中关于 DAL 的管理也需要很多工作，如何管理更方面？工厂模式。
工厂模式，顾名思义，就是生产某件产品的场所，在程序中起到的也是类似的功能，作用就是生产各式各样的 DAL 对象。这样，BLL 层在需要接口的引用指向对应的 DAL 对象的时候，只需要向工厂要就行了，具体是如何产生的那个对象，BLL 不需要关心。这个框架中，DALFactory 工厂起到的作用就是生产各种 DAL 产品，交给 BLL 层使用，如果需要修改某个 DAL 的应用，只需要在工厂中修改，BLL 依旧还是向工厂要对应的产品即可。
示例代码：
·BLL 层 :
public class UserService
{ private IUserManager ium = DALFactory.
          
          
        
      </description>
    </item>
    
    <item>
      <title>Linux下的C/C&#43;&#43;编辑器</title>
      <link>https://www.crs811.com/archives/966/</link>
      <pubDate>Thu, 24 Mar 2016 19:33:02 +0000</pubDate>
      
      <guid>https://www.crs811.com/archives/966/</guid>
      <description>
        
          
            在LINUX上，可以选择的IDE有很多
1：gedit
虽然这只是一个普通的本文编辑器（外加关键字高亮），但却是我初学LINUX时所用的C++编辑器。不过，当时我写的程序也很简单，有没有IDE关系不大，呵呵。
2: vim(gvim)
传说中的神器之一，我也花了很多努力，将它改造成下面这个样子，但是我实在不习惯没有鼠标的世界，后来就没怎么用了（在没有界面的LINUX上除外）
3:emacs
传说中的神器之二，我花了几天来熟悉它，但还是不会用，直接放弃。
4:code::blocks
我挺喜欢的一个IDE，它就相当于VC6的水平，但它的功能和VS+VA相比，还是有些差距的，所以我平时用得也不是很多。
5:qtcreator
QT项目组用QT开发的一个IDE，用它来开发QT程序十分方便（看名字就知道），但开发普通的C++程序时就不是那么好用了，总的来说，它还算是一个非常不错的IDE了。
6:eclipse
传说中比Visual Studio更好用的IDE，但它所占资源实在太大了，在我的虚拟机上，它卡得不得了，加上debug时总是无故挂了。我一怒之下就把它删了。
7:Visual Studio + Visual Assist + VMWare + 共享文件夹
（在虚拟机中安装LINUX，把LINUX的系统的头文件拷出来，加入VA的包含路径，然后用VS在共享文件夹中创建项目，并在VS中编写代码，最后在LINUX中运行makefile）
这种方法是我目前所使用的开发方式，虽然看起来有点怪异，但编写代码的效率还真不低，也是我最喜欢的开发方式（没有之一）
原文：http://bbs.csdn.net/topics/390431474
          
          
        
      </description>
    </item>
    
    <item>
      <title>VS插件 Resharper 的使用</title>
      <link>https://www.crs811.com/archives/397/</link>
      <pubDate>Fri, 11 Mar 2016 02:21:22 +0000</pubDate>
      
      <guid>https://www.crs811.com/archives/397/</guid>
      <description>
        
          
            一：Reshaper是什么
即便是那些整天攻击 .NET 和 C# 的人，也常常不得不承认 Visual Studio 确实是个够强大的 IDE，除非他认为更少的 IDE 功能和命令行调试才是更强大的。可是，即便如此，仍阻止不了一些第三方的个人和厂商开发出一些插件来让 VS 变得更强大。Reshaper 就是这样一个 VS 插件，它提供了一些在 VS 基础上更方便于程序员使用的功能，当然，劣势是：它耗掉了更多的内存，有可能让你不够强大的开发机变得更慢。
安装完毕后，在 VS 的 Menu 里，多了个 RESHAPER 。
二：设置
1.1 智能提示
安装完毕后，IDE 的智能提示（Intellisense）便会默认使用 Resharper 的提示，不知道为什么，我一直不太喜欢它的提示。改过来，是在Option的窗口中：
1.2 快捷键
强烈建议你使用 Reshaper 的快捷键，不要担心 Reshaper 会把你原来的快捷键设置给覆盖了，因为如果某个快捷键和 VS 是冲突的，Reshaper会让你自己选择需要使用 VS 还是 Resharper 的快捷键，看如下界面：
注意，不要选择 Apply to all Reshaper shortcuts，如果选择了，这个界面将不会再出现了，而一般情况下，你会更喜欢在冲突的时候让自己做决定。
当然，如果你一定要使用 VS 原来的快捷键，那么，就应该在 Option 的如下窗口中选中红框内的选项，然后抖抖手，点 Save：
1.3 如果不喜欢某个提示该怎么办？
是的，你可以修改设置。如下：
在这个例子中，我不喜欢将下划线开头的变量作为 warning 进行提示，我们就可以选择最下方的 change settings…… 进行修改，选择后，如下：
可以看到，我们修改为加了前缀。
三：万能的 Alt + Enter
          
          
        
      </description>
    </item>
    
    <item>
      <title>Markdown 简介</title>
      <link>https://www.crs811.com/archives/386/</link>
      <pubDate>Thu, 10 Mar 2016 09:26:50 +0000</pubDate>
      
      <guid>https://www.crs811.com/archives/386/</guid>
      <description>
        
          
            一、认识 Markdown Markdown 是一种用来写作的轻量级「标记语言」，它用简洁的语法代替排版，而不像一般我们用的字处理软件 Word 或 Pages 有大量的排版、字体设置。它使我们专心于码字，用「标记」语法，来代替常见的排版格式。例如此文从内容到格式，甚至插图，键盘就可以通通搞定了。目前来看，支持 Markdown 语法的编辑器有很多，包括很多网站（例如简书）也支持了 Markdown 的文字录入。Markdown 从写作到完成，导出格式随心所欲，你可以导出 HTML 格式的文件用来网站发布，也可以十分方便的导出 PDF 格式，这种格式写出的简历更能得到 HR 的好感。甚至可以利用 CloudApp 这种云服务工具直接上传至网页用来分享你的文章，全球最大的轻博客平台 Tumblr，也支持使用 Mou 这类 Markdown 工具进行编辑并直接上传。
Markdown 官方文档 这里可以看到官方的 Markdown 语法规则文档，当然，后文我也会用自己的方式，阐述这些语法在实际使用中的用法。
创始人 John Gruber 的 Markdown 语法说明 Markdown 中文版语法说明 使用Markdown的优点 专注你的文字内容而不是排版样式。 轻松的导出 HTML、PDF 和本身的 .md 文件。 纯文本内容，兼容所有的文本编辑器与字处理软件。 可读，直观。适合所有人的写作语言。 我该用什么工具？ Mac平台
在 Mac OS X 上，我强烈建议你用Mou 这款免费且十分好用的 Markdown 编辑器，它支持实时预览，既左边是你编辑 Markdown 语言，右边会实时的生成预览效果，笔者文章就是 Mou 这款应用写出来的。 其次还有很多同类选择。如果你是个编辑作者，我强烈建议你购买 Ulysses Ⅲ，这款应用入围了苹果去年 Mac App Store 的 The Best of 2013，相比 Mou 它支持更多的写作格式、多文档的支持。Mou、iA Writer 这些应用都是基于单文档的管理方式，而 Ulysses Ⅲ 支持 Folder、Filter 的管理，一个 Folder 里面可以创建多个 Sheet，Sheet 之间还可以进行 Combine 处理。
          
          
        
      </description>
    </item>
    
    <item>
      <title>asp.net下载文件几种方式</title>
      <link>https://www.crs811.com/archives/382/</link>
      <pubDate>Mon, 07 Mar 2016 05:02:15 +0000</pubDate>
      
      <guid>https://www.crs811.com/archives/382/</guid>
      <description>
        
          
            protected void Button1_Click(object sender, EventArgs e){/*微软为Response对象提供了一个新的方法TransmitFile来解决使用Response.BinaryWrite下载超过400mb的文件时导致Aspnet_wp.exe进程回收而无法成功下载的问题。代码如下：*/Response.ContentType = &#34;application/x-zip-compressed&#34;;Response.AddHeader(&#34;Content-Disposition&#34;, &#34;attachment;filename=z.zip&#34;);string filename = Server.MapPath(&#34;DownLoad/aaa.zip&#34;);Response.TransmitFile(filename);}//WriteFile实现下载protected void Button2_Click(object sender, EventArgs e){/*using System.IO;*/string fileName = &#34;aaa.zip&#34;;//客户端保存的文件名string filePath = Server.MapPath(&#34;DownLoad/aaa.zip&#34;);//路径FileInfo fileInfo = new FileInfo(filePath);Response.Clear();Response.ClearContent();Response.ClearHeaders();Response.AddHeader(&#34;Content-Disposition&#34;, &#34;attachment;filename=&#34; + fileName);Response.AddHeader(&#34;Content-Length&#34;, fileInfo.Length.ToString());Response.AddHeader(&#34;Content-Transfer-Encoding&#34;, &#34;binary&#34;);Response.ContentType = &#34;application/octet-stream&#34;;Response.ContentEncoding = System.Text.Encoding.GetEncoding(&#34;gb2312&#34;);Response.WriteFile(fileInfo.FullName);Response.Flush();Response.End();}//WriteFile分块下载protected void Button3_Click(object sender, EventArgs e){string fileName = &#34;
          
          
        
      </description>
    </item>
    
    <item>
      <title>Linux(CentOS 7)使用gcc编译c,c&#43;&#43;代码</title>
      <link>https://www.crs811.com/archives/263/</link>
      <pubDate>Tue, 01 Mar 2016 09:03:53 +0000</pubDate>
      
      <guid>https://www.crs811.com/archives/263/</guid>
      <description>
        
          
            ** 安装gcc：**
1、使用 yum -list gcc* 查询 centos 官方gcc的所有包：
可安装的软件包
gcc.x86_64gcc-c++.x86_64gcc-gfortran.x86_64gcc-gnat.x86_64gcc-go.x86_64gcc-objc.x86_64gcc-objc++.x86_64gcc-plugin-devel.x86_642、根据需要安装包，编辑c , c++ 需要安装 gcc.x86_64 和 gcc-c++.x86_64
yum -y install gcc.x86_64yum -y install gcc-c++.x86_64使用gcc:
示例程序如下： //test.c#include int main(){printf(&#34;Hello World!\n&#34;);return 0;}**一. 常用编译命令选项 **
假设源程序文件名为test.c
1. 无选项编译链接
用法：#gcc test.c
作用：将test.c预处理、汇编、编译并链接形成可执行文件。这里未指定输出文件，默认输出为a.out。编译成功后可以看到生成了一个a.out的文件。在命令行输入./a.out 执行程序。./表示在当前目录，a.out为可执行程序文件名。
2. 选项 -o
用法：#gcc test.c -o test
作用：将test.c预处理、汇编、编译并链接形成可执行文件test。-o选项用来指定输出文件的文件名。输入./test执行程序。
3. 选项 -E
用法：#gcc -E test.c -o test.
          
          
        
      </description>
    </item>
    
    <item>
      <title>Apache 2.2 Httpd.conf详解</title>
      <link>https://www.crs811.com/archives/258/</link>
      <pubDate>Wed, 24 Feb 2016 14:29:00 +0000</pubDate>
      
      <guid>https://www.crs811.com/archives/258/</guid>
      <description>
        
          
            apache2.4 新版 变化：
在apache2.4版本之前做客户端访问控制,是用Allow Deny Order指令做访问控制的,而在2.4的版本上是用的用法跟之前的版本大不相同,如下
################################################ 2.2上的配置 Order deny,allow Deny from all 2.4上的配置 Require all denied ################################################ 2.2上的配置 Order allow,deny Allow from all 2.4上的配置 Require all granted ################################################# # Apache服务器主配置文件. 包括服务器指令的目录设置.
# 详见 &amp;lt;URL:http://www.apache.org/docs/&amp;gt;
# 请在理解用途的基础上阅读各指令。
# 再读取此文档后，服务器将继续搜索运行
# E:/Program Files/Apache Group/Apache/conf/srm.conf
# E:/Program Files/Apache Group/Apache/conf/access.conf
# 除非用ResourceConfig或AccessConfig覆盖这儿的标识
# 配置标识由三个基本部分组成:
# 1. 作为一个整体来控制Apache服务器进程的标识 (the &#39;global environment&#39;).
# 2. 用于定义主（默认）服务器参数的标识。
# 响应虚拟主机不能处理的请求。
# 同时也提供所有虚拟主机的设置值。
# 3. 虚拟主机的设置。在一个Apache服务器进程中配置不同的IP地址和主机名。
# 配置和日志文件名：指定服务器控制文件命名时，
# 以 &amp;quot;/&amp;quot; (或 &amp;quot;drive:/&amp;quot; for Win32)开始，服务器将使用这些绝对路径。
          
          
        
      </description>
    </item>
    
    <item>
      <title>五胡十六国的脉络关系</title>
      <link>https://www.crs811.com/archives/875/</link>
      <pubDate>Wed, 03 Feb 2016 23:55:38 +0000</pubDate>
      
      <guid>https://www.crs811.com/archives/875/</guid>
      <description>
        
          
            曹魏在三国争霸中，曹家的大权渐渐被征伐有功的权臣司马懿掌控。司马懿的儿子司马昭发动了灭蜀之战，司马昭的儿子司马炎废了姓曹的，自己当了皇帝，建了晋国。这个晋国又灭了孙吴，一统江湖。
西晋 晋武帝司马炎的江山，是如此的雄壮！
可惜二代名叫司马衷，就是那个问“何不食肉糜”的题主。他娶了个媳妇名叫贾南风，一个傻，一个作。
贾南风 司马衷是个二傻子，朝政就交由贾南风处理了，贾南风想废了司马家。显然司马家的不愿意，于是贾南风开始杀司马家的人，引发了八王之乱。
八王之乱 八王之乱已经够乱，民间还爆发了蝗灾和瘟疫。
这就给了胡人以可乘之机。
首先是大西晋的北部都尉刘渊。虽然姓刘，但却是匈奴人，是冒顿单于的后裔，先祖因跟刘邦结为亲家，所以改姓了刘。 刘渊自幼学了一身的武艺，热爱科学文化，而且人缘十分好。子承父业当了都尉以后，被成都王司马颖引为外援，司马颖要在中原打下一片天。结果才知道什么叫鸠占鹊巢，引狼入室。
刘渊建立了汉国（因为他姓刘），后被改为赵 ，史称前赵。他亲眼看见了八王之乱中原的情况，觉得应该干他们一发。让人招呼匈奴五部人马，高呼“打倒东海王司马越，坚决支持司马颖进中央”的口号，杀过来了。
与此同时，四川也出了大事，因为西北地区连年干旱，百姓只好往南逃难。这里边儿的百姓，包括氐族和汉族。氐族头领李特领着大家跑到了四川，扑面而来的是一通棍棒，官府勒令他们赶紧滚回老家。
要是回去，横竖都是一死。留这里也是个死。但有头领带着闹起来，指不定谁死呢！ 就跟着李特他们闹了。他们在绵竹起义，李特死后，他的蛾子李雄继续战斗，率领起义军攻占了成都，建国为成汉。
当前赵大军进击西晋首都洛阳的时候，刘渊已经病死，刘聪即位。南方的勤王之兵要么动都不动，要么来看了一圈儿就给吓跑了，要么就是让人揍了一顿，遭受了一通毒打，损失惨重，没一个给力的。 于是洛阳失守，晋怀帝被刘聪灌了毒酒死了。 在长安即位的晋愍帝下令与前赵决一死战，可惜没人听他的。 只能投降。 西晋灭亡。
晋愍帝被俘之后，被封为怀平侯，主要负责在宴会上给刘聪倒酒，夜里端尿盆儿的工作。 后来刘聪觉得没意思，就把他杀了。
西晋的司马氏宗族，琅琊王司马睿到了江东（古称江左），建立起新政府，唤作东晋。 原西晋的西北方向，是凉州。凉州刺史名叫张轨，西晋灭亡后，此地被前赵阻断，绝断成为了一个独立的政权。 张轨死后，其子张寔继任，等西晋灭亡后，继续沿用晋愍帝的年号，说是晋国的人，实则是一个完全独立的国家。 史称前凉。
前凉 晋怀帝没死的时候，大北方的鲜卑部落的拓跋猗卢被封为大单于，封代公。等到晋愍帝时，给他封了代王。你也知道，这个晋愍帝已经没什么能力了，代王自成一国，称为代国。
前赵有位猛将，名叫石勒。 这个石勒，是羯族人，很猛，帮前赵打西晋，歼灭对方主力，破洛阳的就是他。后来势力坐大，忽然宣布不跟着前赵干了，自称大将军、大单于、领冀州牧、赵王，直接登基了，自建一国，史称后赵。
后赵 石勒自然是非常富有权谋的一个人，但十分凶悍变态，后来继位的石虎更加变态，石虎的儿子石邃将祖辈的变态发挥到了极致。喜欢杀人玩，让美女打扮好然后下令屠杀，把头放在盘子上展览，人肉煮好以后供大家品尝。这一家子对百姓更不用说了，经常运用两脚羊战术进行战斗，用人肉当军需。
西晋灭亡后，汉族成为五胡屠杀对象，已经不能称作人，只能称作羊，想杀就杀，想吃就吃。
原中原的士民实在无法忍受如此残暴的世界，于是纷纷往南迁徙，史称衣冠南渡。曾有一回，二十万人试图过河却被困，几乎全部死亡。
石虎死后，石世继位。 石世干了一个多月，就被兄弟石遵废了。那时候石虎的养孙冉闵很能干，石遵许诺，以后必然会立冉闵为太子。后来一想，他喵的我为什么要立一个异姓当太子！又不同意了。
冉闵很生气，石遵死后，石鉴即位，想除去冉闵这个隐患，被冉闵和李农合伙弄死。一群人要拥戴冉闵当皇帝。冉闵说我不好意思，非让李农当皇帝。李农说你要是不当我就死给你看，冉闵都哭了，说我也实在不是谦虚，还是你当最合适。李农真的要上吊，逼着冉闵即位，冉闵说那就不好意思了，于是登基。 冉闵建国，称之冉魏。
然而冉魏很快就被鲜卑慕容氏在燕地建立的前燕灭了，因为石鉴死后，石家后人占据了一块地方继续跟冉闵撕，引援羌族和前燕，冉闵全歼后赵后，前燕立即南下跟冉闵干，冉闵兵败被俘，冉魏灭亡。 这个前燕，和后来鲜卑族慕容氏建立的几个燕国，就是这位仁兄一直想匡复的：
图为大燕国第四十九代皇帝慕容复，那时燕国已经灭亡700多年
而在此前不久，前后赵大将，氐族优秀中老年苻洪的儿子苻健，在三秦地带扩大了他爹的江山，建立了前秦。可惜苻健的儿子苻生实在是太残暴了，史书称他力大无穷，手格猛虎，但杀人不眨眼。常带着锥子和刀剑在身边，碰见看不顺眼的就砍就杀，光亲手虐待致死的公卿臣妾和奴婢，就有五百多人。 最终要杀堂弟苻坚，被苻坚反杀。 苻坚和前头那几位不大一样，虽然也猛，但他更喜欢文化，重用汉儒王猛辅政，富国强兵，国力强盛。
但苻坚也有怕的人，比方说前燕的慕容垂，他就不敢打。
忽然有一天，慕容垂来了，说要跟苻坚混。原来是前燕内部起了变化，慕容垂因为南下打东晋桓温立下了大功，辅政王慕容评属于那种德高望重的元老，但为政却十分贪婪卑鄙不合群。慕容垂被迫逃离前燕，带着老婆孩子和慕容令、慕容宝、慕容农、慕容楷、兰建、高弼，一起投奔了苻坚。做人做成这样，慕容评也没反思过，继续贪渎，继续害人，怨声载道，军心离散。 没了慕容垂那还怕什么！ 命大臣王猛猛揍前燕15万主力军。 前燕灭亡。
此后，前秦先灭仇池氐杨氏（371年），西南夷邛、筰、夜郎表示归附（373年），再灭前凉，进兵灭代（376年），统一北方。
苻坚的成绩是伟大的。 但他自己觉得，还是不够伟大——他想统一整个中国。一开始王猛劝他不要打，时机不成熟，王猛死后七年，苻坚觉得机会来了，准备南下，颇有大臣劝阻。苻坚以八十万虎狼之师，意欲灭东晋八万汉兵，难道很困难么？ 大臣：有长江天险！ 苻坚：以吾之众旅，投鞭于江足断其流！ 于是在383年，苻坚发动了淝水之战，猛攻东晋。东晋谢安谢太傅命侄子谢玄为先锋迎敌，一举击溃前秦大军，天下震惊。前秦军被打得太惨了，东晋的打法太吓人了，以至于风声鹤唳、草木皆兵，狼狈逃窜，带回去的人，只有十之二三。
淝水之战示意图
苻坚败了。 那些先前被收服的人还能再服气么？ 不能服啊！ 所以先秦统一之前的各国，又都回去了。
最先发难的是慕容垂，他废了前秦的年号，建了自己领导下的燕国，当上了皇帝。 史称后燕。
侄子慕容泓也不装了，他原先是前秦的北地长史，听说叔叔反了，他也反，另外建了个燕国，因为靠西，史称西燕。慕容垂的儿子慕容宝继位后，任命慕容德到山东指导工作，后来这个慕容德自立，也建了个燕国，因为靠南，史称南燕。西燕亡后，原西燕将领汉人冯跋，拥立慕容氏在燕国原地盘新建一国，比较靠北，因此史称北燕。 代国的老大鲜卑族拓跋珪一看苻坚不行了，宣布恢复自我。但这个代国复国才一会儿，就迁都了，废掉了“代”这个名字，改名为“魏”，史称北魏。当时谁也没有想到，他拓跋老儿竟然成了最后的赢家。
原苻坚派出去征讨西域的氐族大将吕光，也在前凉的地盘自建一国，国号凉，史称后凉。吕光后来遭到了讨伐，匈奴族沮渠蒙逊领着众人闹革命，劝说建康太守段业一起，事后大家推举段业为老大，建立了新国，还是叫凉，因为靠北，史称北凉。 北凉曾经的敦煌太守李暠（李唐祖先），自成一家，建了西凉。后凉广武郡公秃发乌孤（鲜卑族，秃发即拓跋）也自行建了南凉。
北凉、西凉、南凉，最多的时间是共存的。
前秦起家的地盘也坏了，苻坚让苻叡去打慕容泓，让姚苌（羌族）当辅佐。然而苻叡是个愣头青，根本就不听劝，败死在华泽。回头苻坚就让姚苌回来，想要治他个辅导不力之罪。姚苌派使者谢罪，使者被苻坚弄死。 一看情况不对，姚老师先跑为敬。跑到了西州，自称大将军、大单于、万年秦王，建了国家，史称后秦。 苻坚又在跟慕容家干仗的时候失利，赶上姚苌也要将他一军，杀得还剩几个人。姚苌权苻坚举办个禅让典礼，苻坚坚决不同意，于是就把苻坚勒死了。这让姚苌很难办，国家都叫秦了，你说你不禅让，还说五胡里面羌族根本排不上号，我没有当皇帝的命，非让我把你勒死。于是假装人不是他杀的，追谥苻坚为壮烈天王。
          
          
        
      </description>
    </item>
    
    <item>
      <title>CentOS 7,8 命令、操作 合辑</title>
      <link>https://www.crs811.com/archives/73/</link>
      <pubDate>Fri, 01 Jan 2016 08:31:26 +0000</pubDate>
      
      <guid>https://www.crs811.com/archives/73/</guid>
      <description>
        
          
            命令 1#联网状态： 2netstat -a 3 4#后台执行的程序： 5ps -aux 6 7#全盘查找文件： 8find / -type f -name [filename] 9 10#在指定目录　（如/etc）中按内容查找包含 content 的所有文件 11ls /etc | xargs grep &amp;#34;content&amp;#34; 12 13init 6 或 reboot #重启： 14init 0 #关机： 15shutdown now # 立即关机 16shutdown +2 # 2 min 后关机 17shutdown 10:01 # 10:01关机 18 19#临时禁ping 20echo 1 &amp;gt; /proc/sys/net/ipv4/icmp_echo_ignore_all 21#临时启用ping 22echo 0 &amp;gt; /proc/sys/net/ipv4/icmp_echo_ignore_all 23 24dhclient -r #释放ip 25dhclient #重新获取ip 26 27#设置主机名为crs811 28hostnamectl set-hostname crs811 Find命令详细用法可参见： Linux-find命令
          
          
        
      </description>
    </item>
    
    <item>
      <title>[转]VS.NET完全手动搭建三层B/S架构</title>
      <link>https://www.crs811.com/archives/192/</link>
      <pubDate>Mon, 28 Dec 2015 03:20:16 +0000</pubDate>
      
      <guid>https://www.crs811.com/archives/192/</guid>
      <description>
        
          
            简介：三层架构(3-tier application) 通常意义上的三层架构就是将整个业务应用划分为：表现层（WebUI）、业务逻辑层（BusinessLogicLayer）、数据访问层（DataAccessLayer），公共层（ModelLayer）。区分层次的目的即为了“高内聚，低耦合”的思想。
一、应用三层架构的优点
三层结构适合群体开发，每人可以有不同的分工，协同工作使效率倍增；各做各的模块，降低开发人员能力要求；方便系统功能的扩展以及后期的维护工作；最大优点是它的安全性。用户端只能通过逻辑层来访问数据层，减少了入口点，把很多危险的系统功能都屏蔽了。可以更好的支持分布式计算环境。逻辑层的应用程序可以有多个机器上运行，充分利用网络的计算功能。分布式计算的潜力巨大，远比升级CPU有效。
二、手动搭建三层架构
** **软件 VS 2008/2010
(也可以用动软.Net代码生成器等自动生成三层架构）
1.建立空白的解决方案
** ** 法1) 文件/新建/项目弹出对话框 选择“其他项目类型”下面的“Visual Studio 解决方案” 单击“空白解决方案” 名称：ling 位置：D/ 确定 完成空白方案搭建
法2) Shift+Ctrl+N 弹出对话框 选择“其他项目类型”下面的“Visual Studio 解决方案”
2.建立三个类库
在解决方案资源管理器中，右击“解决方案ling”选择“ 添加”下面的“新建项目”
在弹出对话框中选择“Visual C#”里面的“类库”
名称：ModelLayer(简写Model) 公共层 位置：D:/ling “确定” 完成一个类库的添加
用相同的方法建立以下两个类库：
名称：DataAccessLayer(简写DAL) 数据访问层 位置：D:/ling
名称：BusinessLogicLayer(简写BLL) 业务逻辑层 位置：D:/ling
3.建立表现层
在解决方案资源管理器中，右击“解决方案ling”选择“ 添加”下面的“新建网站”
在弹出对话框中选择“Asp.NET 网站” 位置：文件系统， D/ling/WebUI
语言：Visual C#(这里值得注意网站的路径为：D/ling/WebUI)
“确定” 完成表现层的搭建
这样我们就完成了基本结构的搭建
4.添加各层之间的引用
4.1 数据访问层（DataAccessLayer）对公共层（ModelLayer）引用
在解决方案资源管理器中，右击“DataAccessLayer”选择“ 添加应用”
弹出“添加引用”对话框，单击“项目” 选择“ModelLayer”
单击“确定” 完成对公共层的引用
4.2 业务逻辑层（BusinessLogicLayer）对DataAccessLayer和ModelLayer引用
          
          
        
      </description>
    </item>
    
    <item>
      <title>ASP.NET三层架构源码(CodeSmith版)之十四：其他公共代码</title>
      <link>https://www.crs811.com/archives/188/</link>
      <pubDate>Mon, 28 Dec 2015 03:11:22 +0000</pubDate>
      
      <guid>https://www.crs811.com/archives/188/</guid>
      <description>
        
          
            包括：
1、帐号处理项目
2、公共函数项目
3、数据操作项目
下载：【_Other】
这些代码为之前生成的代码服务，提供公共方法和数据库操作的方法。
          
          
        
      </description>
    </item>
    
    <item>
      <title>ASP.NET三层架构源码(CodeSmith版)之十三：View-所有模板生成</title>
      <link>https://www.crs811.com/archives/186/</link>
      <pubDate>Mon, 28 Dec 2015 03:06:35 +0000</pubDate>
      
      <guid>https://www.crs811.com/archives/186/</guid>
      <description>
        
          
            动软代码生成器生成的ASP.NET三层架构代码比较规范，是学习ASP.NET的好例子
此三层架构改造自动软的工厂模式模板，使用CodeSmith进行重写，以方便大家修改模板文件
以下是针对视图所有模板共同生成的源码： &lt;%@ CodeTemplate Language=&#34;C#&#34; TargetLanguage=&#34;Text&#34; Src=&#34;&#34; Inherits=&#34;&#34; Debug=&#34;False&#34; CompilerVersion=&#34;v3.5&#34; Description=&#34;Template description here.&#34; %&gt;&lt;%-- SchemaExplorer --%&gt;&lt;%@ Assembly Name=&#34;SchemaExplorer&#34; %&gt;&lt;%@ Import Namespace=&#34;SchemaExplorer&#34; %&gt;&lt;%-- 添加源数据库属性 --%&gt;&lt;%@ Property Name=&#34;SourceDatabase&#34; Type=&#34;SchemaExplorer.DatabaseSchema&#34; DeepLoad=&#34;True&#34; Optional=&#34;False&#34; Category=&#34;01. Required&#34; Description=&#34;Database&#34; %&gt;&lt;%@ Property Name=&#34;vName&#34; Type=&#34;ViewSchema&#34; DeepLoad=&#34;True&#34; Optional=&#34;True&#34; Category=&#34;01. Required&#34; Description=&#34;TableName&#34; %&gt;&lt;%@ Property Name=&#34;Namespace&#34; Type=&#34;String&#34; Category=&#34;Context&#34; Description=&#34;NameSpace&#34;%&gt; &lt;%@ Property Name=&#34;Author&#34; Type=&#34;String&#34; Category=&#34;Context&#34; Description=&#34;Author&#34; Default=&#34;chenr&#34;%&gt; &lt;%@ Property Name=&#34;bGenOne&#34; Type=&#34;Boolean&#34; Category=&#34;Context&#34; Description=&#34;Generate One Template Or All&#34;
          
          
        
      </description>
    </item>
    
    <item>
      <title>ASP.NET三层架构源码(CodeSmith版)之十二：View-StoreProcedure(存储过程)</title>
      <link>https://www.crs811.com/archives/184/</link>
      <pubDate>Mon, 28 Dec 2015 03:05:15 +0000</pubDate>
      
      <guid>https://www.crs811.com/archives/184/</guid>
      <description>
        
          
            动软代码生成器生成的ASP.NET三层架构代码比较规范，是学习ASP.NET的好例子
此三层架构改造自动软的工厂模式模板，使用CodeSmith进行重写，以方便大家修改模板文件
以下是针对视图生成操作存储过程的源码： &lt;%@ CodeTemplate Inherits=&#34;CodeTemplate&#34; language=&#34;C#&#34; TargetLanguage=&#34;Text&#34; Description=&#34;NetTiers main template.&#34;Debug=&#34;True&#34; ResponseEncoding=&#34;UTF-8&#34;%&gt;&lt;%-- 加载访问数据库的组件SchemaExplorer,并声明其使用的命名空间 --%&gt;&lt;%@ Assembly Name=&#34;SchemaExplorer&#34; %&gt; &lt;%@ Import Namespace=&#34;SchemaExplorer&#34; %&gt; &lt;%@ Import Namespace=&#34;System.Text&#34; %&gt; &lt;%@ Assembly Name=&#34;System.Data&#34; %&gt;&lt;%@ Property Name=&#34;Author&#34; Type=&#34;String&#34; Category=&#34;Context&#34; Description=&#34;Author&#34; Default=&#34;chenr&#34;%&gt; &lt;%@ Property Name=&#34;bGenOne&#34; Type=&#34;Boolean&#34; DeepLoad=&#34;True&#34; Optional=&#34;false&#34; Category=&#34;Context&#34; Description=&#34;Generate One View SP Or All&#34; %&gt;&lt;%-- 添加源数据库属性 --%&gt;&lt;%@ Property Name=&#34;SourceDatabase&#34; Type=&#34;SchemaExplorer.DatabaseSchema&#34; DeepLoad=&#34;True&#34; Optional=&#34;False&#34; Category=&#34;01. Required&#34; Description=&#34;Database&#34; %&gt;&lt;%@ Property Name=&#34;vName&#34; Type=&#34;ViewSchema&#34; DeepLoad=&#34;True&#34; Optional=&#34;
          
          
        
      </description>
    </item>
    
    <item>
      <title>ASP.NET三层架构源码(CodeSmith版)之十一：View-SQLServerDAL层</title>
      <link>https://www.crs811.com/archives/181/</link>
      <pubDate>Mon, 28 Dec 2015 03:03:30 +0000</pubDate>
      
      <guid>https://www.crs811.com/archives/181/</guid>
      <description>
        
          
            动软代码生成器生成的ASP.NET三层架构代码比较规范，是学习ASP.NET的好例子
此三层架构改造自动软的工厂模式模板，使用CodeSmith进行重写，以方便大家修改模板文件
以下是针对视图SQLServerDAL层的源码： &lt;%@ CodeTemplate Inherits=&#34;CodeTemplate&#34; language=&#34;C#&#34; TargetLanguage=&#34;Text&#34; Description=&#34;NetTiers main template.&#34;Debug=&#34;True&#34; ResponseEncoding=&#34;UTF-8&#34;%&gt;&lt;%-- 加载访问数据库的组件SchemaExplorer,并声明其使用的命名空间 --%&gt;&lt;%@ Assembly Name=&#34;SchemaExplorer&#34; %&gt; &lt;%@ Import Namespace=&#34;SchemaExplorer&#34; %&gt; &lt;%@ Import Namespace=&#34;System.Text&#34; %&gt; &lt;%@ Assembly Name=&#34;System.Data&#34; %&gt;&lt;%@ Assembly Name=&#34;CodeSmith.BaseTemplates&#34; %&gt;&lt;%@ Import Namespace=&#34;CodeSmith.BaseTemplates&#34; %&gt;&lt;%@ Assembly Name=&#34;CodeSmith.CustomProperties&#34; %&gt;&lt;%@ Import Namespace=&#34;CodeSmith.CustomProperties&#34; %&gt;&lt;%@ Import Namespace=&#34;System.Text.RegularExpressions&#34; %&gt;&lt;%@ Property Name=&#34;Namespace&#34; Type=&#34;String&#34; Category=&#34;Context&#34; Description=&#34;NameSpace&#34;%&gt; &lt;%@ Property Name=&#34;Author&#34; Type=&#34;String&#34; Category=&#34;Context&#34; Description=&#34;Author&#34; Default=&#34;chenr&#34;%&gt; &lt;%@ Property Name=&#34;ViewPrefix&#34; Type=&#34;System.String&#34; Default=&#34;T&#34; Category=&#34;Context&#34; Description=&#34;
          
          
        
      </description>
    </item>
    
    <item>
      <title>ASP.NET三层架构源码(CodeSmith版)之十：View-Model层</title>
      <link>https://www.crs811.com/archives/179/</link>
      <pubDate>Mon, 28 Dec 2015 03:01:56 +0000</pubDate>
      
      <guid>https://www.crs811.com/archives/179/</guid>
      <description>
        
          
            动软代码生成器生成的ASP.NET三层架构代码比较规范，是学习ASP.NET的好例子
此三层架构改造自动软的工厂模式模板，使用CodeSmith进行重写，以方便大家修改模板文件
以下是针对视图Model层的源码： &lt;%@ CodeTemplate Inherits=&#34;CodeTemplate&#34; language=&#34;C#&#34; TargetLanguage=&#34;Text&#34; Description=&#34;NetTiers main template.&#34;Debug=&#34;True&#34; ResponseEncoding=&#34;UTF-8&#34;%&gt;&lt;%@ Assembly Name=&#34;SchemaExplorer&#34; %&gt; &lt;%@ Import Namespace=&#34;SchemaExplorer&#34; %&gt; &lt;%@ Import Namespace=&#34;System.Text&#34; %&gt; &lt;%@ Property Name=&#34;Namespace&#34; Type=&#34;String&#34; Category=&#34;Context&#34; Description=&#34;Namespace&#34;%&gt; &lt;%@ Property Name=&#34;Author&#34; Type=&#34;String&#34; Category=&#34;Context&#34; Description=&#34;Author&#34; Default=&#34;chenr&#34;%&gt; &lt;%@ Property Name=&#34;ViewPrefix&#34; Type=&#34;System.String&#34; Default=&#34;T&#34; Category=&#34;Context&#34; Description=&#34;The prefix to remove from table names&#34; %&gt; &lt;%@ Property Name=&#34;ViewName&#34; Type=&#34;ViewSchema&#34; DeepLoad=&#34;True&#34; Optional=&#34;False&#34; Category=&#34;01. Getting Started - Required&#34; Description=&#34;&#34;%&gt;/*------------------------------------------------ // File Name:m&lt;%=ClearPrefix(ViewName.Name) %&gt;.cs // File Description:&lt;%=ClearPrefix(ViewName.
          
          
        
      </description>
    </item>
    
    <item>
      <title>ASP.NET三层架构源码(CodeSmith版)之九：View-IDAL层（数据访问抽象层）</title>
      <link>https://www.crs811.com/archives/177/</link>
      <pubDate>Mon, 28 Dec 2015 03:00:45 +0000</pubDate>
      
      <guid>https://www.crs811.com/archives/177/</guid>
      <description>
        
          
            动软代码生成器生成的ASP.NET三层架构代码比较规范，是学习ASP.NET的好例子
此三层架构改造自动软的工厂模式模板，使用CodeSmith进行重写，以方便大家修改模板文件
以下是针对视图IDAL层的源码： &lt;%@ CodeTemplate Language=&#34;C#&#34; TargetLanguage=&#34;C#&#34; Description=&#34;Generates a class including a special informational header&#34; %&gt; &lt;%@ Assembly Name=&#34;SchemaExplorer&#34; %&gt; &lt;%@ Import Namespace=&#34;SchemaExplorer&#34; %&gt; &lt;%@ Import Namespace=&#34;System.Text&#34; %&gt; &lt;%@ Property Name=&#34;Namespace&#34; Type=&#34;String&#34; Category=&#34;Context&#34; Description=&#34;NameSpace&#34;%&gt; &lt;%@ Property Name=&#34;Author&#34; Type=&#34;String&#34; Category=&#34;Context&#34; Description=&#34;Author&#34; Default=&#34;chenr&#34;%&gt; &lt;%@ Property Name=&#34;ViewName&#34; Type=&#34;ViewSchema&#34; DeepLoad=&#34;True&#34; Optional=&#34;False&#34; Category=&#34;01. Getting Started - Required&#34; Description=&#34;&#34; %&gt;/*------------------------------------------------ // File Name:I&lt;%=ClearPrefix(ViewName.Name) %&gt;.cs // File Description:&lt;%=ClearPrefix(ViewName.Name) %&gt; Interface // Author:&lt;%=Author%&gt; // Create Time:&lt;%= DateTime.Now.ToString(&#34;yyyy/MM/dd HH:mm:ss&#34;
          
          
        
      </description>
    </item>
    
    <item>
      <title>ASP.NET三层架构源码(CodeSmith版)之八：View-BLL层</title>
      <link>https://www.crs811.com/archives/175/</link>
      <pubDate>Mon, 28 Dec 2015 02:59:24 +0000</pubDate>
      
      <guid>https://www.crs811.com/archives/175/</guid>
      <description>
        
          
            动软代码生成器生成的ASP.NET三层架构代码比较规范，是学习ASP.NET的好例子
此三层架构改造自动软的工厂模式模板，使用CodeSmith进行重写，以方便大家修改模板文件
以下是针对视图BLL层的源码： &lt;%@ CodeTemplate Language=&#34;C#&#34; TargetLanguage=&#34;C#&#34; Description=&#34;Generates a class including a special informational header&#34; %&gt; &lt;%@ Assembly Name=&#34;SchemaExplorer&#34; %&gt; &lt;%@ Import Namespace=&#34;SchemaExplorer&#34; %&gt; &lt;%@ Import Namespace=&#34;System.Text&#34; %&gt; &lt;%@ Property Name=&#34;ViewName&#34; Type=&#34;ViewSchema&#34; DeepLoad=&#34;True&#34; Optional=&#34;False&#34; Category=&#34;01. Getting Started - Required&#34; Description=&#34;&#34; %&gt;&lt;%@ Property Name=&#34;Namespace&#34; Type=&#34;String&#34; Category=&#34;Context&#34; Description=&#34;NameSpace&#34;%&gt; &lt;%@ Property Name=&#34;Author&#34; Type=&#34;String&#34; Category=&#34;Context&#34; Description=&#34;Author&#34; Default=&#34;chenr&#34;%&gt; &lt;%@ Property Name=&#34;ViewPrefix&#34; Type=&#34;System.String&#34; Default=&#34;T&#34; Category=&#34;Context&#34; Description=&#34;The prefix to remove from table names&#34; %&gt; /*------------------------------------------------ // File Name:&lt;%=ClearPrefix(ViewName.
          
          
        
      </description>
    </item>
    
    <item>
      <title>ASP.NET三层架构源码(CodeSmith版)之七：Table-所有模板生成</title>
      <link>https://www.crs811.com/archives/168/</link>
      <pubDate>Mon, 28 Dec 2015 02:32:33 +0000</pubDate>
      
      <guid>https://www.crs811.com/archives/168/</guid>
      <description>
        
          
            动软代码生成器生成的ASP.NET三层架构代码比较规范，是学习ASP.NET的好例子
此三层架构改造自动软的工厂模式模板，使用CodeSmith进行重写，以方便大家修改模板文件
以下是针对表格的所有模板同时生成的源码： &lt;%@ CodeTemplate Language=&#34;C#&#34; TargetLanguage=&#34;Text&#34; Src=&#34;&#34; Inherits=&#34;&#34; Debug=&#34;False&#34; CompilerVersion=&#34;v3.5&#34; Description=&#34;生成所有模板文件&#34; %&gt;&lt;%-- SchemaExplorer --%&gt;&lt;%@ Assembly Name=&#34;SchemaExplorer&#34; %&gt;&lt;%@ Import Namespace=&#34;SchemaExplorer&#34; %&gt;&lt;%-- 添加源数据库属性 --%&gt;&lt;%@ Property Name=&#34;SourceDatabase&#34; Type=&#34;SchemaExplorer.DatabaseSchema&#34; DeepLoad=&#34;True&#34; Optional=&#34;False&#34; Category=&#34;01. Required&#34; Description=&#34;Database&#34; %&gt;&lt;%@ Property Name=&#34;tName&#34; Type=&#34;TableSchema&#34; DeepLoad=&#34;True&#34; Optional=&#34;True&#34; Category=&#34;01. Required&#34; Description=&#34;TableName&#34; %&gt;&lt;%@ Property Name=&#34;Namespace&#34; Type=&#34;String&#34; Category=&#34;Context&#34; Description=&#34;NameSpace&#34;%&gt; &lt;%@ Property Name=&#34;Author&#34; Type=&#34;String&#34; Category=&#34;Context&#34; Description=&#34;Author&#34; Default=&#34;chenr&#34;%&gt; &lt;%@ Property Name=&#34;TablePrefix&#34; Type=&#34;System.String&#34; Default=&#34;T&#34; Category=&#34;Context&#34; Description=&#34;The prefix to remove from table names&#34;
          
          
        
      </description>
    </item>
    
    <item>
      <title>ASP.NET三层架构源码(CodeSmith版)之六：Table-生成DALFactory</title>
      <link>https://www.crs811.com/archives/162/</link>
      <pubDate>Mon, 28 Dec 2015 02:26:37 +0000</pubDate>
      
      <guid>https://www.crs811.com/archives/162/</guid>
      <description>
        
          
            动软代码生成器生成的ASP.NET三层架构代码比较规范，是学习ASP.NET的好例子
此三层架构改造自动软的工厂模式模板，使用CodeSmith进行重写，以方便大家修改模板文件
以下是针对表格的DAL生成工厂的源码： &lt;%@ CodeTemplate Language=&#34;C#&#34; TargetLanguage=&#34;C#&#34; Src=&#34;&#34; Inherits=&#34;OutputFileCodeTemplate&#34; Debug=&#34;False&#34; CompilerVersion=&#34;v3.5&#34; Description=&#34;Template description here.&#34; %&gt;&lt;%-- SchemaExplorer --%&gt;&lt;%@ Assembly Name=&#34;SchemaExplorer&#34; %&gt;&lt;%@ Assembly Name=&#34;CodeSmith.BaseTemplates&#34; %&gt;&lt;%@ Assembly Name=&#34;CodeSmith.CustomProperties&#34; %&gt;&lt;%@ Import Namespace=&#34;SchemaExplorer&#34; %&gt;&lt;%@ Import Namespace=&#34;System.Text&#34; %&gt;&lt;%@ Import Namespace=&#34;CodeSmith.BaseTemplates&#34; %&gt;&lt;%@ Import Namespace=&#34;CodeSmith.CustomProperties&#34; %&gt;&lt;%-- 添加源数据库属性 --%&gt;&lt;%@ Property Name=&#34;SourceDatabase&#34; Type=&#34;SchemaExplorer.DatabaseSchema&#34; DeepLoad=&#34;True&#34; Optional=&#34;False&#34; Category=&#34;01. GettingStarted - Required&#34; Description=&#34;Database&#34; %&gt;&lt;%@ Property Name=&#34;Namespace&#34; Type=&#34;String&#34; Category=&#34;Context&#34; Description=&#34;NameSpace&#34; Default=&#34;CrsNameSpace&#34;%&gt; &lt;%@ Property Name=&#34;
          
          
        
      </description>
    </item>
    
    <item>
      <title>ASP.NET三层架构源码(CodeSmith版)之五：Table-StoreProcedure(存储过程)</title>
      <link>https://www.crs811.com/archives/132/</link>
      <pubDate>Sat, 19 Dec 2015 04:58:19 +0000</pubDate>
      
      <guid>https://www.crs811.com/archives/132/</guid>
      <description>
        
          
            动软代码生成器生成的ASP.NET三层架构代码比较规范，是学习ASP.NET的好例子
此三层架构改造自动软的工厂模式模板，使用CodeSmith进行重写，以方便大家修改模板文件
以下是针对表格的存储过程生成源码：
&lt;%@ CodeTemplate Inherits=&#34;CodeTemplate&#34; language=&#34;C#&#34; TargetLanguage=&#34;Text&#34; Description=&#34;NetTiers main template.&#34;Debug=&#34;True&#34; ResponseEncoding=&#34;UTF-8&#34;%&gt;&lt;%-- 加载访问数据库的组件SchemaExplorer,并声明其使用的命名空间 --%&gt;&lt;%@ Assembly Name=&#34;SchemaExplorer&#34; %&gt; &lt;%@ Import Namespace=&#34;SchemaExplorer&#34; %&gt; &lt;%@ Import Namespace=&#34;System.Text&#34; %&gt; &lt;%@ Assembly Name=&#34;System.Data&#34; %&gt;&lt;%@ Property Name=&#34;Author&#34; Type=&#34;String&#34; Category=&#34;Context&#34; Description=&#34;Author&#34; Default=&#34;chenr&#34;%&gt; &lt;%@ Property Name=&#34;TablePrefix&#34; Type=&#34;System.String&#34; Default=&#34;T&#34; Category=&#34;Context&#34; Description=&#34;The prefix to remove from table names&#34; %&gt; &lt;%@ Property Name=&#34;bGenOne&#34; Type=&#34;Boolean&#34; Category=&#34;Context&#34; Description=&#34;Generate One Template Or All&#34;%&gt;&lt;%-- 添加源数据库属性 --%&gt;&lt;%@ Property Name=&#34;SourceDatabase&#34; Type=&#34;SchemaExplorer.DatabaseSchema&#34; DeepLoad=&#34;True&#34; Optional=&#34;
          
          
        
      </description>
    </item>
    
    <item>
      <title>ASP.NET三层架构源码(CodeSmith版)之四：Table-SQLServerDAL层</title>
      <link>https://www.crs811.com/archives/130/</link>
      <pubDate>Sat, 19 Dec 2015 04:56:08 +0000</pubDate>
      
      <guid>https://www.crs811.com/archives/130/</guid>
      <description>
        
          
            动软代码生成器生成的ASP.NET三层架构代码比较规范，是学习ASP.NET的好例子
此三层架构改造自动软的工厂模式模板，使用CodeSmith进行重写，以方便大家修改模板文件
以下是针对表格的SQLServerDAL层源码：
&lt;%@ CodeTemplate Inherits=&#34;CodeTemplate&#34; language=&#34;C#&#34; TargetLanguage=&#34;Text&#34; Description=&#34;NetTiers main template.&#34;Debug=&#34;True&#34; ResponseEncoding=&#34;UTF-8&#34;%&gt;&lt;%-- 加载访问数据库的组件SchemaExplorer,并声明其使用的命名空间 --%&gt;&lt;%@ Assembly Name=&#34;SchemaExplorer&#34; %&gt; &lt;%@ Import Namespace=&#34;SchemaExplorer&#34; %&gt; &lt;%@ Import Namespace=&#34;System.Text&#34; %&gt; &lt;%@ Assembly Name=&#34;System.Data&#34; %&gt;&lt;%@ Assembly Name=&#34;CodeSmith.BaseTemplates&#34; %&gt;&lt;%@ Import Namespace=&#34;CodeSmith.BaseTemplates&#34; %&gt;&lt;%@ Assembly Name=&#34;CodeSmith.CustomProperties&#34; %&gt;&lt;%@ Import Namespace=&#34;CodeSmith.CustomProperties&#34; %&gt;&lt;%@ Import Namespace=&#34;System.Text.RegularExpressions&#34; %&gt;&lt;%@ Property Name=&#34;Namespace&#34; Type=&#34;String&#34; Category=&#34;Context&#34; Description=&#34;NameSpace&#34; Default=&#34;Crs811NameSpace&#34;%&gt; &lt;%@ Property Name=&#34;Author&#34; Type=&#34;String&#34; Category=&#34;Context&#34; Description=&#34;Author&#34; Default=&#34;chenr&#34;%&gt; &lt;%@ Property Name=&#34;TablePrefix&#34; Type=&#34;System.String&#34; Default=&#34;T&#34; Category=&#34;
          
          
        
      </description>
    </item>
    
    <item>
      <title>ASP.NET三层架构源码(CodeSmith版)之三：Table-Model层</title>
      <link>https://www.crs811.com/archives/128/</link>
      <pubDate>Sat, 19 Dec 2015 04:54:32 +0000</pubDate>
      
      <guid>https://www.crs811.com/archives/128/</guid>
      <description>
        
          
            动软代码生成器生成的ASP.NET三层架构代码比较规范，是学习ASP.NET的好例子
此三层架构改造自动软的工厂模式模板，使用CodeSmith进行重写，以方便大家修改模板文件
以下是针对表格的Model层源码：
&lt;%@ CodeTemplate Inherits=&#34;CodeTemplate&#34; language=&#34;C#&#34; TargetLanguage=&#34;Text&#34; Description=&#34;NetTiers main template.&#34;Debug=&#34;True&#34; ResponseEncoding=&#34;UTF-8&#34;%&gt;&lt;%@ Assembly Name=&#34;SchemaExplorer&#34; %&gt; &lt;%@ Import Namespace=&#34;SchemaExplorer&#34; %&gt; &lt;%@ Import Namespace=&#34;System.Text&#34; %&gt; &lt;%@ Property Name=&#34;Namespace&#34; Type=&#34;String&#34; Category=&#34;Context&#34; Description=&#34;Namespace&#34; Default=&#34;CrsNamespace&#34;%&gt; &lt;%@ Property Name=&#34;Author&#34; Type=&#34;String&#34; Category=&#34;Context&#34; Description=&#34;Author&#34; Default=&#34;chenr&#34;%&gt; &lt;%@ Property Name=&#34;TablePrefix&#34; Type=&#34;System.String&#34; Default=&#34;T&#34; Category=&#34;Context&#34; Description=&#34;The prefix to remove from table names&#34; %&gt; &lt;%@ Property Name=&#34;TableName&#34; Type=&#34;TableSchema&#34; DeepLoad=&#34;True&#34; Optional=&#34;False&#34; Category=&#34;01. Getting Started - Required&#34; Description=&#34;&#34;%&gt;/*------------------------------------------------ // File Name:m&lt;%=ClearPrefix(TableName.Name) %&gt;.cs // File Description:m&lt;%=ClearPrefix(TableName.
          
          
        
      </description>
    </item>
    
    <item>
      <title>ASP.NET三层架构源码(CodeSmith版)之二：Table-IDAL层（数据访问抽象层）</title>
      <link>https://www.crs811.com/archives/125/</link>
      <pubDate>Sat, 19 Dec 2015 04:52:10 +0000</pubDate>
      
      <guid>https://www.crs811.com/archives/125/</guid>
      <description>
        
          
            动软代码生成器生成的ASP.NET三层架构代码比较规范，是学习ASP.NET的好例子
此三层架构改造自动软的工厂模式模板，使用CodeSmith进行重写，以方便大家修改模板文件
以下是针对表格的IDAL层源码：
&lt;%@ CodeTemplate Language=&#34;C#&#34; TargetLanguage=&#34;C#&#34; Description=&#34;Generates a class including a special informational header&#34; %&gt; &lt;%@ Assembly Name=&#34;SchemaExplorer&#34; %&gt; &lt;%@ Import Namespace=&#34;SchemaExplorer&#34; %&gt; &lt;%@ Import Namespace=&#34;System.Text&#34; %&gt; &lt;%@ Property Name=&#34;Namespace&#34; Type=&#34;String&#34; Category=&#34;Context&#34; Description=&#34;The namespace to use for this class&#34; Default=&#34;Crs811NameSpace&#34;%&gt; &lt;%@ Property Name=&#34;Author&#34; Type=&#34;String&#34; Category=&#34;Context&#34; Description=&#34;Author&#34; Default=&#34;chenr&#34;%&gt; &lt;%@ Property Name=&#34;TablePrefix&#34; Type=&#34;System.String&#34; Default=&#34;T&#34; Category=&#34;Context&#34; Description=&#34;The prefix to remove from table names&#34; %&gt; &lt;%@ Property Name=&#34;TableName&#34; Type=&#34;TableSchema&#34; DeepLoad=&#34;True&#34; Optional=&#34;False&#34; Category=&#34;01. Getting Started - Required&#34;
          
          
        
      </description>
    </item>
    
    <item>
      <title>ASP.NET三层架构源码(CodeSmith版)之一：Table-BLL层</title>
      <link>https://www.crs811.com/archives/122/</link>
      <pubDate>Sat, 19 Dec 2015 04:47:32 +0000</pubDate>
      
      <guid>https://www.crs811.com/archives/122/</guid>
      <description>
        
          
            动软代码生成器生成的ASP.NET三层架构代码比较规范，是学习ASP.NET的好例子
此三层架构改造自动软的工厂模式模板，使用CodeSmith进行重写，以方便大家修改模板文件
以下是针对表格的BLL层源码：
&lt;%@ CodeTemplate Language=&#34;C#&#34; TargetLanguage=&#34;C#&#34; Description=&#34;Generates a class including a special informational header&#34; %&gt; &lt;%@ Assembly Name=&#34;SchemaExplorer&#34; %&gt; &lt;%@ Import Namespace=&#34;SchemaExplorer&#34; %&gt; &lt;%@ Import Namespace=&#34;System.Text&#34; %&gt; &lt;%@ Property Name=&#34;TableName&#34; Type=&#34;TableSchema&#34; DeepLoad=&#34;True&#34; Optional=&#34;False&#34; Category=&#34;01. Getting Started - Required&#34; Description=&#34;&#34; %&gt;&lt;%@ Property Name=&#34;Namespace&#34; Type=&#34;String&#34; Category=&#34;Context&#34; Description=&#34;NameSpace&#34; Default=&#34;Crs811NameSpace&#34;%&gt; &lt;%@ Property Name=&#34;Author&#34; Type=&#34;String&#34; Category=&#34;Context&#34; Description=&#34;Author&#34; Default=&#34;chenr&#34;%&gt; &lt;%@ Property Name=&#34;TablePrefix&#34; Type=&#34;System.String&#34; Default=&#34;T&#34; Category=&#34;Context&#34; Description=&#34;The prefix to remove from table names&#34; %&gt; /*------------------------------------------------ // File Name:&lt;%=ClearPrefix(TableName.
          
          
        
      </description>
    </item>
    
    <item>
      <title>Update 两个表之间数据更新</title>
      <link>https://www.crs811.com/archives/118/</link>
      <pubDate>Thu, 17 Dec 2015 08:33:40 +0000</pubDate>
      
      <guid>https://www.crs811.com/archives/118/</guid>
      <description>
        
          
            一、当用一个表中的数据来更新另一个表中的数据，T-SQL提供多种写法(下面列出了二种)，但建议用第一种写法，虽然传统，但结构清晰。
并且要注意，当用一个表中的数据来更新另一个表中的数据时，二个表一定要有关联！
update t1set t1.c2 = t2.c2from t2where t1.c1 = t2.c1 Update t1set t1.c2 = t2.c2from t1 inner join t2on t1.c1 = t2.c1 二、FROM 子句中指定的表的别名不能作为 SET column_name 子句中被修改字段的限定符使用。
例如，下面的内容无效：
UPDATE titlesSET t.ytd_sales = t.ytd_sales + s.qtyFROM titles t, sales sWHERE t.title_id = s.title_idAND s.ord_date = (SELECT MAX(sales.ord_date) FROM sales) 若要使上例合法，请从列名中删除别名 t 或使用本身的表名。
1.
UPDATE titlesSET ytd_sales = t.ytd_sales + s.
          
          
        
      </description>
    </item>
    
    <item>
      <title>UIKit 自由下落图形轨迹的显示</title>
      <link>https://www.crs811.com/archives/19/</link>
      <pubDate>Tue, 17 Nov 2015 08:02:47 +0000</pubDate>
      
      <guid>https://www.crs811.com/archives/19/</guid>
      <description>
        
          
            在UIKit中有一个下落轨迹的图形，我将实验出的实现代码放置在下面：
1// 2// UIKitTestViewController.m 3// UIKitTest 4// 5// Created by chenrs on 14-9-16. 6// Copyright (c) 2014年 chenrs. All rights reserved. 7// 8 9#import &amp;#34;UIKitTestViewController.h&amp;#34; 10 11@interface UIKitTestViewController () &amp;lt;UICollisionBehaviorDelegate&amp;gt; 12@property (strong, nonatomic) UIDynamicAnimator* animator; 13@property (strong, nonatomic) UIGravityBehavior* gravity; 14@property (strong, nonatomic) UICollisionBehavior* collision; 15@property (nonatomic) BOOL firstContact; 16@end 17 18@implementation UIKitTestViewController 19 20- (void)viewDidLoad 21{ 22 [super viewDidLoad]; 23	// Do any additional setup after loading the view, typically from a nib.
          
          
        
      </description>
    </item>
    
    <item>
      <title>UIKit 力学教程</title>
      <link>https://www.crs811.com/archives/17/</link>
      <pubDate>Tue, 17 Nov 2015 07:53:51 +0000</pubDate>
      
      <guid>https://www.crs811.com/archives/17/</guid>
      <description>
        
          
            文章来源：http://www.cocoachina.com/industry/20131226/7614.html
这篇文章还可以在这里找到 英语,
Ray：这篇教程节选自 iOS 7 教程集，它是 iOS 7 盛宴的一部分，希望你能喜欢。
你可能已经注意到 iOS 7 中似乎有一些自相矛盾的地方，苹果在建议放弃真实世界的隐喻和拟物化同时，又鼓励创造体验真实的用户界面。
在实践中这意味着什么呢？iOS 7 的设计目标是鼓励创造能像真实的物理对象一样响应触摸、手势和方向变化的数字界面，而不是像素的简单堆砌。最终，区别于形式上的拟物化，让用户与界面产生更为深刻的联系。
这个任务听起来很艰巨，因为做一个看起来很真实的数字界面，要比做一个体验真实的界面简单得多。值得庆幸的是，你有一些很赞的新工具可以帮助你完成这个任务：UIKit 力学（Dynamics）和动态效果（Motion Effects）。
译者注：关于 UIKit Dynamics 的中译名，我与许多开发者有过讨论，有动力、动力模型、动态等译法。但我认为译为力学更为贴切，希望文中出现的力学知识能让你认同我的看法。
1.UIKit 力学是一个集成到 UIKit 的完整的物理引擎。它使你可以通过添加诸如重力、吸附（弹簧）和作用力等行为（behavior），创造体验真实的界面。你只需定义你的界面元素需要遵从的物理特性，剩下的事交给力学引擎处理即可。
2.动态效果让你能够创造相当酷的视差效果，例如 iOS 7 主屏的动态背景。简单来说，你可以利用手机的加速计提供的数据，开发能够响应手机方向变化的界面。
同时使用动态效果和力学效果，是让数字界面和体验变得栩栩如生的利器。当你的用户看到你的应用以一种自然的、动态的形式响应他们的操作时，就和你的应用产生了更深层次的联系。
开始吧
UIKit 力学非常有意思，最好的学习方法就是从一些小的例子开始。
打开 Xcode，选择 File / New / Project … 然后选择 iOSApplicationSingle View Application 并且命名新的工程为 DynamicsPlayground。创建完工程后，打开 ViewController.m 并且添加下面的代码到 viewDidLoad 的末尾：
UIView* square = [[UIView alloc] initWithFrame: CGRectMake(100, 100, 100, 100)]; square.backgroundColor = [UIColor grayColor]; [self.view addSubview:square]; 以上代码简单地添加了一个方块 UIView 到界面上。
          
          
        
      </description>
    </item>
    
    <item>
      <title>PHP高效率写法（详解原因）</title>
      <link>https://www.crs811.com/archives/10/</link>
      <pubDate>Mon, 16 Nov 2015 07:11:06 +0000</pubDate>
      
      <guid>https://www.crs811.com/archives/10/</guid>
      <description>
        
          
            原文：http://blog.csdn.net/hguisu/article/details/7369827
1.尽量静态化：
如果一个方法能被静态，那就声明它为静态的，速度可提高1/4，甚至我测试的时候，这个提高了近三倍。
当然了，这个测试方法需要在十万级以上次执行，效果才明显。
其实静态方法和非静态方法的效率主要区别在内存：静态方法在程序开始时生成内存,实例方法在程序运行中生成内存，所以静态方法可以直接调用,实例方法要先成生实例,通过实例调用方法，静态速度很快，但是多了会占内存。
任何语言都是对内存和磁盘的操作,至于是否面向对象,只是软件层的问题,底层都是一样的,只是实现方法不同。静态内存是连续的,因为是在程序开始时就生成了,而实例申请的是离散的空间,所以当然没有静态方法快。
静态方法始终调用同一块内存，其缺点就是不能自动进行销毁，而是实例化可以销毁。
2.echo的效率高于print,因为echo没有返回值，print返回一个整型;
测试：
Echo
0.000929 - 0.001255 s (平均 0.001092 seconds)
Print
0.000980 - 0.001396 seconds (平均 0.001188 seconds)
相差8%左右，总体上echo是比较快的。
注意，echo大字符串的时候，如果没有做调整就严重影响性能。使用打开apached的mod_deflate进行压缩或者打开ob_start先将内容放进缓冲区。
3.在循环之前设置循环的最大次数，而非在在循环中;
傻子都明白的道理。
4.销毁变量去释放内存，特别是大的数组;
数组和对象在php特别占内存的，这个由于php的底层的zend引擎引起的，
一般来说，PHP数组的内存利用率只有 1/10, 也就是说，一个在C语言里面100M 内存的数组，在PHP里面就要1G。
特别是在PHP作为后台服务器的系统中，经常会出现内存耗费太大的问题。
5.避免使用像__get, __set, __autoload等魔术方法;
对于__开头的函数就命名为魔术函数，此类函数都在特定的条件下初访的。总得来说，有下面几个魔术函数
__construct()，__destruct()，__get()，__set()，__unset()，__call()，__callStatic()，__sleep()，__wakeup()，__toString()，__set_state()，\__clone()，__autoload()
其实，如果__autoload不能高效的将类名与实际的磁盘文件(注意，这里指实际的磁盘文件，而不仅仅是文件名)对应起来，系统将不得不做大量的文件是 否存在(需要在每个include path中包含的路径中去寻找)的判断，而判断文件是否存在需要做磁盘I/O操作，众所周知磁盘I/O操作的效率很低，因此这才是使得autoload机制效率降低的原因。
因此，我们在系统设计时，需要定义一套清晰的将类名与实际磁盘文件映射的机制。这个规则越简单越明确，autoload机制的效率就越高。
结论：autoload机制并不是天然的效率低下，只有滥用autoload，设计不好的自动装载函数才会导致其效率的降低.
所以说尽量避免使用__autoload魔术方法，有待商榷。
6.requiere_once()比较耗资源;
这是因为requiere_once需要判断该文件是否被引用过),所以能不用尽量不用。常用require/include方法避免。
7.在includes和requires中使用绝对路径。
如果包含相对路径，PHP会在include_path里面遍历查找文件。
用绝对路径就会避免此类问题，因此解析操作系统路径所需的时间会更少。
8.如果你需要得到脚本执行时的时间，$_SERVER[&#39;REQUSET_TIME&#39;]优于time();
可以想象。一个是现成就可以直接用，一个还需要函数得出的结果。
9.能用PHP内部字符串操作函数的情况下，尽量用他们，不要用正则表达式； 因为其效率高于正则;
没得说，正则最耗性能。
有没有你漏掉的好用的函数？例如：strpbrk()strncasecmp()strpos()/strrpos()/stripos()/strripos()加速 strtr如果需要转换的全是单个字符的时候，
用字符串而不是数组来做 strtr：
&lt;?php $addr = strtr($addr, &#34;abcd&#34;, &#34;efgh&#34;); // good $addr = strtr($addr, array(&#39;a&#39; =&gt; &#39;e&#39;, )); // bad ?
          
          
        
      </description>
    </item>
    
  </channel>
</rss>
