可可熊的窝

Category Archives: 编程相关

GAE上使用PyFetion做一个应用

IN:Python, 编程相关   Tags: , ,    Comments:25

GAE上有一个cron jobs的功能,类似于Linux下的crontab,可以实现在指定规则的时间里去运行程序。利用这个功能和飞信的短信功能就完成一些简单的小应用,比如天气预报,服务器监控,股票大盘实时行情提醒等等。

拿服务器监控来说,我们先注册一个GAE账户,然后创建一个Application,下载一份GAE 的SDK,接下来就写代码了。
(以上过程请自行google之)

monitor.py:

#!/usr/bin/env python
# -*- coding: utf-8 -*-
#MIT License
#By : cocobear.cn@gmail.com
#

from google.appengine.api import urlfetch
from PyFetion import *

def get():
    print('<html><body>')
    url = 'http://61.236.244.162'
    result = urlfetch.fetch(url)
    if result.status_code == 200:
        print('OK')
    else:
        fetion = PyFetion('136xxxx','123456','HTTP')
        i = 0
        while True:
            try:
                fetion.login(FetionOnline)
                fetion.send_sms('服务器掉了!')
                fetion.logout()
            except:
                if i > 5:
                    break
                continue
    print('</body></html>')

if __name__ == '__main__':
    get()

很简单的代码,使用GAE的函数urlfetch.fetch来访问这个地址,如果失败调用PyFetion来发短信给自己做通知。

app.yaml:

application: pythoning
version: 1
runtime: python
api_version: 1

handlers:
- url: /console/.*
  script: $PYTHON_LIB/google/appengine/ext/admin
  login: admin

- url: /monitor
  script: monitor.py

- url: /
  static_files: index.html
  upload: index.html

这里指定url映射的规则,访问pythoning.appspot.com/monitor就会执行monitor.py脚本。application需要填写你申请GAE应用时的名称,也就是这个二级域名pythoning,version:当前代码的版本。

index.html:

首页你可以做别的事,比如放个人主页,然后把自己域名指过来。

cron.yaml:

cron:
- description: watch http server
  url: /monitor
  schedule: every 1 minutes
  timezone: Asia/Shanghai

关键的一个文件,对monitor这个url进行定时执行,这里是每分钟执行一次; 如果你是写天气预报,就可以写为 7:00 every day,每天早上7点发一次天气预报。

写完这些以后,运行命令:
ls demos/test
app.yaml cron.yaml index.html monitor.py PyFetion.py
python appcfg.py update demos/test
把你的代码提交到GAE服务器上,你可以在GAE的后台Cron Jobs看到:

/monitor
watch http server every 1 minutes (Asia/Shanghai)
2009/12/15 14:06:50 on time Success

在GAE上使用r49版本的PyFetion,请注释掉from select import select,如果只是像上面做提醒的话最后去掉下面的代码(824行):

self.get_personal_info()
if not self.get_contactlist():
    d_print("get contactlist error")
    return False
self.get("compactlist",self.__uri,self.contactlist.keys())
response = self.send()
code = self.get_code(response)
if code != 200:
    return False
#self.get("PGGetGroupList",self.__uri)
#response = self.send()

self.get_offline_msg()

这里是获得了好友列表,然后给这些好友发一个上线的通知,如果你不想每次提醒的时飞信上的好友都看到你上线,那么就去掉这些,也会加快发送短信的速度。更进一步的优化,你可以去掉TCP通信的相关代码。

ok, 发挥你的想象力,play with GAE and PyFetion

12-15
2009

手动生成X509证书

IN:C, 编程相关   Tags:    Comments:5

X509证书的详细描述在rfc2459中。

简单的来说X509证书是这样的:

Certificate ::= SEQUENCE {
tbsCertificate TBSCertificate,
signatureAlgorithm AlgorithmIdentifier,
signatureValue BIT STRING }

TBSCertificate ::= SEQUENCE {
version [0] EXPLICIT Version DEFAULT v1,
serialNumber CertificateSerialNumber,
signature AlgorithmIdentifier,
issuer Name,
validity Validity,
subject Name,
subjectPublicKeyInfo SubjectPublicKeyInfo,
issuerUniqueID [1] IMPLICIT UniqueIdentifier OPTIONAL,
— If present, version shall be v2 or v3
subjectUniqueID [2] IMPLICIT UniqueIdentifier OPTIONAL,
— If present, version shall be v2 or v3
extensions [3] EXPLICIT Extensions OPTIONAL
— If present, version shall be v3
}

