Modest opinions  
by a humble autodidact
公告
  • 昵称:yushih
    园龄:3年11个月
    粉丝:2
    关注:2
日历
<2012年2月>
2930311234
567891011
12131415161718
19202122232425
26272829123
45678910
统计
  • 随笔 - 57
  • 文章 - 1
  • 评论 - 133
  • 引用 - 1

导航

搜索

 
 

常用链接

我的标签

随笔档案

最新评论

阅读排行榜

评论排行榜

推荐排行榜

 

2011年9月23日

我的第一个erlang/otp程序,虽然弱爆了,还是上线了。

功能:记录gtalk签名档

使用方法:在gtalk里面邀请tpol@takuneering.com为好友。以后每次改签名都会被tpol记录。向tpol发送任意信息,tpol会把签名档历史记录发回来。

实现方式:用Erlang和其标准库实现,没有使用第三方库。整个程序由application/supervisor/gen_server构成,用gen_tcp读写socket,用xmerl_sax_parser解析XMPP协议中的xml,用dets储存数据。

 


第二个程序,虽然只有几百行,但SoLoMo都有了。
有一次我们几个同事去昭觉寺玩,有一个同事晚一点来,然后因为大家都不熟悉,所以怎么也聚不到一块,电话不停的打,短信也发了很多,都是这样:
喂,你们在哪里啊?
我们在门口啊,你呢?
我也到门口了,怎么没看见你们呢?
哦,原来不是同一个门。所以我就写了一个程序解决这个问题:http://rendezvous.takuneering.com/
很简单,用手机上这个网址,打开GPS,然后建一个组,然后把组的地址短信发给同伙,同伙上去以后大家就可以在google maps上互相看到了。然后还可以发信息,照片(仅限android,iphone不支持),在地图上做标记让大家看见之类的辅助功能。虽然简单,但是我觉得也可以算SoLoMo唉--一群人(So了吧),有手机GPS在g maps上定位(LoMo有木有)。
写这个程序的另一个目的是体验Erlang。选Erlang是因为本来是用websocket通讯的,写了一大半才发现android不支持websocket(js websocket标准的撰写人是google的啊,android你種么了),所以可耻的改成xhr轮询了。写这个程序让我发现了Erlang的一个重大优点(比起Python),Erlang程序里面大量使用模式匹配,其实和类型检查是一样的,可以第一时间让错误把程序crash掉,比动态类型的语言不容易隐藏bug。

 

posted @ 2011-09-23 11:33 yushih 阅读(52) 评论(0) 编辑

2010年9月17日

我调用super的习惯是这样的:
super(self.__class__, self)...
第一个参数我一般不写类名,因为我觉得这样更DRY,但是在Django中继承某些类的时候不能这样写。因为Django中有的类使用了特殊的metaclass,如果你这样定义了一个类:

class MyClass(django.XXX):
    def fun(self, ...):

那么self.__class__并不是MyClass。所以super(self.__class__, self)得到的结果并不是一般期望的。

 

当Django以多进程的方式部署时,locmem cache是不能用的。 首先每个进程一个cache,无端降低了命中率,增加了内存消耗。其次,如果程序是在数据改变时更新或删除老的cache,那么只有处理引起数据改变的进程的cache能得到处理,其它进程的cache都可能储存错误内容。

 

 

posted @ 2010-09-17 14:27 yushih 阅读(89) 评论(0) 编辑

2010年7月1日

第一点疑问,不是我认为面向对象不好使,但是“面向对象”这个技术实在太有限了,首先它只能用于解决软件开发中众多问题中的有限的一类,或者说它只是软件的众多维度中的一个维度上的。其次即使只着眼于这一个维度,面向对象也不是银弹,只是对于一小类软件,它是比较不坏的选择。在招聘广告中写上“精通面向对象分析与设计”就好象我要招个C程序员,招聘广告里写“精通C语言的for关键字的使用”,或者要招一个足球运动员,要求“擅长用右脚内侧在禁区线附近射球门左上角”一样荒唐可笑。

 

第二点疑问,根据我的观察,一般有“面向对象分析设计”要求的招聘广告都很矛盾。它们一边要求“面向对象”,一边拒绝使用类为对象的语言、函数是对象的语言以及代码为数据(对象)的语言。不明白这又是为什么?

posted @ 2010-07-01 23:40 yushih 阅读(94) 评论(0) 编辑

2010年6月1日

更新:哥现在已经发展出了基于TUN/TAP+脚本语言的更成熟、稳定的技术,所以下面的内容算是废了。

首先声明:本人只是试验成功,还没有进行过严格正确性、性能和稳定性的实验。以下程序可能存在bug。使用者自己注意。


