Random Stuff from GlacJAYhttps://blog.glacjay.info/Recent content on Random Stuff from GlacJAYHugo -- gohugo.iozh-cnWed, 07 Oct 2020 14:53:18 +0800- 踩坑记:Mobx React 没有触发重绘的问题https://blog.glacjay.info/post/2020-10-07/%E8%B8%A9%E5%9D%91%E8%AE%B0mobx-react-%E6%B2%A1%E6%9C%89%E8%A7%A6%E5%8F%91%E9%87%8D%E7%BB%98%E7%9A%84%E9%97%AE%E9%A2%98/Wed, 07 Oct 2020 14:53:18 +0800https://blog.glacjay.info/post/2020-10-07/%E8%B8%A9%E5%9D%91%E8%AE%B0mobx-react-%E6%B2%A1%E6%9C%89%E8%A7%A6%E5%8F%91%E9%87%8D%E7%BB%98%E7%9A%84%E9%97%AE%E9%A2%98/<p>来水一发:正在学习 <a href="https://mobx.js.org">MobX</a>,用 <code>makeAutoObserverable</code> 写了个 store class,结果发现设置了里面的字段后触发不了重绘,折腾了一圈后发现这字段就没监听上,因为没给初始值(对,懒了,<code>null</code> 都没给😂️),那初始值应该就是 <code>undefined</code> 了,导致被 MobX 忽略掉了😂️</p>
<p>记得看文档的时候也并没有强调过这个,感觉可以加一下,防止新手踩坑吧……不过最近 MobX 正好在整新版,也许文档正好还不完善吧。</p>
- 纯软件共享有线键鼠https://blog.glacjay.info/post/2018-09-09/%E7%BA%AF%E8%BD%AF%E4%BB%B6%E5%85%B1%E4%BA%AB%E6%9C%89%E7%BA%BF%E9%94%AE%E9%BC%A0/Sun, 09 Sep 2018 00:01:18 +0800https://blog.glacjay.info/post/2018-09-09/%E7%BA%AF%E8%BD%AF%E4%BB%B6%E5%85%B1%E4%BA%AB%E6%9C%89%E7%BA%BF%E9%94%AE%E9%BC%A0/<p>嗯……我决定暂时忽略我那个已经攒了二十多条 TODO 项的待写博客标题,还是想到啥写啥吧。</p>
<p>话说我现在也算是个用上了机械键盘的正经程序员了嘛,然后就也像其他人一样再也回不去普通键盘的那种手感了。然额我买的这个是有线键盘,只能接在我的主力工作机上用,需要做 iOS 相关开发的时候就不得不用回我那将近十年高龄的 MBP 自带键盘了,总不能每次切换的时候都来回插拔吧,一度令我很是烦恼。</p>
<p>PS. 之前挑选键盘的时候就发现,为啥现在 84 键的键盘这么少呢,明明既有 87 键的键位完备性,又并不比 60% 键盘大多少来着😜,光是能找到一个合适的入门款就已经不错了,更别提有没有蓝牙款的可选了。不过就算有估计我也不会考虑,因为我还是不太喜欢充电或者换电池这种事情😜</p>
<p>前天……唔已经是大前天了,决定再搜一次看看有没有什么方便的解决办法。靠自己只想到了两个搜索方向,一个是 KVM,好歹我以前也是进过机房的人嘛,优点是连显示器都能共享(我的工作机显示器还是挺大的,比 MBP 不知道高到哪里去了呀),缺点是又要连好几根线,我看了看桌面上已然乱七八糟的走线,决定作罢。</p>
<p>另一个就是有线转蓝牙了,然后就在网上一通搜,还真有这种东东,比如<a href="http://scl13.com/aten-cs533-tap/">这个</a>跟<a href="https://detail.tmall.com/item.htm?spm=a230r.1.14.6.71c938f12f6mUc&id=572409896395&cm_id=140105335569ed55e27b&abbucket=19&sku_properties=5919063:6536025">这个</a>,不过都有点儿小贵呀,都快赶上我这键盘的价格了,而且我也不需要接手机的,犹豫的时候还听到有群友说蓝牙连接其实也不怎么稳定好用来着,于是也作罢了。</p>
<p>这时有群友向我推荐了 <a href="https://symless.com/synergy">synergy</a>,我才知道原来还有通过无线 WIFI 配合软件来实现共享的点子,真是妙啊为啥我之前就想不到呢。哎呀不过这个软件也是要钱的,还是先上 <a href="https://alternativeto.net">alternativeTo</a> 找找看有没有免费的吧😜。支持跨平台的替代中,先是试了下 <a href="http://www.keyboard-and-mouse-sharing.com/">ShareMouse</a>,因为有个人免费版可用,不过后来发现这东东限制一台电脑只能有最多一个显示器,而我今年刚好给主力机配了个 <a href="http://www.dasung.com/front/detail/id/223">Paperlike HD</a>,所以就用不了这个了。</p>
<p>然后就是现在在用的 <a href="https://github.com/debauchee/barrier">barrier</a> 啦。虽然一开始看到这东东是开源的还挺有好感的,不过扫了一眼主页发现貌似只能自己编译感觉好麻烦还是有点儿想放弃的来着。不过好歹咱也是个程序猿啊,编译都搞不定的话怎么说得过去,于是就开搞了。</p>
<p>先是 Windows。需要的编译工具有 cmake、Visual Studio(Community 即可)、Qt、Bonjour SDK for Windows 等,还好这些在 Windows 下也都挺好装的(虽然只有 cmake 可以通过 <a href="https://scoop.sh/">scoop</a> 来装😂),然后按照 <code>./clean_build.bat</code> 里面的代码创建一个 <code>build_env.bat</code> 文件,来设置下所需的环境变量,就可以执行 <code>./clean_build.bat</code> 来编译了。嘛反正在我这儿编译还算顺利(除了搞清楚 Qt 要用最新的 5.11.1 才行,还有缺的那个 <code>dns_sd.h</code> 是出自 Bonjour 之外😂),也能直接跑起来,然后我就又去编 macOS 版本的了。</p>
<p>macOS 的依赖准备也差不多,确保你有 Xcode,然后用 Homebrew 装了 cmake、qt 就够了,Bonjour 本就是苹果家的,应该是算在 Xcode 自带里的吧。同样也需要创建个 <code>build_env.sh</code> 文件,不过就不需要设置依赖路径啥的了,只要指定个 Release 就好。不过编完之后的 <code>barrier</code> 命令不能直接运行,要通过 <code>./build/bundle</code> 目录下的 Barrier.app 来执行才行,把它拖到 Applications 里即可(我一开始没指定编译成 Release,编译出来的 Barrier.app 是运行不了的😂)。</p>
<p>然后就可以跑起来试试啦。Windows 这边指定为服务端,macOS 指定为客户端,Barrier 可以自己通过局域网相互搜索到对方,不过我的 Windows 会被检测出好几个 IP 地址,而对应 Wifi 的那个地址并不是首选的,所以客户端连过来有困难。不过我的 Windows Wifi 地址是固定的,所以只要在客户端手动填下服务端地址就能搞定,就不折腾了。</p>
<p>最后就是服务端的问题了,一直是 starting 状态,从日志看也是要连个啥东西,我猜应该是 Windows Service?然额找了半天也没搞懂该怎么手动安装 service,只好继续去 github 仓库翻翻看有啥提示没。这一翻不要紧,原来 Barrier 仓库的 wiki 是有内容的😂,不只有编译说明(虽然自己摸索也不是很难吧😂(虽然自己摸索出来的 Windows 版不能正常工作吧😂)),还有安装包的下载地址😂😂,当时我就惊了啊,这么重要的东西你为啥不放在首页啊😂。然后我就选择弃疗了,直接下载了 Windows 的安装包搞定,直接跑起来就可以用了😂。</p>
<p>用起来还是挺好的,指定下相对位置后,用鼠标就可以直接在两个屏幕间移来移去啦,然后鼠标在哪个屏幕,键盘焦点就在哪台电脑上,丝般顺滑(好吧鼠标在客户端那边说不上有那么顺滑,毕竟是通过软件和 Wifi 二传手之后的信号😂,不过够用啦),这下不仅能愉快地在两台电脑上都用上我的机械键盘,在切换时也不用再挪椅子啦😂</p>
<p>而且说实话,有时候还是会觉得鼠标比触摸板要更好用一些的,就算是苹果的触摸板(逃</p>
- cmder 颜色配置https://blog.glacjay.info/post/2018-04-05/cmder-%E9%A2%9C%E8%89%B2%E9%85%8D%E7%BD%AE/Thu, 05 Apr 2018 16:25:07 +0800https://blog.glacjay.info/post/2018-04-05/cmder-%E9%A2%9C%E8%89%B2%E9%85%8D%E7%BD%AE/<p>工作需要,现在在用 Windows 10 作为主力开发系统,然后根据以往使用 Linux 和 macOS 的经验,一个好用的终端还是必不可少的,然后就找到了 <a href="http://cmder.net">cmder</a>,一个非常好用的 Windows 终端环境。</p>
<p>PS. 其实倒也不全是因为工作需要啦,现在的 Windows 10 也已经挺好用的了,现在老了也懒得折腾 Linux 桌面了,苹果的电脑还是那么的贵~~,当然最重要的是 Windows 上游戏多啊😂~~。</p>
<p>跟 msys2 这种在 Windows 系统中模拟 Linux 环境的工具不同,cmder 的定位是 Windows 自带 cmd 窗口的替代品。现在有很多命令行工具,如 git、node.js 等,都专门针对 Windows 系统进行了优化,而这样的优化版本是需要在 Windows 自己的 cmd.exe 环境下才能正常运行的,这时一个像 cmder 这样的 cmd.exe 增强工具就很有必要了。至于在 msys2 中通过 pacman 安装的版本,特别是 node.js,实际使用中总会有这样那样的问题,大概还是 unix 版在 Windows 下的水土不服吧。</p>
<p>PS. 有了好用的终端,当然还少不了好用的软件包管理器啦,特别是对 Windows 这种并不原生对命令行特别友好的系统来说,能有个管理器帮忙安装和升级命令行工具的话会方便很多。我自己选用的是 <a href="http://scoop.sh">scoop</a>,虽然没有 <a href="https://chocolatey.org">Chocoletey</a> 那么流行和那么多的软件包数量,但胜在可以方便的定制安装位置(Chocolatey 要定制貌似得用收费版才行),对我来说已经够用了。</p>
<p>emmm 进入正题……之前没在 Windows 下搞过 node.js 开发的时候还不知道,原来 Windows 的 cmd.exe 也是支持彩色输出的,而且颜色还挺多😂。这时遇到的一个问题就是,在 cmder 下用 node.js 时总会有些输出的前景色跟背景色一样导致有些字符显示不出来了😂:</p>
<p><img src="https://blog.glacjay.info/img/2018-04-05/cmder-initial.png#center" alt="初始的 Tomorrow 配色"></p>
<p>从上图可以看出(其实我也是过了一段时间才注意到的😂,因为记得我一开始遇到这个问题的时候,还没有这个显眼的背影色来着,也不记得当时用的是啥配色了😂),画红圈的地方就有字符没能正常显示出来。</p>
<p>经过摸索,只要按照下图中的配置就可以把这个颜色问题给修正过来了:</p>
<p><img src="https://blog.glacjay.info/img/2018-04-05/cmder-settings.png#center" alt="相关的 cmder 配置项"></p>
<p>下面是最终效果图:</p>
<p><img src="https://blog.glacjay.info/img/2018-04-05/cmder-final.png#center" alt="最终效果图"></p>
<p>嘛,虽然原来的背景色没了,不过至少能看了不是😂</p>
- vue 集成 iframehttps://blog.glacjay.info/post/2018-01-07/vue-%E9%9B%86%E6%88%90-iframe/Sun, 07 Jan 2018 14:09:22 +0800https://blog.glacjay.info/post/2018-01-07/vue-%E9%9B%86%E6%88%90-iframe/<p>书接上回:最近不是在用 <a href="https://vuejs.org/">vue</a> 开发 H5 App 嘛(再后来又加上了 react-native 😂,这个以后有机会说),我们有个接口返回的是 HTML 页面,在原来的原生 App 里面自然是用个 WebView 控件来展示啦,但我们现在整个应用都是 H5 了,HTML 里面嵌另一个 HTML,那第一反应自然就是 iframe 啰。</p>
<p>PS. H5 里面是嵌不了原生控件的对吧?react-native 是可以的,有时确实是要方便一些的……吧</p>
<p>PSS. 除了 iframe 之外呢,最近好像还有一个比较新的标准是 <a href="https://www.webcomponents.org/">web components</a>,也是用来做内嵌的吧,但对浏览器的版本要求应该比较高(虽然也是有 polyfill 的啦),记得我当时好像也是试了一下的,但是没成功 😂,也不记得是啥问题了,而且 iframe 也能满足要求啦,所以就没弄这个了。回头有机会再研究下吧。</p>
<p>如果只是简单的页面展示的话,直接通过 <code><iframe></code> 控件的 <code>:src</code> 属性绑定页面 URL 就完事啦。</p>
<p>但我们这是个 App 嘛,页面里面也是有一些可交互元素的,比如点击跳转到详情页之类的,这时就要绑定 <code><iframe></code> 的 <code>@load</code> 事件(vue 写法,对应于 JS 接口里面的 <code>onload</code> 事件),示例代码如下:</p>
<!-- raw HTML omitted -->
<p>要点:</p>
<ul>
<li>第 15 行:在 <code>@load</code> 事件回调方法 <code>onIframeLoad</code> 中,iframe 控件本身可以从 <code>event.target</code> 中得到,不需要用 vue 的 ref 之类的。</li>
<li>第 16 行:要从 iframe 页面中访问外部提供的接口,可以通过发送 <code>message</code> 事件来实现,那么在外部的 HTML 环境中就要通过 <a href="https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener"><code>window.addEventListener()</code></a> 来设置对该事件的监听函数。这里的 <code>window</code> 对象就是 iframe 外部 vue 所在的浏览器对象。</li>
<li>第 17 行:从外部访问 iframe 本身的 <code>window</code> 对象就是通过 <code>iframe.contentWindow</code> 来得到,而调用该对象的 <code>eval</code> 方法就是从外部对 iframe 进行操作的一般方法了。该方法接受一个字符串参数,可以传入一段完整的 JS 代码,这时用 JS 新特性 template literals 来传这个参数就会很舒服了,既支持多行,又支持内嵌表达式,可以传点儿参数进去。</li>
<li>第 18 行:耶,服务端返回回来的页面自带 <del>jQuery</del> <a href="http://zeptojs.com/">zepto</a>,这让我们的字符串小脚本好写很多啦。不过要注意:由于这段脚本是要直接在 iframe 所在的浏览器环境(WebView)里面跑的,而不是像外面的 vue 会先经过 babel 的编译(因为用了 <a href="https://vuejs.org/v2/guide/single-file-components.html">.vue 格式</a>嘛),所以最好不要用那些个比较新的语法,比如这里就没有用 <code>() => {}</code> 的匿名函数写法(因为……我也懒得查啦,而且手机的 WebView 兼容性嘛,你懂的 😏)。</li>
<li>第 19 行:在 iframe 环境中,<code>window.parent</code> 就是其外部环境的 <code>window</code> 对象啦,调用其 <a href="https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage"><code>postMessage</code></a> 方法就可以往外边发 <code>message</code> 事件了,所传参数会最终变成该事件的 <code>data</code> 字段。</li>
<li>第 30 行:最终接收到 iframe 传出来的 <code>message</code> 事件,然后就……该干嘛干嘛啰。</li>
</ul>
<p>OK,以上就是本次的 vue 集成 iframe 并实现互操作的方法总结啦。</p>
- quasar 开发中的跨域问题https://blog.glacjay.info/post/2017-12-18/quasar-%E5%BC%80%E5%8F%91%E4%B8%AD%E7%9A%84%E8%B7%A8%E5%9F%9F%E9%97%AE%E9%A2%98/Mon, 18 Dec 2017 23:30:22 +0800https://blog.glacjay.info/post/2017-12-18/quasar-%E5%BC%80%E5%8F%91%E4%B8%AD%E7%9A%84%E8%B7%A8%E5%9F%9F%E9%97%AE%E9%A2%98/<p>最近在用 vue 三件套 + quasar 开发 hybrid app,遇到了一个跨域问题,简单记录一下。</p>
- Firefox 插件:TooManyTabshttps://blog.glacjay.info/post/2016-04-23/firefox-%E6%8F%92%E4%BB%B6toomanytabs/Sat, 23 Apr 2016 10:33:22 +0800https://blog.glacjay.info/post/2016-04-23/firefox-%E6%8F%92%E4%BB%B6toomanytabs/<p><a href="https://addons.mozilla.org/en-US/firefox/addon/toomanytabs-saves-your-memory/">TooManyTabs</a> 简直是标(tuo)签(yan)党(zheng)的福音啊!每每在一大堆待读标签里面翻找要看的网页简直要疯掉!包括我和我的内存 ▔f゚゚▔</p>
<p>但只是简单的插件介绍的话是不足以让我这个万年懒癌晚期开工写博的,主要是这货配合 Firefox 的帐户同步功能的时候有点儿坑:一开始没有给分组重命名的时候,几个电脑的 TooManyTabs 一同步就全乱套了;直到我把各个电脑的分组都分别命名,然后又费了老劲儿地整理一番之后才搞定。</p>
<p>让我觉得这个插件很神奇的是,它是用 Firefox 的书签功能来保存标签的,但又不是简单地保存网址,因为标签恢复之后其前进后退的历史也都一并恢复了。看来 Firefox 的书签还有很多的隐藏功能有待发掘啊。</p>
<p>最后的最后,既然是通过书签功能来保存和同步的,那如果 Firefox Android 的书签功能能再给点儿力就好了,让我可以直接把网址保存到指定的分组下面,这样就不用先发送到电脑上再(能用电脑时)TooManyTabs 了(再加上 Firefox Android 的发送标签功能有时还会丢标签)。</p>
<p>以上</p>
- 我的 MBP SSD 优化过程https://blog.glacjay.info/post/2015-01-17/%E6%88%91%E7%9A%84-mbp-ssd-%E4%BC%98%E5%8C%96%E8%BF%87%E7%A8%8B/Sat, 17 Jan 2015 16:40:49 +0800https://blog.glacjay.info/post/2015-01-17/%E6%88%91%E7%9A%84-mbp-ssd-%E4%BC%98%E5%8C%96%E8%BF%87%E7%A8%8B/<p>嗯,这次的标题终于没那么长了 ;-)</p>
<hr>
<p>给我的 MBP 换 SSD 已经是很久之前的事了,当时就已经折腾过一次优化了,不过没有相应的记录。最近发现了新装的 Yosemite 的一些老是搞不定而且连原因都不知道的问题(其中一个可以参见<a href="http://apple.stackexchange.com/questions/163500/when-i-want-to-install-teamviewer-10-why-cant-i-select-my-system-disk-as-the-d" title="AskDifferent: When I want to install TeamViewer 10, why can't I select my system disk as the distination?">我在 AskDifferent 上的提问</a>),一怒之下重装之,自然对 SSD 的优化也要重新搞一遍。搞的过程中发现有的手段能用,有的却不行,特此记录。</p>
<p>优化手段的主要来源是<a href="http://chenyufei.info/blog/2011-09-06/13-%E5%AF%B8-macbook-pro-%E6%8B%86%E5%85%89%E9%A9%B1%E6%9B%B4%E6%8D%A2-ssd/" title="13 寸 Macbook Pro 拆光驱更换 SSD">朋友的一篇博文</a>及其中的链接。</p>
<p><strong>注意:操作有风险,动手须谨慎哟。因为我是不(lan)会(de)做太多解释的,所以你一定要在操作前搞清楚那些个命令的作用哟,特别是像 <code>rm</code> 啦 <code>mv</code> 啦之类的危险命令哟,可别说我没提醒你哟 -_-</strong></p>
- Keepalived 实现双机热备并对关键进程进行监控https://blog.glacjay.info/post/2014-06-22/keepalived-%E5%AE%9E%E7%8E%B0%E5%8F%8C%E6%9C%BA%E7%83%AD%E5%A4%87%E5%B9%B6%E5%AF%B9%E5%85%B3%E9%94%AE%E8%BF%9B%E7%A8%8B%E8%BF%9B%E8%A1%8C%E7%9B%91%E6%8E%A7/Sun, 22 Jun 2014 01:09:12 +0800https://blog.glacjay.info/post/2014-06-22/keepalived-%E5%AE%9E%E7%8E%B0%E5%8F%8C%E6%9C%BA%E7%83%AD%E5%A4%87%E5%B9%B6%E5%AF%B9%E5%85%B3%E9%94%AE%E8%BF%9B%E7%A8%8B%E8%BF%9B%E8%A1%8C%E7%9B%91%E6%8E%A7/<p>三连更有木有!(对不起我网文看多了,而且中间其实断过两天的,我不会告诉你其实是我把这事儿给忘了的)</p>
<p>另,这篇照例是工作需要。</p>
<hr>
<p>使用 Keepalived 实现多机热备(无负载均衡)时,除了对网口状态的监控外,一般还要对系统关键进程(如 Web 服务器的话就是 nginx 或者 httpd 之类的)进行监控,这时就要用到 <code>vrrp_script</code> 配置。网上能找到的 <code>vrrp_script</code> 示例都使用了 <code>weight</code> 选项,以实现基于优先级机制的切换,我在使用中遇到了一点儿问题,总结一下。</p>
- LoadRunner 中进行 HTTP 测试时使 Keep-Alive 生效的注意事项https://blog.glacjay.info/post/2014-06-19/loadrunner-%E4%B8%AD%E8%BF%9B%E8%A1%8C-http-%E6%B5%8B%E8%AF%95%E6%97%B6%E4%BD%BF-keep-alive-%E7%94%9F%E6%95%88%E7%9A%84%E6%B3%A8%E6%84%8F%E4%BA%8B%E9%A1%B9/Thu, 19 Jun 2014 00:23:16 +0800https://blog.glacjay.info/post/2014-06-19/loadrunner-%E4%B8%AD%E8%BF%9B%E8%A1%8C-http-%E6%B5%8B%E8%AF%95%E6%97%B6%E4%BD%BF-keep-alive-%E7%94%9F%E6%95%88%E7%9A%84%E6%B3%A8%E6%84%8F%E4%BA%8B%E9%A1%B9/<p>工作需要,在使用 LoadRunner 进行 HTTP 测试时,为了使每个虚拟用户在不同的循环周期中都能保持长连接,则除了要打开 Keep-Alive 运行时配置(默认打开)之外,还有两个选项需要修改,这两个选项都在运行时配置的「Browser - Browser Simulation」中:</p>
<ul>
<li>
<p>Simulate browser cache :取消勾选。禁用对浏览器缓存机制的模拟,令虚拟用户确实的每次都真正发起与 Web 服务器的对话,而不是只读取一下缓存。</p>
</li>
<li>
<p>Simulate a new user on each iteration :取消勾选。不要在每次执行 Action 之前重置虚拟用户的状态,不然会把原来的 TCP 长连接也重置掉,Keep-Alive 就没用了(更准确地说,是在不同循环周期之间就没用了)。</p>
</li>
</ul>
- VS2010 环境中调试 IE ActiveX 控制时断点不起作用的问题https://blog.glacjay.info/post/2014-06-18/vs2010-%E7%8E%AF%E5%A2%83%E4%B8%AD%E8%B0%83%E8%AF%95-ie-activex-%E6%8E%A7%E5%88%B6%E6%97%B6%E6%96%AD%E7%82%B9%E4%B8%8D%E8%B5%B7%E4%BD%9C%E7%94%A8%E7%9A%84%E9%97%AE%E9%A2%98/Wed, 18 Jun 2014 22:29:01 +0800https://blog.glacjay.info/post/2014-06-18/vs2010-%E7%8E%AF%E5%A2%83%E4%B8%AD%E8%B0%83%E8%AF%95-ie-activex-%E6%8E%A7%E5%88%B6%E6%97%B6%E6%96%AD%E7%82%B9%E4%B8%8D%E8%B5%B7%E4%BD%9C%E7%94%A8%E7%9A%84%E9%97%AE%E9%A2%98/<p>又是惯例的长了好长时间的草,今天先来篇短的。</p>
<p>工作需要,在使用 VS2010 开发调试 IE ActiveX 插件时,默认条件下下的断点不起作用,这是因为选错了调试器,在工程属性 - Debugging 中的 Debugger to launch 项,选择 Web Browser Debugger ,然后在 HTTP URL 项填本地 HTML 文件的绝对路径,以 file:/// 打头就可以了。</p>
- OpenSSL 与 WinSock2 配合使用时遇到的一个坑https://blog.glacjay.info/post/2014-03-29/openssl-%E4%B8%8E-winsock2-%E9%85%8D%E5%90%88%E4%BD%BF%E7%94%A8%E6%97%B6%E9%81%87%E5%88%B0%E7%9A%84%E4%B8%80%E4%B8%AA%E5%9D%91/Sat, 29 Mar 2014 23:06:38 +0800https://blog.glacjay.info/post/2014-03-29/openssl-%E4%B8%8E-winsock2-%E9%85%8D%E5%90%88%E4%BD%BF%E7%94%A8%E6%97%B6%E9%81%87%E5%88%B0%E7%9A%84%E4%B8%80%E4%B8%AA%E5%9D%91/<p>今天才发现,这里已经两年多没有被照看过了,估计连树都要长出来了吧。</p>
<hr>
<p>在用 Windows 的 WSAEventSelect 模式进行网络编程时,比较固定的一个模式是这样的:</p>
- 修改 OpenVPN 实现加密算法的自动协商https://blog.glacjay.info/post/2011-09-17/%E4%BF%AE%E6%94%B9-openvpn-%E5%AE%9E%E7%8E%B0%E5%8A%A0%E5%AF%86%E7%AE%97%E6%B3%95%E7%9A%84%E8%87%AA%E5%8A%A8%E5%8D%8F%E5%95%86/Sat, 17 Sep 2011 00:00:00 +0000https://blog.glacjay.info/post/2011-09-17/%E4%BF%AE%E6%94%B9-openvpn-%E5%AE%9E%E7%8E%B0%E5%8A%A0%E5%AF%86%E7%AE%97%E6%B3%95%E7%9A%84%E8%87%AA%E5%8A%A8%E5%8D%8F%E5%95%86/<p>由<a href="https://blog.glacjay.info/post/2011-01-18/openvpn-%E7%9A%84%E5%88%9D%E5%A7%8B%E5%8C%96%E8%BF%87%E7%A8%8B%E5%88%86%E6%9E%90/">另一篇博</a>中的分析可知,OpenVPN 中有两个加解密通道。一条是标准的 SSL 协议通道,被 OpenVPN 用于协商自己所用的密钥。这个通道的加密算法当然也是通过 SSL 协议来进行协商的,可以通过 <code>--tls-cipher</code> 选项来进行配置。另一条是 OpenVPN 自己的加解密通道,用于交换实际的数据,也就是虚拟网卡抓到的 IP 报文。这个通道的加密算法则是通过 <code>--cipher</code> 和 <code>--auth</code> 两个选项,分别在通调两端指定的。</p>
<p>对于第二条通道的加密算法,必须要同时在两端分别指定一致的选项,有时候不是很方便(当然,我研究的还是 2.1.1 版本的 OpenVPN ,不知道最新的版本还是不是这样)。比如说,我想通过在服务端修改配置,指定加密算法,然后让连接我的客户端自动用同一个算法。最简单的修改思路,就是借用第一条通道中的算法协商机制,从 SSL 对象中取得协商出来的算法。</p>
- 编写自己的 Web 版 Google Reader 客户端https://blog.glacjay.info/post/2011-08-11/%E7%BC%96%E5%86%99%E8%87%AA%E5%B7%B1%E7%9A%84-web-%E7%89%88-google-reader-%E5%AE%A2%E6%88%B7%E7%AB%AF/Thu, 11 Aug 2011 00:00:00 +0000https://blog.glacjay.info/post/2011-08-11/%E7%BC%96%E5%86%99%E8%87%AA%E5%B7%B1%E7%9A%84-web-%E7%89%88-google-reader-%E5%AE%A2%E6%88%B7%E7%AB%AF/<p>最近花在路上的时间明显变多了,手机就成了我打发这些路上时间的利器。小说神马的看太多也会腻,正好 Google Reader 中也积累了大量的未读文章,因此用手机看看订阅文章就成了一个比较好的选择。</p>
<p>但多次使用下来,却也发现了很多 Google 原版 Web 界面的不方便之处。Google 提供了两个版本的 Reader 界面给手机,一个是苹果风格的 <code>/i/</code> 界面,设计得很漂亮,功能也很全,用 Nokia 手机也能看,但太费流量(未证实,只是感觉,大概是因为一次加载了很多的文章吧),而且在网络状况不好的时候,体验不太好。另一个是 <code>/m/</code> 界面,很简洁,选项不多,但也总有些这样那样的细节另我不太满意,下面详述。然后又去找 Nokia 的 S60v3 客户端软件,总之是没一个喜欢啦。作为一个 Geek (至少是自称),在这种情况下,最佳选择自然就是打造一个自己专属的解决方案啦。</p>
<p>正好蹭着同学的一个 PHP 空间(其实也有 Python 和 Ruby 可选啦,但总觉得会很折腾,还是 PHP 好点,虽然折腾也少不了,见下),于是花了几天时间,连复习 PHP (以前只学过没用过,主要还是看 w3schools 的教程和查 php.net 的函数文档)、研究 OAuth (参见<a href="http://www.ioncannon.net/programming/1443/google-oauth-for-installed-apps-php-example/">这篇文章</a>,不过 Web 应用稍有不同)、研究 Google Reader API (参见<a href="http://blog.martindoms.com/2009/08/15/using-the-google-reader-api-part-1/">这系列文章</a>)、编写代码,终于搞定了一个很阳春的 Google Reader Mobile 版,刚刚满足我的手机阅读需要。</p>
- [转载] Compilers: what are you thinking about?https://blog.glacjay.info/post/2011-07-26/%E8%BD%AC%E8%BD%BD-compilers-what-are-you-thinking-about/Tue, 26 Jul 2011 00:00:00 +0000https://blog.glacjay.info/post/2011-07-26/%E8%BD%AC%E8%BD%BD-compilers-what-are-you-thinking-about/<p>最近在翻看以前加星的 Google Reader 文章,把有用的整理出来打标签,然后就看到了这篇。原文作者的博客现在不知道被丢到哪边去了,搜也搜不到,转到这里,权当保存一下吧。</p>
<p>原文链接:<a href="http://www.onebadseed.com/blog/?p=119">Compilers: what are you thinking about?</a>。当然,已经打不开了。</p>
<hr>
<h2 id="compilers-what-are-you-thinking-about">Compilers: what are you thinking about?</h2>
<p>Author: Rotten Cotton</p>
<p>My recent post <a href="http://www.onebadseed.com/blog/?p=103">Compiler bibliography</a>, a motley list of compiler papers that had been sitting in a box in my attic, generated a surprising amount of traffic: over a thousand unique visitors. But no comments. For those of you interested in compiler design, I ask, what are you trying to understand? What are you trying to do?</p>
- [翻译] 用 Ruby 写编译器之六:匿名函数 lambdahttps://blog.glacjay.info/post/2011-05-21/%E7%BF%BB%E8%AF%91-%E7%94%A8-ruby-%E5%86%99%E7%BC%96%E8%AF%91%E5%99%A8%E4%B9%8B%E5%85%AD%E5%8C%BF%E5%90%8D%E5%87%BD%E6%95%B0-lambda/Sat, 21 May 2011 00:00:00 +0000https://blog.glacjay.info/post/2011-05-21/%E7%BF%BB%E8%AF%91-%E7%94%A8-ruby-%E5%86%99%E7%BC%96%E8%AF%91%E5%99%A8%E4%B9%8B%E5%85%AD%E5%8C%BF%E5%90%8D%E5%87%BD%E6%95%B0-lambda/<p>原文链接:<a href="http://www.hokstad.com/writing-a-compiler-in-ruby-bottom-up-step-6.html">http://www.hokstad.com/writing-a-compiler-in-ruby-bottom-up-step-6.html</a></p>
<hr>
<p>既然上次已经提到说,我们其实是在从 Lisp、Scheme 还有类似的其他语言中借鉴各种要实现的功能(我没想过要把这个项目做成原创的⋯⋯或者至少也要等到以后再说吧),那么现在也<strong>是时候</strong>实现一些更加强大的功能了。</p>
<h2 id="那就来做延迟求值以及匿名函数吧">那就来做延迟求值以及匿名函数吧</h2>
<p>Lambda ,又名匿名函数,可以像普通的数值或者字符串类型那样被当作函数参数来到处传递,也可以在需要的时候才调用(当然不调也可以)。同时,外层函数(也就是定义匿名函数的函数)作为它们的运行环境,在其中定义的局部变量可以被这些匿名函数所访问。这就形成了[一个闭包](<a href="http://en.wikipedia.org/wiki/Closure_(computer_science">http://en.wikipedia.org/wiki/Closure_(computer_science</a>))。我们这次<strong>并不是</strong>要实现完整的闭包功能,只是开头的一小步而已,完整的实现要等到再后面了。</p>
- [翻译] 用 Ruby 写编译器之五:整数常量,以及 if 语句https://blog.glacjay.info/post/2011-05-17/%E7%BF%BB%E8%AF%91-%E7%94%A8-ruby-%E5%86%99%E7%BC%96%E8%AF%91%E5%99%A8%E4%B9%8B%E4%BA%94%E6%95%B4%E6%95%B0%E5%B8%B8%E9%87%8F%E4%BB%A5%E5%8F%8A-if-%E8%AF%AD%E5%8F%A5/Tue, 17 May 2011 00:00:00 +0000https://blog.glacjay.info/post/2011-05-17/%E7%BF%BB%E8%AF%91-%E7%94%A8-ruby-%E5%86%99%E7%BC%96%E8%AF%91%E5%99%A8%E4%B9%8B%E4%BA%94%E6%95%B4%E6%95%B0%E5%B8%B8%E9%87%8F%E4%BB%A5%E5%8F%8A-if-%E8%AF%AD%E5%8F%A5/<p>原文链接:<a href="http://www.hokstad.com/writing-a-compiler-in-ruby-bottom-up-step-5.html">http://www.hokstad.com/writing-a-compiler-in-ruby-bottom-up-step-5.html</a></p>
<hr>
<p>上次我承诺会发布的更快一些,不过还是失败了⋯⋯作为补偿,这章的内容将会是原计划中的第 5,6,7 章内容的合并,因为这三章确实都很短。闲话少叙:</p>
<h2 id="处理数字常量">处理数字常量</h2>
<p>到目前为止,我们只处理了一些实现所必须的数字常量,也就是当一个外部函数的返回值是数字的情况,而且没有做任何形式的类型检查。</p>
- [翻译] 用 Ruby 写编译器之四:自定义函数,以及运行时支持https://blog.glacjay.info/post/2011-05-09/%E7%BF%BB%E8%AF%91-%E7%94%A8-ruby-%E5%86%99%E7%BC%96%E8%AF%91%E5%99%A8%E4%B9%8B%E5%9B%9B%E8%87%AA%E5%AE%9A%E4%B9%89%E5%87%BD%E6%95%B0%E4%BB%A5%E5%8F%8A%E8%BF%90%E8%A1%8C%E6%97%B6%E6%94%AF%E6%8C%81/Mon, 09 May 2011 00:00:00 +0000https://blog.glacjay.info/post/2011-05-09/%E7%BF%BB%E8%AF%91-%E7%94%A8-ruby-%E5%86%99%E7%BC%96%E8%AF%91%E5%99%A8%E4%B9%8B%E5%9B%9B%E8%87%AA%E5%AE%9A%E4%B9%89%E5%87%BD%E6%95%B0%E4%BB%A5%E5%8F%8A%E8%BF%90%E8%A1%8C%E6%97%B6%E6%94%AF%E6%8C%81/<p>原文链接:<a href="http://www.hokstad.com/writing-a-compiler-in-ruby-bottom-up-step-4.html">http://www.hokstad.com/writing-a-compiler-in-ruby-bottom-up-step-4.html</a></p>
<hr>
<p>抱歉,又拖了很长时间。要忙的事情实在很多。正如上一篇文章末尾提到的那样,这次要讲的是自定义函数,以及一个简单的“运行时库”。</p>
<h2 id="自定义函数">自定义函数</h2>
<p>一门编程语言如果连函数和方法都没有的话,那也就不能算是一门语言了。而且,实践表明,一门面向对象语言中的所有特性都可以通过过程式的语言要素来实现:一个方法也只不过是以一个对象为额外参数的函数而已。因此,增加对函数的支持就是实现一门语言的核心所在。</p>
- [翻译] 用 Ruby 写编译器之三:语句序列,以及子表达式https://blog.glacjay.info/post/2011-05-02/%E7%BF%BB%E8%AF%91-%E7%94%A8-ruby-%E5%86%99%E7%BC%96%E8%AF%91%E5%99%A8%E4%B9%8B%E4%B8%89%E8%AF%AD%E5%8F%A5%E5%BA%8F%E5%88%97%E4%BB%A5%E5%8F%8A%E5%AD%90%E8%A1%A8%E8%BE%BE%E5%BC%8F/Mon, 02 May 2011 00:00:00 +0000https://blog.glacjay.info/post/2011-05-02/%E7%BF%BB%E8%AF%91-%E7%94%A8-ruby-%E5%86%99%E7%BC%96%E8%AF%91%E5%99%A8%E4%B9%8B%E4%B8%89%E8%AF%AD%E5%8F%A5%E5%BA%8F%E5%88%97%E4%BB%A5%E5%8F%8A%E5%AD%90%E8%A1%A8%E8%BE%BE%E5%BC%8F/<p>原文链接:<a href="http://www.hokstad.com/writing-a-compiler-in-ruby-bottom-up---step-3.html">http://www.hokstad.com/writing-a-compiler-in-ruby-bottom-up—step-3.html</a></p>
<hr>
<p><strong>我本来是想要早点发表的,可是我这周又不行了 – 虽然整理一篇旧文只需要半个小时。不管怎样,这是第三章,而且我会在末尾大概列一下之后的大纲。由于我会试着把一些小的步骤组合成更有内容的章节(下面就有个这样的例子),因此原来的 30 篇文章已经被我给减到了 20 篇左右(当然,这只是我已经完成了的,后面还有新的呢)。</strong></p>
- [翻译] 用 Ruby 写编译器之二:函数调用,以及 Hello Worldhttps://blog.glacjay.info/post/2011-04-29/%E7%BF%BB%E8%AF%91-%E7%94%A8-ruby-%E5%86%99%E7%BC%96%E8%AF%91%E5%99%A8%E4%B9%8B%E4%BA%8C%E5%87%BD%E6%95%B0%E8%B0%83%E7%94%A8%E4%BB%A5%E5%8F%8A-hello-world/Fri, 29 Apr 2011 00:00:00 +0000https://blog.glacjay.info/post/2011-04-29/%E7%BF%BB%E8%AF%91-%E7%94%A8-ruby-%E5%86%99%E7%BC%96%E8%AF%91%E5%99%A8%E4%B9%8B%E4%BA%8C%E5%87%BD%E6%95%B0%E8%B0%83%E7%94%A8%E4%BB%A5%E5%8F%8A-hello-world/<p>原文地址:<a href="http://www.hokstad.com/writing-a-compiler-in-ruby-bottom-up-step-2.html">http://www.hokstad.com/writing-a-compiler-in-ruby-bottom-up-step-2.html</a></p>
<hr>
<p>我会选择 Ruby 来作为我的实现语言并没有什么特别的理由。在现阶段,语言的选择并不重要;不过,我确实很喜欢 Ruby。</p>
<p>在这之后,我会采取一系列的步骤令所实现的语言向其实现语言靠拢。我的意思是,我想将编译器实现为可以<strong>自举</strong>的,即它应该能够编译自身。</p>
<p>而这也就意味着,要么我的编译器需要至少支持 Ruby 语言的一个子集,要么就需要一个中间的翻译步骤,来将编译器中的实现翻译成它自己可以编译的语言。</p>
- [翻译] 用 Ruby 写编译器之一:一个简单的 main 函数模板https://blog.glacjay.info/post/2011-04-11/%E7%BF%BB%E8%AF%91-%E7%94%A8-ruby-%E5%86%99%E7%BC%96%E8%AF%91%E5%99%A8%E4%B9%8B%E4%B8%80%E4%B8%80%E4%B8%AA%E7%AE%80%E5%8D%95%E7%9A%84-main-%E5%87%BD%E6%95%B0%E6%A8%A1%E6%9D%BF/Mon, 11 Apr 2011 00:00:00 +0000https://blog.glacjay.info/post/2011-04-11/%E7%BF%BB%E8%AF%91-%E7%94%A8-ruby-%E5%86%99%E7%BC%96%E8%AF%91%E5%99%A8%E4%B9%8B%E4%B8%80%E4%B8%80%E4%B8%AA%E7%AE%80%E5%8D%95%E7%9A%84-main-%E5%87%BD%E6%95%B0%E6%A8%A1%E6%9D%BF/<p>原文链接:<a href="http://www.hokstad.com/writing-a-compiler-in-ruby-bottom-up-step-1.html">http://www.hokstad.com/writing-a-compiler-in-ruby-bottom-up-step-1.html</a></p>
<p>[译者抱怨:翻译好麻烦啊。]</p>
<hr>
<p>我已经将这件事情搁置了很长时间了 – 这个系列中最早的文章甚至可以追溯到 2005 年的早期,而那时我还没有开始写这个博客呢。</p>
- [翻译] 用 Ruby 写编译器之零https://blog.glacjay.info/post/2011-04-10/%E7%BF%BB%E8%AF%91-%E7%94%A8-ruby-%E5%86%99%E7%BC%96%E8%AF%91%E5%99%A8%E4%B9%8B%E9%9B%B6/Sun, 10 Apr 2011 00:00:00 +0000https://blog.glacjay.info/post/2011-04-10/%E7%BF%BB%E8%AF%91-%E7%94%A8-ruby-%E5%86%99%E7%BC%96%E8%AF%91%E5%99%A8%E4%B9%8B%E9%9B%B6/<p>这是一个国外的编译器达人写的一系列教程,内容为用 Ruby 语言,以自底向上的方式开发一个 Ruby 语言的编译器。这个教程非常适合于实战派的程序员。该教程的入口见<a href="http://www.hokstad.com/compiler">这里</a>,其代码见<a href="https://github.com/vidarh/writing-a-compiler-in-ruby">这里</a>。</p>
<p>我会试着翻译一下这个教程。由于这个项目之后又有了很大的进展,而教程本身却又已经很久没有更新了,所以之后我可能也会自己总结一下那些最新的开发工作。</p>
- 总结一下学到的 LVS 相关知识( DR 模式)https://blog.glacjay.info/post/2011-03-13/%E6%80%BB%E7%BB%93%E4%B8%80%E4%B8%8B%E5%AD%A6%E5%88%B0%E7%9A%84-lvs-%E7%9B%B8%E5%85%B3%E7%9F%A5%E8%AF%86-dr-%E6%A8%A1%E5%BC%8F/Sun, 13 Mar 2011 00:00:00 +0000https://blog.glacjay.info/post/2011-03-13/%E6%80%BB%E7%BB%93%E4%B8%80%E4%B8%8B%E5%AD%A6%E5%88%B0%E7%9A%84-lvs-%E7%9B%B8%E5%85%B3%E7%9F%A5%E8%AF%86-dr-%E6%A8%A1%E5%BC%8F/<p>不喜欢看长的 Blog 文章,当然更不喜欢写,所以就分开写啦。另,因为 TUN 模式限制更多,实际很可能用不到,所以不一定会写。</p>
<p>所以这次要讲的是 DR 模式的负载均衡啦。 DR 模式,也就是 Direct Route ,其基本原理就是不对包做任何处理,直接转给所分配的真实服务;回包则由真实服务直接发给客户端而不走负载机。因为不像 NAT 模式那样有相似的架构可以参考,所以这次就上图来说明啦(注,该图偷自<a href="http://www.austintek.com/LVS/LVS-HOWTO/HOWTO/LVS-HOWTO.LVS-DR.html">这里</a>)。</p>
- 总结一下学到的 LVS 相关知识( NAT 模式)https://blog.glacjay.info/post/2011-03-12/%E6%80%BB%E7%BB%93%E4%B8%80%E4%B8%8B%E5%AD%A6%E5%88%B0%E7%9A%84-lvs-%E7%9B%B8%E5%85%B3%E7%9F%A5%E8%AF%86-nat-%E6%A8%A1%E5%BC%8F/Sat, 12 Mar 2011 00:00:00 +0000https://blog.glacjay.info/post/2011-03-12/%E6%80%BB%E7%BB%93%E4%B8%80%E4%B8%8B%E5%AD%A6%E5%88%B0%E7%9A%84-lvs-%E7%9B%B8%E5%85%B3%E7%9F%A5%E8%AF%86-nat-%E6%A8%A1%E5%BC%8F/<p>LVS,即 Linux Virtual Server 的简称,是 Linux 下用来实现负载均衡的一个项目。它支持三种负载模式,分别为 NAT 、 DR 以及 TUN 。</p>
<p>注意,我这里讲的都是针对的 2.6 的内核, 2.4 、 2.2 、 2.0 版内核的实现方法和配置方法都各有不一样的地方。还好我不需要维护历史遗留系统(擦汗)。</p>
<p>首先是最简单的 NAT 模式。这种模式跟普通的 NAT 防火墙的原理差不多,只不过它会根据指定的分配策略,为每一个新的客户端连接选择一个不同的真实服务,而不是像 NAT 防火墙那样只映射到后台的同一个真实服务。</p>
- 发布一个寻找局域网内主机的小工具https://blog.glacjay.info/post/2011-03-05/%E5%8F%91%E5%B8%83%E4%B8%80%E4%B8%AA%E5%AF%BB%E6%89%BE%E5%B1%80%E5%9F%9F%E7%BD%91%E5%86%85%E4%B8%BB%E6%9C%BA%E7%9A%84%E5%B0%8F%E5%B7%A5%E5%85%B7/Sat, 05 Mar 2011 22:00:00 +0000https://blog.glacjay.info/post/2011-03-05/%E5%8F%91%E5%B8%83%E4%B8%80%E4%B8%AA%E5%AF%BB%E6%89%BE%E5%B1%80%E5%9F%9F%E7%BD%91%E5%86%85%E4%B8%BB%E6%9C%BA%E7%9A%84%E5%B0%8F%E5%B7%A5%E5%85%B7/<p>在工作中,经常需要远程登录到机房中的设备上进行调试与开发,走的是工作局域网。由于这些设备的地址也是动态获取的,因此在遇到一些意外事故,如网线松了、网络不稳定之类的,这些地址可能就变了。每当这时,我们就得跑到机房,给设备连上显示器(我们连 KVM 都没有,命苦啊),查看 IP ,然后再跑回去重新连。太麻烦了。</p>
<p>我知道有支持动态地址的 DNS 服务,可是我们没权限操作 DNS 服务器,而且设备也都是不固定的,没必要惊动网络管理员(好吧,我甚至都不知道谁是网络管理员,作为三年的“老”员工,我面壁去了。好吧,其实我就是想写写程序练练手),所以我就写了个小程序,用来查找一台特定设备的 IP 地址。</p>
<p>原理其实很简单啦。客户端(也就是我的笔记本)发个 UDP 广播报文,里面有要找的主机的名字。服务端呢,启动时则指定一个主机名字。当服务端收到一个 UDP 广播报文,并且发现找的就是自己呢,就返回一个 <code>bingo</code> 报文。这样,客户端就知道这个主机的 IP 地址啦。</p>
- Linux 下有关环境变量与换行符的一个小问题https://blog.glacjay.info/post/2011-03-05/linux-%E4%B8%8B%E6%9C%89%E5%85%B3%E7%8E%AF%E5%A2%83%E5%8F%98%E9%87%8F%E4%B8%8E%E6%8D%A2%E8%A1%8C%E7%AC%A6%E7%9A%84%E4%B8%80%E4%B8%AA%E5%B0%8F%E9%97%AE%E9%A2%98/Sat, 05 Mar 2011 00:00:00 +0000https://blog.glacjay.info/post/2011-03-05/linux-%E4%B8%8B%E6%9C%89%E5%85%B3%E7%8E%AF%E5%A2%83%E5%8F%98%E9%87%8F%E4%B8%8E%E6%8D%A2%E8%A1%8C%E7%AC%A6%E7%9A%84%E4%B8%80%E4%B8%AA%E5%B0%8F%E9%97%AE%E9%A2%98/<p>最近在工作中,老是遇到一个莫名其妙的问题。我有一个用来设置一些环境变量的脚本,结果经常发现这个脚本设过的环境变量乱七八糟的,像 PATH 这种,就是之前的值跟后面添加的值重叠在了一起。直到后来才发现,原来是换行符搞的鬼。</p>
<p>这样说还不太清楚,上代码吧。编辑文本文件 <code>test.sh</code> 如下,记得以 DOS 换行符的模式来保存:</p>
- OpenVPN 的并发测试方法https://blog.glacjay.info/post/2011-01-19/openvpn-%E7%9A%84%E5%B9%B6%E5%8F%91%E6%B5%8B%E8%AF%95%E6%96%B9%E6%B3%95/Wed, 19 Jan 2011 00:00:00 +0000https://blog.glacjay.info/post/2011-01-19/openvpn-%E7%9A%84%E5%B9%B6%E5%8F%91%E6%B5%8B%E8%AF%95%E6%96%B9%E6%B3%95/<p>由于 OpenVPN 本身协议的特殊性,用一般的方法不太好测它的并发。看过 LoadRunner ,但也最多只支持标准的 SSL/TLS 协议(当然,我也没细看这个)。于是动手改了其客户端的实现,最终完成任务。</p>
<p>其实阻止我们在一台机器上同时跑很多 OpenVPN 客户端的因素就只有虚拟网卡一个。貌似装十个左右的虚拟网卡驱动之后,机器就不行了。于是解决办法也很简单,把虚拟网卡相关的功能跳过就可以了。根据<a href="https://blog.glacjay.info/post/2011-01-18/openvpn-%E7%9A%84%E5%88%9D%E5%A7%8B%E5%8C%96%E8%BF%87%E7%A8%8B%E5%88%86%E6%9E%90/">上篇</a>的说明,只要在 <code>incoming_push_message()</code> 函数中,把对 <code>do_up()</code> 的调用直接换成 <code>initialization_sequence_completed()</code> 就 OK 了。</p>
- OpenVPN 的初始化过程分析https://blog.glacjay.info/post/2011-01-18/openvpn-%E7%9A%84%E5%88%9D%E5%A7%8B%E5%8C%96%E8%BF%87%E7%A8%8B%E5%88%86%E6%9E%90/Tue, 18 Jan 2011 00:00:00 +0000https://blog.glacjay.info/post/2011-01-18/openvpn-%E7%9A%84%E5%88%9D%E5%A7%8B%E5%8C%96%E8%BF%87%E7%A8%8B%E5%88%86%E6%9E%90/<p>题外话:Eclipse CDT 很给力,至少在我用起来,比 gVim + Cscope 或者 SourceInsight 要来得给力,推荐一下。</p>
<p>更准确的来说,是 OpenVPN 的客户端与服务端之间,从协商密钥、到推送配置,以及最后的网卡与路由配置生效,开始进行 IP 报文的传递,这整个的过程。</p>
<p>完了。嗯,整个过程就像上面说的,这几个步骤而已。</p>
<p>不过重点当然还是代码啦。以前一直以为 OpenVPN 的点对点模式下,两端会进行一个决定谁是客户端,谁是服务端的协商过程,一直都想知道是怎么做的。后来才知道,原来通过配置信息,就已经决定好这个了。当然,我下面说的是客户端-服务器模式。</p>
- OpenVPN 的握手协议分析https://blog.glacjay.info/post/2010-11-22/openvpn-%E7%9A%84%E6%8F%A1%E6%89%8B%E5%8D%8F%E8%AE%AE%E5%88%86%E6%9E%90/Mon, 22 Nov 2010 00:00:00 +0000https://blog.glacjay.info/post/2010-11-22/openvpn-%E7%9A%84%E6%8F%A1%E6%89%8B%E5%8D%8F%E8%AE%AE%E5%88%86%E6%9E%90/<p>又是好久没来这儿了啊。</p>
<p>最近因为工作需要(其实也没需要那么多),一直在断断续续地看 OpenVPN 的代码,终于大概搞清楚了它的握手是怎么个流程了。简单来说的话其实非常的简单,首先在 <code>reliable</code> 模块中实现了一个可靠的 UDP 报文协议,就是加上超时重传和确认报文的功能;然后用该协议交换一个 Hard Reset 命令,开始握手;最后建立 SSL 对象,并且通过内存 <code>BIO</code> 在可靠 UDP 协议的基础上转发 OpenSSL 的握手协议报文,通过这个 SSL 连接交换 OpenVPN 自己的密钥。接下来就是用这些密钥,该干嘛干嘛了。</p>
- 用 Python 操作虚拟网卡https://blog.glacjay.info/post/2010-09-18/%E7%94%A8-python-%E6%93%8D%E4%BD%9C%E8%99%9A%E6%8B%9F%E7%BD%91%E5%8D%A1/Sat, 18 Sep 2010 00:00:00 +0000https://blog.glacjay.info/post/2010-09-18/%E7%94%A8-python-%E6%93%8D%E4%BD%9C%E8%99%9A%E6%8B%9F%E7%BD%91%E5%8D%A1/<p>在我的 <a href="https://blog.glacjay.info/post/2009-12-19/%E5%88%A9%E7%94%A8-xmpp-%E5%8D%8F%E8%AE%AE%E5%AE%9E%E7%8E%B0-vpn/">XTunnel</a> 项目中,已经用 Python 作过这种相对底层的工作了(这说明 Python 果然还是非常强大的,上下层通吃啊),不过那边目前还是只实现了 Linux 的版本。后来我又陆陆续续地把 Windows 以及 Mac 下的操作方法给搞通了,今天就来总结一下。</p>
<p>在 Linux 内核中,特别是在现在的发行版中,应该都已经有了 <code>TUN/TAP</code> 虚拟网卡的驱动程序,看一下有没有 <code>/dev/net/tun</code> 这个文件就可以知道了。如果没有,就执行一下 <code>sudo modprobe tun</code> 这个命令吧。如果还是没有,那就 Google 之吧。下面上代码:</p>
- 通过 ODBC 接口访问 Oracle 数据库 -- Linux 篇https://blog.glacjay.info/post/2010-03-03/%E9%80%9A%E8%BF%87-odbc-%E6%8E%A5%E5%8F%A3%E8%AE%BF%E9%97%AE-oracle-%E6%95%B0%E6%8D%AE%E5%BA%93-linux-%E7%AF%87/Wed, 03 Mar 2010 00:00:00 +0000https://blog.glacjay.info/post/2010-03-03/%E9%80%9A%E8%BF%87-odbc-%E6%8E%A5%E5%8F%A3%E8%AE%BF%E9%97%AE-oracle-%E6%95%B0%E6%8D%AE%E5%BA%93-linux-%E7%AF%87/<p>首先,你要安装好 UnixODBC 软件包,这个就不多说了。</p>
<p>然后,安装 Oracle 官方客户端,因为我的使用环境为 Fedora 12 ,所以我下载安装的是 <code>oracle-xe-client-10.2.0.1-1.0.i386.rpm</code> 。</p>
<p>装好之后,要设置一些环境变量,我是用的一个 Shell 脚本来完成这项工作的,你可以把它放在 <code>/etc/profile.d/</code> 目录下并加上可执行权限来让其在系统启动时自动执行,也可以直接运行这个脚本来使其立即生效。脚本如下:</p>
- Oracle 建库 SQL 脚本https://blog.glacjay.info/post/2010-03-02/oracle-%E5%BB%BA%E5%BA%93-sql-%E8%84%9A%E6%9C%AC/Tue, 02 Mar 2010 00:00:00 +0000https://blog.glacjay.info/post/2010-03-02/oracle-%E5%BB%BA%E5%BA%93-sql-%E8%84%9A%E6%9C%AC/1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 -- 首先是删除该数据库中该用户名下的所有表、序列与触发器, -- 其中触发器是通过表格级联删除的。 declare cursor usertables is select * from user_tables where table_name not like 'BIN$%'; cursor usersequences is select * from user_sequences; begin for next_row in usertables loop execute immediate 'drop table ' || next_row.
- 利用 XMPP 协议实现 VPNhttps://blog.glacjay.info/post/2009-12-19/%E5%88%A9%E7%94%A8-xmpp-%E5%8D%8F%E8%AE%AE%E5%AE%9E%E7%8E%B0-vpn/Sat, 19 Dec 2009 00:00:00 +0000https://blog.glacjay.info/post/2009-12-19/%E5%88%A9%E7%94%A8-xmpp-%E5%8D%8F%E8%AE%AE%E5%AE%9E%E7%8E%B0-vpn/<p>这主意是我<a href="http://chenyufei.info">一同学</a>想到的(至少是他告诉我的),基于一种实际的需要。假设你有两台内网机,都没有公网地址,你想从一台机器访问另一台机器的服务,这时要怎么办呢?当然很可能是我无知了,就我所知,网上倒是有一些提供这类服务的网站,但都是基于 Windows 的远程桌面的,至于 Linux ,我没找过。</p>
<p>于是那家伙联想到了 IM Bot 这种东西。现在网上有各种各样的 IM Bot ,可以通过与之聊天执行各种各样的自动化任务,那为什么不能让它把发过去的命令交给另一台机器的 Shell 执行,并把结果返回呢?这不就实现了一个简单的 Telnet 了吗?这就是最初的想法了(我没去找现成实现,因为我也该练练手了)。而我刚好才折腾过 OpenVPN ,于是就有了标题所说的这个最终想法。这样的话,就能一下子从只支持一种应用协议到支持几乎所有的应用协议了,而且实现的工作量也同时减到了最低。真是好主意啊,自我夸奖一下 :-)</p>
- 让 Vim 在保存时自动调用外部命令进行格式化https://blog.glacjay.info/post/2009-12-13/%E8%AE%A9-vim-%E5%9C%A8%E4%BF%9D%E5%AD%98%E6%97%B6%E8%87%AA%E5%8A%A8%E8%B0%83%E7%94%A8%E5%A4%96%E9%83%A8%E5%91%BD%E4%BB%A4%E8%BF%9B%E8%A1%8C%E6%A0%BC%E5%BC%8F%E5%8C%96/Sun, 13 Dec 2009 00:00:00 +0000https://blog.glacjay.info/post/2009-12-13/%E8%AE%A9-vim-%E5%9C%A8%E4%BF%9D%E5%AD%98%E6%97%B6%E8%87%AA%E5%8A%A8%E8%B0%83%E7%94%A8%E5%A4%96%E9%83%A8%E5%91%BD%E4%BB%A4%E8%BF%9B%E8%A1%8C%E6%A0%BC%E5%BC%8F%E5%8C%96/<p>肯定有许多人遇到过这个问题,也肯定有许多现成的解决方案被发现,可是我没找到(或者说没耐心找)。无所谓,自己找到的话,得到的就不仅仅是最终结果了。</p>
<p>闲话少说。其实以前也干过类似的事情,就是在保存的时候自动去掉所有的行末空白;不过这个操作使用 Vim 本身的功能就能实现,不需要借助于外部程序,所以只要简单地设一个 <code>BufWrite</code> 时的自动命令就行了。但当需要借助外部程序的时候,在 <code>BufWrite</code> 或者 <code>BufWritePre</code> 或者 <code>FileWritePre</code> 时执行的自动命令就不行了,老是提示说什么文件本身已更改,是否确定写入。我在这上面反覆试了好多次,才发现是自己没有搞清楚底下到底发生了什么。要让外部程序对文件内容进行格式化(或者其他什么操作。我想调的是 gofmt,顺带一提),首先当然得要那个外部程序能看到你做过的,还没有保存的更改,所以说应该是先写入再操作的,即在 <code>BufWritePost</code> 的时候执行自动命令。而我一开始就把基本步骤给搞反了。</p>
- 使用 Visual Studio 2008 为 Windows CE 开发编译 OpenSSLhttps://blog.glacjay.info/post/2009-12-05/%E4%BD%BF%E7%94%A8-visual-studio-2008-%E4%B8%BA-windows-ce-%E5%BC%80%E5%8F%91%E7%BC%96%E8%AF%91-openssl/Sat, 05 Dec 2009 00:00:00 +0000https://blog.glacjay.info/post/2009-12-05/%E4%BD%BF%E7%94%A8-visual-studio-2008-%E4%B8%BA-windows-ce-%E5%BC%80%E5%8F%91%E7%BC%96%E8%AF%91-openssl/<p>我的编译环境是 Visual Studio Team System 2008 版本 9.0.21022.8 RTM , Windows Mobile 5.0 SDK R2 ( VS2008 自带的版本)。当然, Perl 也是需要的,我装的是 ActivePerl 。我要编译的 OpenSSL 版本是 0.9.8e 。</p>
<h2 id="vs2008-的安装">VS2008 的安装</h2>
<p>那个 Web Developer Tools (好像叫这个)的安装会失败,又不能不装,根据网上的说明,要把它的目录单独从光盘上解压出来安装,且安装的时候要挂 Office 的安装光盘(我的 Office 版本是 2007 )。这个装好了之后,再从光盘上安装 VS2008 就没有问题了。</p>
- 在 Haskell 中实现 Generic zip 函数https://blog.glacjay.info/post/2009-07-14/%E5%9C%A8-haskell-%E4%B8%AD%E5%AE%9E%E7%8E%B0-generic-zip-%E5%87%BD%E6%95%B0/Tue, 14 Jul 2009 00:00:00 +0000https://blog.glacjay.info/post/2009-07-14/%E5%9C%A8-haskell-%E4%B8%AD%E5%AE%9E%E7%8E%B0-generic-zip-%E5%87%BD%E6%95%B0/<p>其实嗫,这个问题已经有标准和其他的解决方案了。标准解决方案参见 <code>Control.Applicative</code> 中的 <code>ZipList</code> ,不过这东东用起来蛮麻烦的说;其他解决方案见 bff 库的 <code>Data.Zippable</code> 模块,嗯,我还没搞明白这玩意怎么用,不过总感觉杀鸡用牛刀了有点(Template Haskell ,以及其他依赖)。</p>
<p>所以,如果你只是跟我一样,看 <code>Data.List</code> 中的那一砣 <code>zipn</code> 不顺眼的话(其实也只是看着不顺哈,用着还是蛮顺的,反正实现不用我写),一个更简单的方案在此:</p>
- Haskell 中的可变长参数列表https://blog.glacjay.info/post/2009-05-06/haskell-%E4%B8%AD%E7%9A%84%E5%8F%AF%E5%8F%98%E9%95%BF%E5%8F%82%E6%95%B0%E5%88%97%E8%A1%A8/Wed, 06 May 2009 00:00:00 +0000https://blog.glacjay.info/post/2009-05-06/haskell-%E4%B8%AD%E7%9A%84%E5%8F%AF%E5%8F%98%E9%95%BF%E5%8F%82%E6%95%B0%E5%88%97%E8%A1%A8/<p>说实话,我之前有就这个题目很有激情地写了很长很罗嗦的一篇草稿的,哦,确切来说是大半篇,直到被打断,激情不再,这篇草稿也就此躺了两个多月。好吧,其实是我还不是八卦那块料,就不卖弄了,直接总结。</p>
<p>要在 Haskell 中实现可变长参数列表,就是利用其 Typeclass 系统,对函数进行最终结果类型和中间函数类型之间的重载,然后利用 Haskell 的类型推导机制为我们自动调用合适的重载版本。嗯,就这么简单。下面是一个最简单的例子:</p>
- 有关 C/C++ 中的 do { ... } while (0) 惯用法https://blog.glacjay.info/post/2009-04-08/%E6%9C%89%E5%85%B3-c/c-%E4%B8%AD%E7%9A%84-do-...-while-0-%E6%83%AF%E7%94%A8%E6%B3%95/Wed, 08 Apr 2009 00:00:00 +0000https://blog.glacjay.info/post/2009-04-08/%E6%9C%89%E5%85%B3-c/c-%E4%B8%AD%E7%9A%84-do-...-while-0-%E6%83%AF%E7%94%A8%E6%B3%95/<p>C/C++ 中的宏是个让人又爱又恨的家伙(感觉这句话好俗啊),在带给我们很强大的 Power 的同时,却也需要我们绝对的细心,而这也是在宏定义中诸多惯用法的由来。</p>
<p>当我们要把一组语句定义成一个宏,并希望像用一条语句那样来使用它的时候,我们就可以这样做:</p>
- MiniJava 语法中的 non-LALR(1) 的部分及用 Bison 的解决方案https://blog.glacjay.info/post/2009-03-22/minijava-%E8%AF%AD%E6%B3%95%E4%B8%AD%E7%9A%84-non-lalr1-%E7%9A%84%E9%83%A8%E5%88%86%E5%8F%8A%E7%94%A8-bison-%E7%9A%84%E8%A7%A3%E5%86%B3%E6%96%B9%E6%A1%88/Sun, 22 Mar 2009 22:00:00 +0000https://blog.glacjay.info/post/2009-03-22/minijava-%E8%AF%AD%E6%B3%95%E4%B8%AD%E7%9A%84-non-lalr1-%E7%9A%84%E9%83%A8%E5%88%86%E5%8F%8A%E7%94%A8-bison-%E7%9A%84%E8%A7%A3%E5%86%B3%E6%96%B9%E6%A1%88/<p>我正在看<a href="http://www.cs.princeton.edu/~appel/modern/java/">虎书</a>,在这本书中所给出的那个 <a href="http://www.cambridge.org/us/features/052182060X/">MiniJava</a> 语言的语法并不是 LALR(1) 语法,因此在某些情况下,所生成的语法分析器会对正确的输入给出语法解析错误。不过 Bison 提供了一个简单而又强大的<a href="http://www.gnu.org/software/bison/manual/html_mono/bison.html#Generalized-LR-Parsing">解决方案</a>,可以轻易的解决掉这个问题。</p>
- C++ 中的纯虚析构函数与抽象类https://blog.glacjay.info/post/2009-03-22/c-%E4%B8%AD%E7%9A%84%E7%BA%AF%E8%99%9A%E6%9E%90%E6%9E%84%E5%87%BD%E6%95%B0%E4%B8%8E%E6%8A%BD%E8%B1%A1%E7%B1%BB/Sun, 22 Mar 2009 20:00:00 +0000https://blog.glacjay.info/post/2009-03-22/c-%E4%B8%AD%E7%9A%84%E7%BA%AF%E8%99%9A%E6%9E%90%E6%9E%84%E5%87%BD%E6%95%B0%E4%B8%8E%E6%8A%BD%E8%B1%A1%E7%B1%BB/<p>我以前只知道,在 C++ 中,如果要表示一个类是抽象基类,只要为它定义一个纯虚析构函数就可以了,没想到今天用到的时候才发现,连接的时候通不过,说没有找到那个函数的定义。到网上一搜才知道,原来纯虚函数也是可以有定义的啊。在实现文件中加上它的空定义之后,一切就 OK 了。</p>
<p>不过,因为我那个基类里面已经有了一个纯虚函数,所以貌似没必要把析构函数也定义成纯虚的。</p>
<p>PS. 在 C++ 里面要实现 AST 还真是一件麻烦的体力劳动,要写那么多类,每个类还得写那么一砣的样板代码。幸好不是那种长期运行的服务器程序,不需要太考虑 memory leak 的问题,就不用写析构函数和 <code>delete</code> 了(实际上是懒得写),不然样板代码还要更大砣。不知道有什么更好的方法没。</p>
- 对 Bison 手册中的 C++ 的例子的总结https://blog.glacjay.info/post/2009-03-19/%E5%AF%B9-bison-%E6%89%8B%E5%86%8C%E4%B8%AD%E7%9A%84-c-%E7%9A%84%E4%BE%8B%E5%AD%90%E7%9A%84%E6%80%BB%E7%BB%93/Thu, 19 Mar 2009 00:00:00 +0000https://blog.glacjay.info/post/2009-03-19/%E5%AF%B9-bison-%E6%89%8B%E5%86%8C%E4%B8%AD%E7%9A%84-c-%E7%9A%84%E4%BE%8B%E5%AD%90%E7%9A%84%E6%80%BB%E7%BB%93/<p>注意,我用的软件版本为:Bison - 2.4.1,Flex - 2.5.35 。至于老的版本会怎样我就不深究了。工具不是重点。</p>
<hr>
<pre><code class="language-bison" data-lang="bison">%skeleton "lalr1.cc"
</code></pre><p>可以用</p>
<pre><code class="language-bison" data-lang="bison">%language "c++"
</code></pre><p>来代替了,其中参数 “c++” 不区分大小写。</p>
- Bison 中的 Prologue 的格式变迁https://blog.glacjay.info/post/2009-03-18/bison-%E4%B8%AD%E7%9A%84-prologue-%E7%9A%84%E6%A0%BC%E5%BC%8F%E5%8F%98%E8%BF%81/Wed, 18 Mar 2009 00:00:00 +0000https://blog.glacjay.info/post/2009-03-18/bison-%E4%B8%AD%E7%9A%84-prologue-%E7%9A%84%E6%A0%BC%E5%BC%8F%E5%8F%98%E8%BF%81/<p>今天在用 Bison 手册中的 C++ 例子作为一个编译器前端实现的起点时发现,这个官方示例居然编译通不过,具体错误为在 Bison 生成的头文件中,没有 Driver 类的声明。按照 POSIX Yacc 标准,位于 <code>%union</code> 块之前的 Prologue 区中的代码,应该会被拷到头文件中的啊,于是 google 半天,在某个地方的 Bison ChangeLog 中找到了线索。</p>
<p>原来,POSIX Yacc 确实应该符合上述行为,可是 Bison 这家伙为了统一性,从 2.3a 版开始,就把所有 Prologue 中的代码,不管是 %union 前的还是之后的,统统只拷到实现文件中而不管头文件了。而为了对应不同的需求,又新增了一套 Prologue 语法,就是 <code>%before-header</code> 等四个新的 directive。好吧,这样也不错,以显式的统一格式的声明代替了可能会让人抓狂的隐规则。遂试之,结果告诉我说语法错误。接着往上看 ChangeLog 才发现,到了 2.3b 就又改了,把 <code>%before-header</code> 改成了 <code>%code</code> 之类的。这回终于没问题了。</p>
<p>我说,这也太不厚道了吧,这种兼容性改动,我在它的文档里面扒了半天都没看到半个字,而且还是出现在流行度这么高的软件中。于是深刻体会到「错文档不如无文档」的道理啊。由此看来,要做好软件还是需要有相当的责任感的啊。</p>
- Hello Worldhttps://blog.glacjay.info/post/2009-01-01/hello-world/Thu, 01 Jan 2009 00:00:00 +0000https://blog.glacjay.info/post/2009-01-01/hello-world/<p>如题 :-)</p>