X509由三部分组成,分别是TBSCertificate,AlgorithmIdentifier ,signatureValue 。TBSCertificate包含了证书的详细信息,如证书编号,颁发者,发行者,过期日期等;AlgorithmIdentifier 是指证书自身使用数字签名算法标识,TBSCertificate中也有一个AlgorithmIdentifier,这个是证书可以用作的数字签名算法标识;signatureValue是指使用AlgorithmIdentifier 所指定的算法对整个TBSCertificate签名得到的数字签名。

可以使用openssl命令行工具生成X509证书,不过需要用openssl先生成一对RSA密钥对,如果只有公钥需要生产证书,就需要自己通过编程调用openssl函数来生成证书了。openssl自带的例子中有一个生成证书的例子,不过也是先生成一对RSA密钥对。

通过对openssl源代码的分析,可以X509_set_pubkey函数只是用到了RSA结构中的公钥,所以我们可以通过自己创建一个openssl的RSA结构,只设置RSA密钥对中的公钥,来完成证书的生成。

参考代码

该函数入口参数是一个证书的主题名,和128字节的公钥(1024位;RSA中的modulus INTEGER—-n),返回一个证书ID,和DER编码的证书,默认使用的publicExponent INTEGER, — e为65535。

参考:
RFC2459
PKCS#1
openssl

10-19
2009

网页前端编程

IN:Not Language   Tags: ,    Comments:4

IE6竟然不能连接向同一个网页发请求[做个按钮使用ajax请求一个网址 你们在服务器上发现 其实IE6只发了一次 但是ajax返回确是成功的]

IE7对iframe标签的支持竟然有问题–>http://zhengrenchi.blogbus.com/logs/23056446.html

IE6与IE6 div标签的默认值不一样。

JS代码报错的位置竟然不是真正出错的位置!

…….

就这些简单的问题折腾了我好几天。web前端编程太麻烦了,这么痛苦的开发环境,真是受不了。

08-25
2009

Google Map

IN:Python   Tags: ,    Comments:5

Google Map的算法分析见:http://www.codeproject.com/KB/scrapbook/googlemap.aspx

Google Map使用http://mt[0-3].google.cn/mt/v=cn1.11&hl=zh-CN&x=%d&y=%d&z=%d&s=Galile这样的URL来表示一个放大等级中最小的地图分块。
mt0—-mt3是四个Google Map的服务器
v=cn1.11 是当前地图的版本 一直在变化中
x,y,z分别代表当前分块所在位置和放大等级,Z=19为最大的放大等级,目前很多城市都可以查看到该等级下的地图
在某个放大等级z下,整个地球被分成2^z分块
x,y可以根据经纬度来计算;x的计算比较好理解(longitude->经度):
longitude=180+longitude #修正经度值到0-360 因为经度的表示是从-180—>180
longTileSize=360.0/(pow(2,zoom)) #计算每个分块所占的角度数
tilex = longitude/longTileSize #计算当前经度所在的分块位置

y的计算要牵扯到墨卡托投影这个地图算法,比较麻烦没看懂。不过并不影响使用,相应的代码上面已经给出来了,然后就可以用Python下载地图分块,使用PIL库把分块合并。

代码见Google Code

(这个是西安地图):
#GMap2Png(108.80824,34.37075,109.10316,34.15366,16)
参数为你需要确定的图片左上角的经纬度和右下角的经纬度 最后一个是放大的等级
使用的时候需要注意如果你选择的经纬度范围较大,那么放大等级就不能太大,不然要生成一个巨大图片,PIL会报MemoryError的错误。

还有些问题我在CPyUG记录了下来,不过没使用好的解决方案。

08-04
2009

多资源、多线程、断点续传

IN:Python   Tags:    Comments:16

我要做一个支持多资源、多线程、断点续传的小工具,基于Python。Windows下有迅雷、FlashGet、QQ旋风(相当地泛滥),Linux下也有D4X,Axel ,aria2,那为什么还要写这样一个工具呢?

(1) 上面都不是Python写的。
(2) Linux下的下载工具都不能主动获取资源,而现在迅雷和FlashGet之所以快就是因为他们有资源。
(3) Linux下几个工具多线程、断点续传做的不太好。aria2似乎不错,不过我没编译过去,支持那么多协议,觉得有点臃肿。

其实从原理上讲,迅雷不过就是一个HTTP/FTP的多线程断点下载工具,现在做大了就来抢BT、电驴的用户,把这两个协议也加了进去。