问题:有人在豆瓣Python版提出“在一台PC上模拟多个IP地址向服务器发起socket连接,并在建立连接后发数据包“的需求。具体要求是“可以在 界面上输入想要模拟的IP地址的范围,比如我想模拟100个用户,就输入192.168.4.100——192.168.4.200,然后自动以这些IP 地址向服务器发socket连接和一些数据“,“服务器侧是一个注册系统,以IP和序列号区分不同用户,我要想进行压力测试必须模拟不同的IP地址“。环 境是“测试所有使用的都是私网地址,而且环境比较独立,所以不必考虑NAT和IP冲突问题“。限制:”服务器侧要是能动就好了,就是不能改动“。以下是我 的解决方法。

搭建环境:服务器端环境不限。客户端必须是Linux。服务器和客户直接通过LAN连接。以上只是逻辑要求,可以用虚拟机在一台电脑上实现。客户端ip地 址设置为cip,掩码nm,服务器端ip地址设置为sip(sip&nm == cip&nm),掩码nm,缺省网关cip(注意,是把服务器的缺省网关地址设置为客户ip地址。课后练习:为什么?)。

软件安装:在客户端装nfqueue-bindings(http://software.inl.fr/trac/wiki/nfqueue- bindings)。有大量的依赖需要安装,不过不需要Perl,只要把CMakeLists.txt中“ADD_SUBDIRECTORY(perl) “这一行去掉。另外libnetfilter-queue要自己下载编译安装,至少在我的机器上用rpm安装后nfqueue-bindings不认。

运行ip模拟器:在客户端以root权限运行wansim.py(代码在后面),命令行参数为:
python wansim.py sip cip ip_range
其中sip为上面设置的服务器ip,cip为上面设置的客户端机器ip,ip_range为要模拟的ip范围,例如:
1.1.1.1-254

1.1.1-254.1-254

222-235.1-8.2.3-6 

限制:模拟ip不能进入客户端-服务器所用LAN的子网ip范围,即对任何模拟ip地址fip:fip&nm != sip&nm(课后作业:为什么?)。
ip模拟器开始运行后,所有从客户端发起到服务器端的tcp会话将被ip模拟器从指定ip范围中随机分配一个ip。服务器程序看到的是这个模拟的ip,而不是cip。

运行:运行服务器。在客户机上运行客户端测试软件。以下是我Windows上服务器看到的效果:

 

很明显服务器看到的是模拟出来的客户ip。

 最后,上代码,再次声明,本人不负任何责任。以下代码进入公共域。

wansim.py
import sys
sys.path.append(r'/usr/local/lib/python2.6/site-packages')
import nfqueue
import time
from socket import AF_INET, AF_INET6, inet_ntoa, inet_aton
from dpkt import ip, tcp, hexdump
import re
import sys
import random




svr_ip=sys.argv[1]

my_ip=sys.argv[2]


def parse():
        
for r in sys.argv[3].split('.'):
                
if '-' in r: #xxx-yyy
                        m=re.match(r'(\d+)-(\d+)', r)
                        
yield range(int(m.group(1)), int(m.group(2))+1)
                
else#xxx
                        yield range(int(r), int(r)+1)
fake_ip_range=list(parse())
def get_fake_ip():
        ip = '.'.join(str(random.choice(r)) for r in fake_ip_range)
        
print 'fake ip: ', ip
        
return ip
        
#Track connection by src port. This is very crude. Should watch tcp more closely.
port2ip={}

time0 = None

def cb(i,payload):
        
global time0
        data = payload.get_data()
        pkt = ip.IP(data)
        
if not time0:
                time0=time.time()
        
print time.time()-time0,\
              
"source: %s" % inet_ntoa(pkt.src),\
              
"dest: %s" % inet_ntoa(pkt.dst)
        
if pkt.p == ip.IP_PROTO_TCP:
                
#outgoing to target server
                if inet_ntoa(pkt.dst) == svr_ip:
                        
if pkt.tcp.sport in port2ip:
                                pkt.src = port2ip[pkt.tcp.sport]
                        
else:
                                fip = inet_aton(get_fake_ip())
                                port2ip[pkt.tcp.sport]=fip
                                pkt.src = fip

                
#incoming from target server
                elif inet_ntoa(pkt.src) == svr_ip and \
                     inet_ntoa(pkt.dst) != my_ip:
                        
#a stronger condition is to check if it is one of our fake ip
                        pkt.dst = inet_aton(my_ip)
                        
                pkt.tcp.sum = 0
                pkt.sum = 0
                payload.set_verdict_modified(
                        nfqueue.NF_ACCEPT,str(pkt),len(pkt))

                
return 0
        payload.set_verdict(nfqueue.NF_ACCEPT)

        sys.stdout.flush()
        
return 1

def run(cmd):
        
from commands import getstatusoutput
        (s, o) = getstatusoutput(cmd)
        
print cmd
        
print 'exit code ', s
        
if len(o):
                
print o

cmds = [
        
#intercept outgoing packets
        "iptables -t mangle -A POSTROUTING -p tcp -d %s -j NFQUEUE" % svr_ip,
        
#intercept incoming packets
        "iptables -t mangle -A PREROUTING  -p tcp -s %s -j NFQUEUE" % svr_ip,
        
#"iptables -A INPUT -p tcp -i eth1 -j NFQUEUE "
]

for c in cmds:
        run(c)

= nfqueue.queue()

print "open"
q.open()

print "bind"
q.bind(AF_INET);

print "setting callback"
q.set_callback(cb)

print "creating queue"
q.create_queue(0)

print "trying to run"
try:
        q.try_run()
except KeyboardInterrupt, e:
        
print "interrupted"


print "unbind"
q.unbind(AF_INET)

print "close"
q.close()

for c in cmds:
        run(c.replace('-A''-D'))

 

如果需要更改模拟ip分配的方式,只需修改get_fake_ip这个函数。 

posted @ 2010-06-01 17:06 yushih 阅读(497) 评论(0) 编辑

2010年5月5日

豆瓣Python版有人想要goto。虽说看不出来goto有什么特别吸引力,但是为了实现Python社区对广大人民群众做出的“Python是世界上除Lisp外最牛b的编程语言”的庄严承诺,同时也为了复习一下一段时间没用Python知识,写了一个goto模块。使用如下例:

 1 from goto import *
 2 
 3 @patch
 4 def f2():
 5     goto(10)
 6     print 'should not see this'
 7     label(10)
 8     for i in range(1,99999):
 9         print i
10         if i == 5:
11             goto('out')
12     label('out')
13 
14 f2()

用法是:

1. from goto import *。注意暂时不支持import goto,不是不能实现,是暂时没时间写。

2.对需要使用goto的函数,前面加个@patch

3.用label(x)和goto(x)的形式写label和goto。x可以是数字或字符串。

 goto模块的代码如下:

goto.py
import dis,pdb

#dummy functions serving as target of bytecode patching
def goto(label):
    
pass

def label(label):
    
pass

#
def decode_bytecode(fun):
    
"""Input: a function
       Ouput: a list of pairs (opcode, arguments)
"""
    c 
= fun.func_code.co_code
    n 
= len(c)
    i 
= 0
    
while i < n:
        op 
= c[i]
        i 
+= 1
        arguments 
= ""
        
if ord(op) >= dis.HAVE_ARGUMENT:
            arguments 
= c[i : i+2]
            i 
+= 2
        
yield (op, arguments)

def sample():
    goto(
200)
    
if 1 == 2:
        sample()
    
else:
        
print 'sample'
        
def test_decode(fun):
    
for op,arg in decode_bytecode(fun):
        
if arg=='':
            
print dis.opname[ord(op)]
        
else:
            
print dis.opname[ord(op)] +' '+str(ord(arg[0]))+' '+str(ord(arg[1]))
        
def match_pattern(seq, i, p):
    
"""
    try to match pattern p to seq[i:], return None if match failed
    seq: output of decode_bytecode
    p -> [instr, instr, ...]
    instr -> (opcode, arg, arg)      opcode is a opcode string
    arg -> ''                        I don't give a damn about this arg
    arg -> integer                   match arg with number
    arg -> string                    the arg is key of the returned match dict from which the arg value can be extracted
    arg -> lambda                    lambda is evaluated with the argument, false return means failed match
    
"""
    
#pdb.set_trace()
    m = {}

    
for op, arg1, arg2 in p:
        
if i==len(seq):
            
return None
        
        
if dis.opmap[op] != ord(seq[i][0]):
            
return None

        
if arg1 == '':
            
pass
        
else:
            
if seq[i][1== ''return None
            
            a1 
= ord(seq[i][1][0])
            
if type(arg1) is str:
                m[arg1]
=a1
            
elif type(arg1) is int:
                
if arg1 != a1: return None
            
elif not arg1(a1):
                
return None

        
#don't need arg2 in this program

        i
+=1

        
    
return m
        
def int_to_bytecode_arg(i):
    
return chr(i  % 256+\
           chr(i 
// 256)

def patch(fun):
    NOP 
= chr(dis.opmap['NOP'])
    co 
= fun.func_code
    old 
= list(decode_bytecode(fun))
    new 
= [] #a list of characters
    
    
#mapping from label to bytecode offset
    label_table={}
    
#if a goto(label) is seen but label is not seen
    #record for the number the bytecode offset of the
    #argument for JUMP_ABSOLUTE for later patching
    goto_table={}

    i
=0
    
#pdb.set_trace()
    while i<len(old):
        m
= match_pattern(old, i,
                         [(
'LOAD_GLOBAL','fun_name',''),
                          (
'LOAD_CONST','label',''),
                          (
'CALL_FUNCTION',1,''),
                          (
'POP_TOP','','')])
        
if m:
            stmt 
= co.co_names[m['fun_name']]
            label 
= co.co_consts[m['label']]
            
        
if   m and stmt == 'goto':
            
# we have a goto statement
            if label_table.has_key(label):
                arg 
= int_to_bytecode_arg(label_table[label])
            
else:
                arg 
= '\xff\xff'
                goto_table[label] 
=\
                 goto_table.get(label, [])
+[len(new)+1]
            new 
+= chr(dis.opmap['JUMP_ABSOLUTE'])
            new 
+= arg
            
#todo
            #this is to maintain proper bytecode offset to
            #source code line number mapping. A better way
            #would be fixing the mapping instead of using
            #placeholders
            new += NOP*7
            i 
+= 4
        
elif m and stmt == 'label':
            
# we have a label statement
            label_table[label]=len(new)
            
if goto_table.has_key(label):
                
for offset in goto_table[label]:
                    new[offset: offset
+2]=int_to_bytecode_arg(len(new))
                
del goto_table[label]
            new 
+= NOP*10
            i 
+= 4
        
else:
            
# emit as-is 
            new += old[i][0] #the opcode
            new += old[i][1#its args if it has 
            i += 1

    
if len(goto_table):
        
#todo: output line number
        raise Exception('missing label')

    
import types
    newcode 
= types.CodeType(co.co_argcount,
                       co.co_nlocals,
                       co.co_stacksize,
                       co.co_flags,
                       
''.join(new),
                       co.co_consts,
                       co.co_names,
                       co.co_varnames,
                       co.co_filename,
                       co.co_name,
                       co.co_firstlineno,
                       co.co_lnotab)
    
return types.FunctionType(newcode,fun.func_globals)
    


 

posted @ 2010-05-05 15:03 yushih 阅读(410) 评论(0) 编辑

2010年1月28日

摘要: 本来是应该写在豆瓣网上的,但是鉴于豆瓣网过分的删贴行为,认定豆瓣已经不是受害者而已经充当起了帮凶的角色。从即日起,不再向豆瓣贡献任何有意义的内容,上豆瓣网仅限于:骂娘,灌纯水,捣蛋。言 归正传,我非常不推荐这本书。虽然pragmatic书一贯是很高的质量,但这本书真的很不好。问题就出在pragmatism上--它完全是一本 how-to,只覆盖到了一些常用情况下的操作方法,没有把Subversio...阅读全文
posted @ 2010-01-28 22:05 yushih 阅读(84) 评论(1) 编辑

2010年1月23日

摘要: 好吧,我承认我又标题党了,不该把Python拉出来和C比,我绝无轻视C语言的意思。我想说的只是,在解决某些问题是,比起用C,用Python真是太舒服了。《Beautiful Code》开篇第一章是由大神Brian Kernighan讲解另一位半神半程序员Rob Pike设计的C语言“正则”表达式引擎(“正则“二字打引号的原因下面会说明)。不能不说短短...阅读全文
posted @ 2010-01-23 19:08 yushih 阅读(701) 评论(5) 编辑

2010年1月7日

摘要: 问题:有Python函数一枚,用递归写成。运行时超出Python的递归深度,现欲将其由在堆栈中分配空间改为在堆中分配空间(即用malloc)。解决方法:首先,from heaprecursion import *。然后对目标函数进行改造,假设要改造的递归函数为def func(p1, p2):1.把函数中的递归调用func(exp1,exp2)改成yield RECURSION(exp1,exp2...阅读全文
posted @ 2010-01-07 21:26 yushih 阅读(279) 评论(0) 编辑

2009年6月17日

摘要: STL的binary search是由lower_bound和uppper_bound两个函数实现的。lower_bound的描述为:lower_bound() returns the position of the first element that has a value less than or equal to value. This is the first position wher...阅读全文
posted @ 2009-06-17 19:30 yushih 阅读(233) 评论(0) 编辑

2008年11月9日

摘要: 最近文档标准之争正烈。我完全不问政治(虽然在技术无区分的情况下我情感上偏袒国货),而且对相关技术也没有深入了解,但我还是想指出文档标准中一个可能被忽视的重要方面--对象寻址。现在是互联网时代,所有的东西都要考虑在网络上的使用性,文档更是如此。W3C定义的URI提供了寻址到文档的方法,但这显然是不够的,我们需要寻址到文档的一个部分,因此需要一个扩展URI的标准。HTML有可以命名的anchor,文档...阅读全文
posted @ 2008-11-09 20:43 yushih 阅读(78) 评论(0) 编辑
 
Copyright © yushih Powered by: 博客园 模板提供:沪江博客