Linux下使用zdclient进行神州数码上网认证

Author:zumikua Updated at:2013-09-23 14:11:33 UTC

本来是个很简单的事请……但是因为我是个煞笔的原因搞得很复杂…… 因为个人问题我一开始下的版本是[github](https://github.com/isombyt/zdcclient)版本的,一开始编译就出问题,没有pcap安装包,用apt-get安装提示包已经被废弃,没办法只好自己下源码自己编译,不过还好pcap的依赖没啥大要求,咱好像只安装了个flex什么的就成功编译了,记得make 和 sudo make install之前先./configure一下看看需求有没有满足 然后就是编译zdclient,编译成功后的确能运行,但是总是提示用户名与密码错误,怎么修改runzdclient脚本都没用……然后在windows下试用zdclient是有效的,真是奇怪的问题啊是吧? 然后我就直接下载了原来的工程,然后翻readme的时候看到了这样一句话“安装前先修改runzdclient文件内的账户信息。”然后我就先修改了runzdclient再继续安装,然后就尼!玛!好!了! 心存怀疑的我到/usr/bin下一看,特么runzdclient竟然是直接拷贝进去不是通过软硬链接链过去的!也就是说之前咱用自己编译的程序压根就没该过用户名和密码!卧槽,就这问题还困扰了我老半天,甚至还自己亲自抓包来实验从作者博客上看到的协议过程……简直不能再坑。 嘛,实际上现在还有一个需要解决的问题就是断线了……我先在在linux下基本想用网就得runzdclient -l再runzdclient,和在windows下使用官方客户端勾选了使用私有报文地址是一样效果,看样子这个问题要想修复又是个大工程了……嘛,以后再说吧……

初探mRuby,C程序嵌入以及自定义扩展

Author:zumikua Updated at:2014-03-01 16:04:24 UTC

博客荒废好长一段时间了,总感觉再不写点什么我说不定都提不起劲给VPS续费了……

mRuby已经release了1.0.0版本,虽然无论是文档还是社区建设mRuby都还有很长的一段路要走,但是对我来说尝鲜已经是足够了。

既然你会翻到这里估计我也就不用再费口舌介绍什么是mRuby了,那么下面我们就直接进入正题好了。

编译

Linux

之前在linux上编译过一次,不过说起来linux上编译起来真的有难度么?连configure都不需要直接装上bison、automake和ruby然后在代码根目录直接make就好。

Windows

曾经试过在Windows上编译一个Ruby出来,不过因为种种原因作罢了,这次编译mRuby也算是补回这个遗憾。

  1. 去GNUWIN32下载bison、make以及mingw32
  2. 安装一个版本的ruby
  3. 在环境变量中添加bison、make、gcc(mingw32提供)所在的路径,具体方法自己google
  4. 在mRuby源码的根目录下make
  5. Done

编译好了以后在build/host/bin/下提供了mruby、mirb和mrbc,分别对应ruby、irb以及rbc

mruby和mirb不用多说,mrbc好像是编译rb程序用的,我没用过就不多说了。

嵌入

正如mRuby名字所揭示的那样,她是一门专门用于嵌入(Embedded)的轻量级语言,类似于Lua。既然如此我们就首先来测试一下将Ruby嵌入到C程序中去。

#include<stdio.h>
#include<stdlib.h>
#include<mruby.h>
#include<mruby/compile.h>

int main(){
  char ruby_code[] = "puts 'Hello World'";
  mrb_state \*mrb = mrb_open();
  mrb_load_string(mrb,ruby_code);
  return 0;
}

嗯……好像还真是比Ruby简单不少……顺带一提之前我曾经试着在windows下将Ruby嵌入到C程序中去,可是使用RubyInstaller提供的名字叫1.9.1的lib总是会在运行的时候报段错误……(Ruby版本1.9.3),当然在Linux下没有任何问题就是了。

顺带一提,请自行设置include文件的搜索位置,以及需要链接的lib(libmruby.a,位于build\host\lib下),在此仅提供Code::Blocks自动生成的编译命令

mingw32-gcc.exe -Wall  -g    -IF:\mruby\mruby-1.0.0\include -c F:\mruby\main.c -o obj\Debug\main.o
mingw32-g++.exe -LF:\mruby\mruby-1.0.0\build\host\lib -o bin\Debug\mruby.exe obj\Debug\main.o   -lmingw32 F:\mruby\mruby-1.0.0\build\host\lib\libmruby.a 

好像同时指定了lib的搜索位置以及lib文件的绝对路径,嘛,不要在意

扩充

在C程序里单独嵌入一个Ruby命令没什么意思,我们来为其扩充一些我们自己定义的内容。

#include<stdio.h>
#include<stdlib.h>
#include<mruby.h>
#include<mruby/compile.h>
mrb_value foo_add(mrb_state\* mrb,mrb_value self){
  int a,b;
  mrb_get_args(mrb,"ii",&a,&b);
  return mrb_fixnum_value(a+b);
}
int main(){
  char ruby_code[] = "p Foo.new.add(1,2)";
  mrb_state \*mrb = mrb_open();
  struct RClass\* foo_class;
  foo_class = mrb_define_class(mrb,"Foo",mrb->object_class);
  mrb_define_method(mrb,foo_class,"add",foo_add,MRB_ARGS_REQ(2));
  mrb_load_string(mrb,ruby_code);
  return 0;
}

这样,我们就添加了一个名为Foo的类以及其一个实例方法add

参考代码,我们可以了解一下mrb定义方法的一般方式,foo_add是作为方法的具体实现函数,其返回类型以及参数类型都是固定的。而ruby传给该方法的参数则需要通过mrb_get_args(mrb,args...)获取。其中args表示各个参数的类型。具体参考此表:

string  mruby type     C type                 note

    o:      Object         [mrb_value]
    C:      class/module   [mrb_value]
    S:      String         [mrb_value]
    A:      Array          [mrb_value]
    H:      Hash           [mrb_value]
    s:      String         [char\*,int]            Receive two arguments.
    z:      String         [char\*]                NUL terminated string.
    a:      Array          [mrb_value\*,mrb_int]   Receive two arguments.
    f:      Float          [mrb_float]
    i:      Integer        [mrb_int]
    b:      Boolean        [mrb_bool]
    n:      Symbol         [mrb_sym]
    &:      Block          [mrb_value]
    \*:      rest argument  [mrb_value\*,int]       Receive the rest of the arguments as an array.
    |:      optional                              Next argument of '|' and later are optional.

\*来源于src/class.c内部的注释

需要指出的是,所有的ruby变量都是mrb_value类型, foo_add 函数的self参数指代instance自己。而对于mrb_define_class_method定义的类方法等self指代的是该类(Class类的instance)本身。

至于mrb_define_class以及mrb_define_method及其参数意义就不用我说了吧?稍微懂点英语就可以看懂了。

还有ruby中每个方法必须要有一个返回值,所以即使你没有返回值也要return mrb_nil_value();,而且函数必须返回mrb_value。(我一开始就直接想都没想用了void作为返回类型……)

很明显,这种方法只适合少量的零散的定义,而对于大量的,更加结构化的工程这种方法也有其局限性,而我们又常常会想要在Ruby类中储存一些持久化数据,但这又会牵扯到Ruby的垃圾回收(GC)工作机理,这一切我们会在后面讲解。

下一讲:

《mRuby:mrbgems以及在Ruby对象中储存struct》

Main