前段时间看过axel,它的实现太简单了,只是固定的产生N个线程,然后把文件分成N块交给这些线程去下载。从迅雷的配置文件和下载的日志中可以看出来迅雷对下载文件的分块和线程的使用是有自己独有的方式(它线程下载的数据块有时很大4M,有时很小32K,即使在同一个线程中也是这样),我没办法知道迅雷是怎么做这个工作。所以我只能通过猜测和自己的一些想法来做这个工作。尽可能的保证合理的分块和线程使用。

创建一个下载管理器,包括配置信息,任务列表,一个具有速度值与使用次数的URL列表。

首先得到下载文件的大小(filesize),然后根据配置以及获得的URL数(N)对文件进行分块。
设置一个最小的分块值 MinPiece = 1024*128 (最小分块大于filesize的5%)
设置一个最大的分块值 MaxPiece = 1024*1024*200

if filesize < = MinPiece:
不进行分块。选第一个地址进行下载,如果该地址下载超时则使用其它地址下载。(是否可以考虑使用N个地址同时下载?)

elif:
把文件分为N块,每块大小为Piece。
if Piece < MinPiece
把文件分为N-1块,Until Piece > MinPiece

if Piece > MaxPiece
把文件分为N+1块,Until Piece < MaxPiece

生成任务列表,一个任务包括:URL,filename,range[start,pos,end]
任务列表中对任务进行标记,DONE,RUNNING,PAUSE,STOP(需要这么多吗?)

根据获得的资源数产生N线程的线程池。

逐步向线程池中增加线程:前提是所有线程成功运行,则增加一个线程。
每个URL对应一个线程的上限数(5),总使用线程数固定(35)

线程运行时检查是否有空闲线程,如果有,则把自己的任务分割(分割的办法使用折半方式,同时要保证分块大于MinPiece),放在任务列表中,同时修改自己的任务的分段信息。
加入任务列表时从URL列表中选一个速度较快的URL,且该URL线程数未达到上限。(如何判断是否达到服务器支持连接数上限?如果针对某个URL创建新连接失败则标记该URL为不可再连接)

线程运行时检查缓冲区的大小,当大于write_buffer_size时则写文件(大于文件的10%时也写?),并且写记录文件,更新URL列表中的速度值,做这些操作时要使用锁机制。这个write_buffer_size根据不同的文件对应不同的大小(2M--->16M迅雷使用8-256)。写文件时可以直接seek到需要写入的位置,如果操作系统不支持这种方式,则先用0填充文件。

线程对失效的URL进行标记,对不支持断点续传的URL进行标记。考虑GBK,UTF-8编码。
线程完成时与停止时做写文件操作与上面操作相同。

记录文件中保存任务列表:
URL,filename,range[start,pos,end]
这样续传的时候程序就根据记录文件载入所有的任务,然后开启线程,进行下载。
记录文件使用MD5校验(最后一行存放前面信息的MD5值)。

一个线程如果速度过慢,则释放当前的任务,把它扔回任务列表中,标记该URL很慢,由空闲的线程再次开启这个任务,这时候有可能又由这个线程接管,但是使用的URL不同,因为扔回任务列表的时候会先一个较快的URL。

HTTP请求需要设置一个超时时间。

———————————————————————-
只是把我的一些想法在这里先记录下来,所以比较乱,做的时候可能还会有些变化。至少我目前觉得这种设计方式还是比较智能和高效的,欢迎大家拍砖,如果有好的建议我会记录下来。

06-02
2009

pythunder又写了一遍

IN:Python   Tags: ,    Comments:27

前几天在Python中文件邮件列表里看到讨论使用Python实现迅雷,后来又在Ubuntu论坛看到一个贴子,实现了获取迅雷服务器上的侯选资源(不是开源的)。突然就对这个迅雷协议很感兴趣,在别人分析的基础上用Python写了个小工具,与Ubuntu论坛上那个作用是一样的,获取迅雷服务器上的侯选资源。

迅雷有多个资源服务器,有的资源服务器返回完全一样,有的返回某些一样,这样可以指定多个服务器,获取更多的资源,同时也可以防止某个服务器不能正常响应。

用webpy写了个演示面面:

http://cocobear.info/demo/pythunder/?url=http://3.duote.com/xunleidt.exe

不知道开源了会不会产生麻烦?

———————————解释下标题——————————
前几天拿U盘做产量的时候没把代码备份出来,所以原本已经写好了今天又写了一遍,幸好代码很短:-)

05-04
2009
Page 2 of 22123451020...Last »
loading...