• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            socketref,再見!高德

            https://github.com/adoggie

              C++博客 :: 首頁 :: 聯系 :: 聚合  :: 管理
              246 Posts :: 4 Stories :: 312 Comments :: 0 Trackbacks

            常用鏈接

            留言簿(54)

            我參與的團隊

            搜索

            •  

            最新評論

            閱讀排行榜

            評論排行榜

            置頂隨筆 #

                 摘要: 項目地址: http://github.com/adoggie/TCE 從12年的時候開始想做一個rpc的東東,這些年來陸陸續續往里面增加不同的功能、特點。
            tce是一個 全棧的東西,并不是 protocalbuf,或者接近 thrift。 支持語言: csharp,python,java,objc,javascript,actionscript,c++,我想這些夠了。
              閱讀全文
            posted @ 2016-09-18 16:03 放屁阿狗 閱讀(14859) | 評論 (0)編輯 收藏

                 摘要: 有問題的c++通信代碼的識別,希望寫c++的碼農不要犯同樣的錯  閱讀全文
            posted @ 2016-03-24 15:29 放屁阿狗 閱讀(16285) | 評論 (4)編輯 收藏

            近日獲得一份微信營銷系統的代碼,看其功能比較豐富,便開始窺其代碼的實現。為了將整個業務系統跑起來,還真的花了不少時間琢磨,幸好不負我的幾十年功力,終于將運營環境和開發環境搭建成功,并將系統的授權代碼全部剔除(軟件廠商控制使用授權)。
            準備條件: 
            1. 互聯網服務器(必須開啟80,443端口)
            2. 申請域名,且綁定到服務器
            3. 微信公眾號申請,并通過微信認證(300人民幣)
            先上系統部署圖 : 

            幾個部件需要介紹一下: 
            1. xampp :  開發php的套件,包含了apache,php,mysql,用起來很簡單,不過我是部署在linux和mac 上,要留意的是文件目錄訪問權限的問題,mac下 所有的服務進程跑在root用戶下;
            2. phpstrom: 開發php的ide,出自jetbrains(我個人理解是目前開發工具最牛逼的公司)。 管理數據庫推薦 DataGrip 軟件。 
            3. xdebug : 這個東西是php與phpstrom的調試接口 ,apche接收到http請求,轉給php解釋器,php解釋器再phpStorm進行調試互動(建立xdebug的9000端口的tcp連接),開發者可以在phpStorm里面隨意下斷點。 注意: 在php.ini中需配置 ide-key:scott , 我是在nginx的轉發頭里面添加了 XDEBUG_SESSION=scott,令所有經過 nginx 服務器的http請求都被轉到phpStorm中,否則無法實現代碼斷點。 
            4. wxDebuger: 這是微信提供的本地微信頁面調試工具,開發這可以利用winre來調試手機上的頁面,也可以脫離手機,直接調試微信頁面(要調試微信的wxjssdk必須使用wxDebuger)。 
            5. nginx : 在公網服務器部署nginx作為http服務器,接收各種用戶請求,并將其轉發到xampp。 
            6. vpn :  這個是關鍵,為了實現本地開發調試的目的,我在公網服務器上部署了openvpn,并在mac開發機上部署了xampp,phpstorm等,并安裝vpn客戶端 Tunnelblick,其自動撥號到公網服務器,獲得地址10.8.0.6,nginx將http請求轉發到了我本地的開發機器上,這樣我可以很方便的進行遠程和本地調試了。 


            主要的功能描述: 
            1. 手機、瀏覽器、調試器 發起的http請求到達公網服務器,nginx通過vpn轉發到本地開發機,開發者在phpstorm中斷點調試代碼,并將處理結果按原路返回。 
            2. 微信服務器的主要作用是獲取 粉絲信息、oauth認證回調、服務器鑒權等功能 , HTTP(302)是 oauth的靈魂 。 
            3. 這種配置架構很靈活的可以將開發模式切換到部署模式,只需要將xampp部署到公網服務器,并在 nginx的反向代理指到本地xampp服務即可。 



            附錄  nginx.conf 
             server {
                    listen       80;
                    server_name  wx.xxxx.com www.xxxx.com;
                    proxy_set_header X-real-ip $remote_addr;
                    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

                    location / {
                            proxy_pass http://10.8.0.6:8081;
                            proxy_set_header Cookie "$http_cookie;XDEBUG_SESSION=scott";
                            proxy_set_header Host $host;
                            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
                            proxy_set_header X-real-ip $remote_addr;
                   }
                }



            posted @ 2016-03-24 14:55 放屁阿狗 閱讀(16205) | 評論 (1)編輯 收藏

                 摘要: 6.x 版本系統自帶python 2.6,升級2.7的方式網上有很多版本,本人試用下來覺得諸多不便。
            工作項目中越來越多的開發特性必須要求工作在py2.7版本中,例如: django 1.7+已經不支持 py2.6.x了; pyBox2d也不支持。
            這次選擇的最新版本 python 2.7.11   閱讀全文
            posted @ 2016-01-29 14:17 放屁阿狗 閱讀(16686) | 評論 (0)編輯 收藏


            訪問sf,記錄下一下代碼

            (注冊sf的app,登記 callback-url,執行sql查詢)
            #coding:utf-8
            __author__ = 'scott'
            import imp
            imp.load_source('init','../init_script.py')
            import urllib2,urllib,json,sys,os
            import traceback,threading,time,struct,os,os.path,shutil,distutils.dir_util,array,base64,zlib,struct,binascii
            import datetime
            from libs.python.lemon import webapi
            callback = 'http://localhost:8002/oauth'
            client_id = '3MVG9ZL0ppGP5UrC_wQ8U02mOhowPKwjeaaLsWZ3BcYYVqiSsy1rL_D2h6qG.rGPnb_j6IcgLHPdhmvomzDFj'
            client_secret = '9046731979xxxxxxx'

            def accessToken(request,code,state):
                url = 'https://login.salesforce.com/services/oauth2/token'
                data = {
                    'grant_type':'authorization_code',
                    'code':code,
                    'client_id':client_id,
                    'client_secret':client_secret,
                    'redirect_uri':callback
                }
                result = ''
                try:
                    result = urllib2.urlopen(url,urllib.urlencode(data) )
                except:
                    traceback.print_exc()
                result = result.read()
                return json.loads( result )

            def oauth(request):
                cr = webapi.SuccCallReturn()
                code =  webapi.GET(request,'code','')
                state = webapi.GET(request,'state','')
                cr.result=[code,state]
                token = accessToken(request,code,state)
                cr.result.append(token)
                print token
                try:
                    sqlExecute(token['access_token'],token['instance_url'])
                except:
                    traceback.print_exc()
                return cr.httpResponse()

            import cookielib

            # -H "Authorization: OAuth token" -H "X-PrettyPrint:1" "
            def sqlExecute(token,url_host):
                httpHandler = urllib2.HTTPHandler(debuglevel=1)
                httpsHandler = urllib2.HTTPSHandler(debuglevel=1)
                opener = urllib2.build_opener(httpHandler, httpsHandler)
                urllib2.install_opener(opener)
                sf_cmd_query="%s/services/data/v20.0/query/?%s"%(url_host, urllib.urlencode({'q':'select count() from account'}))
                headers = {
                    'Authorization':'OAuth %s'%token,
                    'X-PrettyPrint':1
                }
                httpReq = urllib2.Request( sf_cmd_query,headers=headers )
                r = opener.open(httpReq).read()
                print r
                pass

            url1 = """https://login.salesforce.com/services/oauth2/authorize?response_type=code&client_id=%s&redirect_uri=%s&state=first"""%(client_id,callback)

            def launchBrowserForOAuth():
                import webbrowser
                webbrowser.open(url1)

            if __name__ == '__main__':
                launchBrowserForOAuth()
            posted @ 2015-06-29 20:21 放屁阿狗 閱讀(917) | 評論 (0)編輯 收藏


            python內部數據容器有dict和list兩種 ,工作中最常用的方式是定義一些數據結構(數據即代碼),例如: 

            1 frog={'name':'scott',
            2           'age':2,
            3           'parts':{
            4                     'eye':'green','leg':85
            5                     },
            6           ''friend":['moee','wee'],
            7           "hometown":'affica'
            8          }

            frog對象定義了小動物的某些屬性,訪問frog對象屬性時,通過 dict,list的取值方法進行訪問,例如:  
            print frog['name']
            print frog['friend'][0]  
            有時覺得這種表達方式太原始了,需要改進,最好是以 '.'方式訪問對象屬性,例如:  
            print frog.name
            代碼來開始和結束吧, class _x 
             1 class _x:
             2     """
             3     從簡單數據類型轉換成python對象
             4 
             5     p = _x({'name':'boob','body':{'color':'black'},'toys':[1,2,3,],'age':100})
             6     print p['toys'][1]
             7     print len(p.toys)
             8     print p.body.colors
             9     """
            10     def __init__(self,primitive):
            11         self.data = primitive
            12 
            13     def __getattr__(self, item):
            14         value = self.data.get(item,None)
            15         if type(value) == dict:
            16             value = _x(value)
            17         return value
            18 
            19     def __len__(self):
            20         return len(self.data)
            21 
            22     def __str__(self):
            23         return str(self.data)
            24 
            25     def __getitem__(self, item):
            26         value = None
            27         if type(self.data) in (list,tuple):
            28             value = self.data[item]
            29             if type(value) in (dict,list,tuple):
            30                 value = _x(value)
            31         elif type(self.data) == dict:
            32             value = self.__getattr__(item)
            33         return value







            posted @ 2015-05-26 14:44 放屁阿狗 閱讀(627) | 評論 (0)編輯 收藏

            相關技術:  haproxy_keepalived_nginx_uwsgi_gevent_django 

            之前部署django一直采用 apache + mod_wsgi,用得倒也沒啥問題,看到越來越多的人采用nginx部署,所以也嘗試了一下,結果很讓人欣喜。

            nginx夠小夠簡潔,編譯、配置相當簡單,但要知道她僅僅是個靜態webserver,動態功能需要搭配相應的cgi來實現; 
            uwsgi是個啥東西,看其官方文檔還真寫的相當詳細,功能很豐富,但我的需求可能只會使用其30%的功能;
            uwsgi可以認為是python代碼運行的loader,或者是容器(container),這有點像java的container(resin,tomcat)。看了其配置文檔,很是驚喜,其不僅可以配置為多進程+多線程模式,也可以配置為單進程+多線程模式,并能保持高并發高銷率,非常感興趣。
            一直以來自己總在尋找一種 高效、靈活的django的應用容器。
            apache默認都是多進程模式,http又是無狀態的,不同的請求被分派到不同的進程處理,request處理都是隔離的。多進程帶來的問題是高昂的系統開銷(apache也支持多線程處理)。
            這種隔離又帶來了諸多不便,request之間不能共享狀態、數據和協作,不能很好的完成與外部系統的協同工作(例如request共享同一個服務器的socket連接或者訪問控制某個rs232端口)
            所以很想有種類似java的應用容器這樣的東東。 
            接觸了gevent,其核心是io異步分派,單線程模擬多協程來對應用層多任務的支持,幾近瘋狂io效率得到了我的認可。ps:八過smp系統就應該啟動多個gevent服務,不然其他核心數都浪費了。
            采用gevent+django的模式搭建了自己得app容器,也跑了幾個項目,總體效果還是可以。
            nginx+uwsgi+django 的配合開始應用到新項目中
            posted @ 2015-01-01 00:41 放屁阿狗 閱讀(741) | 評論 (0)編輯 收藏


            上海交通違章查詢網站: http://www.shjtaq.com/Server1/dzjc_new.asp
            驗證碼圖片獲取地址: http://www.shjtaq.com/Server1/validatecode.asp?m=2304.046

            服務器通過頁面請求的session-id來區分之后提交的驗證碼。 第一次請求查詢頁面時,服務器將訪問session(cookie)傳到客戶端,之后的查詢和驗證碼獲取時客戶端攜帶之前的cookie傳送到服務器,服務器端保存著當前 session-id與驗證碼 的對應關系。 

            查詢返回記錄可通過 xpath或者 beautifulsoup進行解析

            程序使用python完成,也是個簡單的小爬蟲,scrapy 之類的沒必要使用了,gevent完成異步通信。

            交通網的驗證碼生成還是比較簡單,做自動識別可找幾個簡單的圖形識別程序即可。
            如若不行,則人工輸入嘍
            posted @ 2014-10-08 00:45 放屁阿狗 閱讀(1339) | 評論 (0)編輯 收藏

                 摘要:   閱讀全文
            posted @ 2014-05-20 11:33 放屁阿狗 閱讀(17165) | 評論 (0)編輯 收藏

            開始抓yixun.com的商品信息,開始很開心,但一下子來了問題。

            http請求回來的商品分類條目用<a href=>, 但這個href不能直接使用,因為頁面加載之后會啟動js程序(一般都是jquery)對頁面element進行配置和處理,例如:設置風格、事件等等。 

            yixun玩了個防頁面過期的小技巧:
               >每個請求page在server都會產生一個有效期變量XY(具體算法不詳),
               >如果獲取商品<a>直接請求,server將返回失敗,因為<a href>并未包含XY
               >page加載完成之后js代碼設置<a>被點擊時觸發事件E,E將XY添加到<a href>內
               >然后可以正確請求了


            易迅防止請求頁面過期,在主頁中設置了一下參數: 
            <script type="text/javascript"> window.yPageId = '17384560'; window.yPageLevel = '2';</script>

            在頁面內容中顯示
            <a ytag="40037" target="_blank">路由器</a>
            注意: 返回的html就是如此

            但如果用戶點擊(左鍵或者右鍵)此 node對象時,js代碼會動態插入一個YTAG的變量 

            未點擊:
            <a ytag="40037" target="_blank">路由器</a>

            點擊:   
            <a ytag="40037" target="_blank">路由器</a>

            變量生成方式在這個js中實現:

            此js 使用了jquery,頁面完成加載之后,將配置頁面元素的onclick行為,如果點擊了頁面元素,將YTAG屬性加入到商品<a href=""/>中去 
            js代碼凌亂可以使用:
            進行格式化觀察

            js代碼:

            G.header.search = {
                init: function() {
                    G.header.search.event();
                    G.header.search.setInputStyle();
                    G.header.search.autoComplete();
                },
            G.header.search.init();
            query: function() {
                    var input = $("#q_show"),
                    v = $.trim(input.val()),
                    c = $("#cate_show").val(),
                    ret = true,
                    href = input.attr("_href");
                    if (v === G.header._Q_SHOW_DEF_TEXT && href) {
                        window.location.href = href;
                        ret = false;
                    } else if (v === "" || v === G.header._Q_SHOW_DEF_TEXT) {
                        if (!|| (c && c == "")) {
                            input.focus();
                            ret = false;
                        }
                    }
                    if ($('#q_show').parents("form").find('input[name="YTAG"]').length === 0) {
                        var ytag = $('#q_show').parents("form").find('input[type="submit"]').attr("ytag");
                        var YTAG = (window.yPageLevel || 0+ '.' + (window.yPageId || 0+ ytag;
                        $('#q_show').parents("form").append($('<input type="hidden" name="YTAG" value="' + YTAG + '" />'));
                    }
                    return ret;
                }

            程序定義了G.header.search對象,并進行初始化init() ,query()是用戶點擊查詢時觸發使用 
            init()內部配置了query函數,用于鼠標點擊時候生成YTAG屬性
            看代碼就很簡單了

            YTAG生成方式就是 window.yPageLevel+'.'+window.yPageId + <a ytag="40037">
            這樣一個商品條目的href就獲得了
            posted @ 2014-05-19 21:30 放屁阿狗 閱讀(1675) | 評論 (0)編輯 收藏

            posted @ 2014-05-15 01:00 放屁阿狗 閱讀(786) | 評論 (0)編輯 收藏

            tkinter工作在主線程,而gevent是單線程工作,如何整合在一起?
            瞅到一段代碼,迅速收藏



             1 import gevent
             2 from gevent import socket
             3 import Tkinter as tk
             4 
             5 class SockLoop(object):
             6     def __init__(self, callback):
             7         self.callback = callback
             8 
             9     def __call__(self, sock, client):
            10         while 1:
            11             mes = sock.recv(256)
            12             ret = self.callback(client, mes)
            13             if ret is not None:
            14                 sock.send(ret)
            15 
            16 def socket_server(port, callback):
            17     ssock = socket.socket(socket.AF_INET, socket.SOCK_STREAM, socket.IPPROTO_TCP)
            18     ssock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
            19     ssock.bind(('', port))
            20     ssock.listen(5)
            21 
            22     while 1:
            23         sock, client = ssock.accept()
            24         gevent.spawn(callback, sock, client)
            25 
            26 class App(object):
            27     def __init__(self, root):
            28         self.greenlet = None
            29         self.root = root
            30         self._build_window(root)
            31         self.root.after(100, self._connect)
            32 
            33     def add_text(self, text):
            34         cleaned_string = text.replace('\r''')
            35         self.text.insert(tk.END, cleaned_string)
            36 
            37     def quit(self):
            38         self.root.quit()
            39 
            40     def _build_window(self, root):
            41         self.frame = tk.Frame(root)
            42         self.text = tk.Text(self.frame)
            43         self.quit_button = tk.Button(self.frame, text="Quit", command=self.quit)
            44         self.text.pack()
            45         self.quit_button.pack()
            46         self.frame.pack()
            47 
            48     def _connect(self):
            49         self.greenlet = gevent.spawn(
            50                 socket_server,
            51                 8080,
            52                 SockLoop(lambda cl, txt: self.add_text("%s: %s" % (cl, txt))))
            53         self.gevent_loop_step()
            54 
            55     def gevent_loop_step(self):
            56         gevent.sleep()
            57         self.root.after_idle(self.gevent_loop_step)
            58 
            59 
            60 if __name__ == '__main__':
            61     root = tk.Tk()
            62     app = App(root)
            63     root.mainloop()
            posted @ 2014-05-04 16:59 放屁阿狗 閱讀(954) | 評論 (0)編輯 收藏

            俺不是果粉,但開發必須mac
            參加的開發者大會,老外沒一個不是mac的,也的確如此,mac是開發神器,雖然貴點,但還是很值,對得起他的身價 。
            這是一種態度,價值觀世界觀的體現
            linux+windows的完美結合,不!! ui遠超windows

            14.5k mac pro 15 retina 8G 內存 250 G ssd ,都配置差了點,但目前夠了,有錢了再買臺高配的,然后imac,還有那個外星桶的工作站


            酷斃!
            posted @ 2014-04-15 00:53 放屁阿狗 閱讀(475) | 評論 (0)編輯 收藏

            寫代碼,寫好代碼其實并不難,但如果要做好文檔,能完整闡述清楚自己的構思、想法和邏輯結構,這比較難,自己也缺少這方面的耐心。
            很多opensource的代碼根本不需要文檔也能一目了然,這是一種定力
            多年前的項目中使用到python和ffmpeg, 網絡上搜索了一下,均不能滿足自己的要求。ffmpeg的python綁定提供的均是文件級的訪問控制,也就是說沒有暴露更多的可控接口來用。
            所以還是一切都自己來做
            ffmpeg采用0.81版本以上,當時發現mov文件在0.71以下無法正常解碼,到0.81則解決了此問題。
            python包裝ffmpeg的方式很多,最好的可能就是swig,但太煩了,最后選擇ctypes來訪問ffmpeg接口。 
            如果直接使用ffmpeg的api接口也不太合適,因為要暴露很多ffmpeg的接口、數據類型、常數定義等。
            所以我是這么處理:   
              1. 編寫一個功能動態庫來包裝ffmpeg,提供基本的業務功能 ,屏蔽ffmpeg細節,這里叫ffmpeg_media_codec.dll
              2. 用ctypes包裝此ffmpeg_media_codec.dll,這里是ffmpeg.py
              3. 業務代碼使用ffmpeg.py提供的接口訪問、解碼多媒體文件 
            代碼: http://sw2us.com/static/projects/py-ffmpeg/

            ffmpeg_media_codec.dll 暴露的c接口 

             1 ffmpeg lib interface list:
             2 ===========================
             4 typedef unsigned char  StreamByte_t;
             6 struct MediaStreamInfo_t{
             7     int codec_type;
             8     int codec_id;
             9     int width;
            10     int height;
            11     int gopsize;
            12     int pixfmt;
            13     int tb_num;
            14     int tb_den;
            15     int bitrate;
            16     int frame_number;
            17     int videostream; //視頻流編號
            18 };
            19 
            20 struct MediaVideoFrame_t{
            21     StreamByte_t *    rgb24;
            22     size_t            size;
            23     int                width;
            24     int                height;
            25     unsigned int    sequence; //控制播放順序
            26     unsigned int    duration; //播放時間
            27 };
            28 
            29 struct MediaPacket_t{
            30      StreamByte_t*    data;
            31      size_t            size;
            32     AVPacket    *    pkt;
            33     int                stream;    //流編號 
            34     int                dts;
            35     int                pts;
            36     size_t            sequence;
            37     size_t            duration;
            39 };
            40 
            41 struct MediaFormatContext_t;
            42 
            43 //解碼器
            44 struct MediaCodecContext_t{
            45     AVCodecContext * codecCtx;    //AVCodecContext*
            46     AVCodec *        codec;    
            47     int                stream; //流編號
            48     AVFrame *        rgbframe24; //
            49     AVFrame*        frame;    //
            50     StreamByte_t*    buffer;
            51     size_t            bufsize;
            52     void *            user;
            53     MediaStreamInfo_t si;
            54 };
            55 
            56 struct MediaFormatContext_t{
            57     AVFormatContext * fc; //AVFormatContext* 
            58     MediaStreamInfo_t video;    //視頻信息
            60 };
            66 #ifdef __cplusplus
            67  extern "C" {  
            68 #endif
            69 
            70 int InitLib();         //初始化解碼庫
            71 void Cleanup();    //
            73 MediaCodecContext_t* InitAvCodec(MediaStreamInfo_t* si);    //根據媒體類型分配解碼器對象
            74 void FreeAvCodec(MediaCodecContext_t* codec);                  //釋放解碼器對象
            76 MediaVideoFrame_t * DecodeVideoFrame(MediaCodecContext_t* ctx,MediaPacket_t* pkt);  //送入媒體包進行解碼,返回視頻幀
            77 void FreeVideoFrame(MediaVideoFrame_t* frame);                  //釋放視頻幀
            79 MediaPacket_t * AllocPacket();                                             //分配一個流媒體包對象(用于網傳)
            80 void FreePacket(MediaPacket_t* pkt);                                    //釋放流媒體包
            82 MediaFormatContext_t* InitAvFormatContext(char * file);          //媒體文件訪問上下文,申請
            83 void FreeAvFormatContext(MediaFormatContext_t* ctx);          //釋放
            84 MediaPacket_t* ReadNextPacket(MediaFormatContext_t* ctx);   //讀媒體文件一個數據包
            85 void ReadReset(MediaFormatContext_t* ctx) ;                //重置媒體訪問讀取位置
            86 int SeekToTime(int timesec) ;                                     //跳躍到指定時間

            ffmpeg.py 包裝:

              1 import ctypes
              2 from ctypes import *

              5 _lib = cdll.LoadLibrary('ffmpeg.dll')
              6 
              7 _int_types = (c_int16, c_int32)
              8 if hasattr(ctypes, 'c_int64'):
              9     # Some builds of ctypes apparently do not have c_int64
             10     # defined; it's a pretty good bet that these builds do not
             11     # have 64-bit pointers.
             12     _int_types += (ctypes.c_int64,)
             13 for t in _int_types:
             14     if sizeof(t) == sizeof(c_size_t):
             15         c_ptrdiff_t = t
             16 
             17 class c_void(Structure):
             18     # c_void_p is a buggy return type, converting to int, so
             19     # POINTER(None) == c_void_p is actually written as
             20     # POINTER(c_void), so it can be treated as a real pointer.
             21     _fields_ = [('dummy', c_int)]

             26 class MediaStreamInfo_t(Structure):
             27     _fields_ = [
             28         ('codec_type', c_int),
             29         ('codec_id', c_int),
             30         ('width', c_int),
             31         ('height', c_int),
             32         ('gopsize', c_int),
             33         ('pixfmt', c_int),
             34         ('tb_num',c_int),
             35         ('tb_den',c_int),
             36         ('bitrate',c_int),
             37         ('frame_number',c_int),
             38         ('videostream',c_int),
             39         ('duration',c_int),
             40         ('extr',POINTER(c_char)), #解碼器 額外hash表數據
             41         ('extrsize',c_int),
             42     ]
             43 
             44 class MediaVideoFrame_t(Structure):
             45     _fields_=[
             46         ('rgb24',POINTER(c_char)),
             47         ('size',c_uint),
             48         ('width',c_int),
             49         ('height',c_int),
             50         ('sequence',c_uint),
             51         ('duration',c_uint)
             52     ]
             53     
             54 class MediaPacket_t(Structure):
             55     _fields_=[
             56         ('data',POINTER(c_char)),
             57         ('size',c_uint),
             58         ('pkt',c_char_p),
             59         ('stream',c_int),
             60         ('dts',c_int),
             61         ('pts',c_int),
             62         ('sequence',c_uint),
             63         ('duration',c_uint)
             64     ]
             65     
             66     
             67 class MediaCodecContext_t(Structure):
             68     _fields_=[
             69         ('codecCtx',c_char_p),
             70         ('codec',c_char_p),
             71         ('stream',c_int),
             72         ('rgbframe24',c_char_p),
             73         ('frame',c_char_p),
             74         ('buffer',c_char_p),
             75         ('bufsize',c_uint),
             76         ('user',c_char_p),
             77         ('si',MediaStreamInfo_t)
             78     ]    
             79     
             80 class MediaFormatContext_t(Structure):
             81     _fields_=[
             82         ('fc',c_char_p),
             83         ('video',MediaStreamInfo_t)
             84     ]
             85     
             86 InitAvCodec = _lib.InitAvCodec
             87 InitAvCodec.restype = POINTER(MediaCodecContext_t)
             88 InitAvCodec.argtypes = [POINTER(MediaStreamInfo_t)]
             89 
             90 
             91 FreeAvCodec = _lib.FreeAvCodec
             92 FreeAvCodec.restype = None
             93 FreeAvCodec.argtypes = [POINTER(MediaCodecContext_t)]
             96 DecodeVideoFrame = _lib.DecodeVideoFrame
             97 DecodeVideoFrame.restype = POINTER(MediaVideoFrame_t)
             98 DecodeVideoFrame.argtypes = [POINTER(MediaCodecContext_t),POINTER(MediaPacket_t)]
            100 FreeVideoFrame = _lib.FreeVideoFrame
            101 FreeVideoFrame.restype = None
            102 FreeVideoFrame.argtypes = [POINTER(MediaVideoFrame_t)]  
            104 AllocPacket = _lib.AllocPacket
            105 AllocPacket.restype = POINTER(MediaPacket_t)
            106 AllocPacket.argtypes = []
            109 FreePacket = _lib.FreePacket
            110 FreePacket.restype = None
            111 FreePacket.argtypes = [POINTER(MediaPacket_t),c_int]
            113 InitAvFormatContext = _lib.InitAvFormatContext
            114 InitAvFormatContext.restype = POINTER(MediaFormatContext_t)
            115 InitAvFormatContext.argtypes = [c_char_p]
            117 FreeAvFormatContext = _lib.FreeAvFormatContext
            118 FreeAvFormatContext.restype = None
            119 FreeAvFormatContext.argtypes = [POINTER(MediaFormatContext_t)]
            122 ReadNextPacket = _lib.ReadNextPacket
            123 ReadNextPacket.restype = POINTER(MediaPacket_t)
            124 ReadNextPacket.argtypes = [POINTER(MediaFormatContext_t)]
            127 ReadReset = _lib.ReadReset
            128 ReadReset.restype = None
            129 ReadReset.argtypes = [POINTER(MediaFormatContext_t)]
            130 
            131 SeekToTime = _lib.SeekToTime
            132 SeekToTime.restype = c_int
            133 SeekToTime.argtypes = [POINTER(MediaFormatContext_t),c_int]
            134 
            135 FlushBuffer = _lib.FlushBuffer
            136 FlushBuffer.restype =None
            137 FlushBuffer.argtypes = [POINTER(MediaCodecContext_t)]
            138 
            139 InitLib = _lib.InitLib
            140 InitLib.restype =None
            141 InitLib.argtypes = []
            142 
            143 Cleanup = _lib.Cleanup
            144 Cleanup.restype =None
            145 Cleanup.argtypes = []

            好了,看看如何使用這些接口 
            視頻文件播放:      http://sw2us.com/static/projects/py-ffmpeg/test_qt.py
            posted @ 2014-04-14 22:35 放屁阿狗 閱讀(5848) | 評論 (2)編輯 收藏

            從事webgis及其應用有些時日,實驗性質的東西一直沒有被大規模應用,一路走來頗多辛苦 
            現將代碼放出,有興趣的朋友可看看,包括地圖數據處理編譯、地圖渲染服務程序、wms程序、tce
            http://114.215.178.29/wms/

            目前從事im,移動互聯網平臺框架,p2p,并行計算方面研究
            posted @ 2014-04-13 14:27 放屁阿狗 閱讀(1426) | 評論 (4)編輯 收藏

            近一周時間都在玩p2p,本來以為實現很簡單,但做起來實屬不易 。 
            Udp穿透Nat會遇到多種Nat類型: 
            1.FULL CORE 
            2. RESTRICT
            3. PORT-RESTRICT
            4. SYMMETRIC 
            1-3三種NAT實現穿透很簡單,問題在于處理第4種類型:對等NAT 
            SYMMETRIC NAT的工作模式區分在于內網通過NAT時分配的外部端口的方式不同,這又有三種情況: 
            1. 端口遞增: 通常新端口號會是前一次分配端口號加1或者加固定值 
            2. 端口在當前NAT最新端口的左右區間: 例如當前NAT外網端口P,那新的分配端口會落在 -N < P < N
            3. 隨機分配SR (這個根據當時NAT的網絡情況參數等作為函數f(x)的因子決定)
            這第三種分配方式,目前無解,只要任意一端存在SR,則無法穿透  
            當然很多技術研究者提出了如何猜測動態端口的方案,例如:統計技術的使用,服務器可對固定NAT進行采樣分析等等。。
            這個很難哦!
            面對SR我直接放棄了,還真不巧,測試了3,4個網絡環境的NAT,居然50%是SR,50%是SYMMETRIC的1,2種類型 。 
            還是老實的服務器中轉把!
            一些p2p資料供參考:  http://114.215.178.29/static/p2p
            posted @ 2014-04-11 00:32 放屁阿狗 閱讀(373) | 評論 (0)編輯 收藏

            應用中經常用pyCrypto 來生成用戶Token等相關信息,夠簡單,所以貼代碼分享
            部分代碼被關閉或者打開,使用者請自行調整,如果了解rsa很簡單理解一下代碼 

              1 GCONFS={
              2     'auth_public_keyfile':'public.rsa',
              3     'auth_private_keyfile':'private.rsa'
              4 }
              5 
              6 
              7 def encrypt_des(key,text):
              8     from Crypto.Cipher import DES
              9     import base64
             10     from Crypto import Random
             11     #iv = Random.get_random_bytes(8)
             12     des = DES.new(key, DES.MODE_ECB)
             13     reminder = len(text)%8
             14     if reminder ==0:  # pad 8 bytes
             15         text+='\x08'*8
             16     else:
             17         text+=chr(8-reminder)* (8-reminder)
             18     #text+=' '*(8-len(text)%8)
             19     return des.encrypt(text)
             20 #return base64.encodestring(des.encrypt(text))
             21 
             22 def decrypt_des(key,text):
             23     from Crypto.Cipher import DES
             24     import base64
             25     #    print key
             26     des = DES.new(key, DES.MODE_ECB)
             27     text = des.decrypt(text)
             28     pad = ord(text[-1])
             29     if pad == '\x08':
             30         return text[:-8]
             31     return text[:-pad]
             32 
             33 
             34 def rsa_generate():
             35     from Crypto.PublicKey import RSA
             36     from Crypto import Random
             37     random_generator = Random.new().read
             38     key = RSA.generate(1024, random_generator)
             39 
             40 
             41     #print key.publickey().encrypt('123213213123213213',20)
             42     public =  key.publickey().exportKey()
             43     #print key.publickey().exportKey()
             44     private = key.exportKey()
             45     return public,private
             46 
             47 def rsa_encrypt(key,text):
             48     '''
             49         傳入私鑰key和待加密明文數據text
             50         自動生成8字節長度隨機密碼P,用P將text進行des加密生成E,
             51         用私鑰key加密P生成P2
             52 
             53         key - private key
             54         text - orignal text
             55         @return:  [P2+E]  RSA加密的des秘鑰 + 加密的密文
             56     '''
             57     import uuid
             58     from Crypto.PublicKey import RSA
             59     deskey = hashlib.md5(uuid.uuid1().hex).hexdigest()[:8]
             60     text = encrypt_des(deskey,text)
             61 
             62     key = RSA.importKey(key)
             63     r = key.encrypt(deskey,32)
             64 
             65     return r[0]+text # 加密的key,和des加密的數據
             66 
             67 def rsa_decrypt(key,text):
             68     from Crypto.PublicKey import RSA
             69     try:
             70         rsa = RSA.importKey(key)
             71         deskey = text[:128]
             72         text = text[128:]
             73         deskey = rsa.decrypt(deskey)
             74         return decrypt_des(deskey,text)
             75     except:
             76         return ''
             77 
             78 class Cipher:
             79     def __init__(self):
             80 #        self.pubkey = pubkey
             81 #        self.privkey = privkey
             82         pass
             83 
             84     def encrypt(self,key,text):
             85         return rsa_encrypt(key,text)
             86 
             87 
             88     def decrypt(self,key,text):
             89         return rsa_decrypt(key,text)
             90 
             91     @staticmethod
             92     def getCipher():
             93         try:
             94             cip = Cipher()
             95             return cip
             96         except:
             97             traceback.print_exc()
             98             return None
             99 
            100 def encryptToken(user):
            101     '''
            102         用戶信息轉換為token
            103     '''
            104     token=''
            105     try:
            106         d = json.dumps(user)
            107 #        f = open(GCONFS['auth_public_keyfile'],'r')
            108 #        pubkey = f.read()
            109 #        f.close()
            110         pubkey = ENCRYPT_PUBKEY
            111         # d = Cipher.getCipher().encrypt(pubkey,d)  #rsa encrpyt
            112         token = base64.encodestring(d).strip()
            113     #print 'token size:',len(token)
            114     except:
            115         print traceback.format_exc()
            116         token = ''
            117 
            118     return token
            119 
            120 def decryptToken(token):
            121     user = None
            122     try:
            123 #        f = open(GCONFS['auth_private_keyfile'],'r')
            124 #        privkey = f.read()
            125 #        f.close()
            126         privkey = ENCRYPT_PRIVKEY
            127         d = base64.decodestring(token)
            128         # d = Cipher.getCipher().decrypt(privkey,d) #rsa decrept
            129         user = json.loads(d)
            130     except:
            131         #print traceback.format_exc()
            132         pass
            133     return user
            posted @ 2014-04-01 10:22 放屁阿狗 閱讀(3361) | 評論 (1)編輯 收藏

            系統中,用戶的消息在移動設備與接入服務器建立的Tcp長連接上傳遞。這些消息包括:文本,復合文本,位置信息,音頻剪輯,圖像等等。
            發送者傳送消息到平臺系統內部并將消息寫入gridfs,待接收者上線時平臺將消息推送至接收者。
            考慮到帶寬利用,接收者得到的消息將不包含二進制數據,例如: 音頻,圖像等等。 這要求接收者對平臺發起一次獲取消息包內指定的音頻和圖像數據的請求。
            移動端向平臺請求二進制數據的情況還包含 【離線文件傳送】場景 。
            二進制數據往往是指那些數據量比較大的對象,這些對象在移動兩端交換時,交互通道將不占用與接入服務器的連接通道,而是通過nginx傳送到平臺內部; 同樣接收者獲取二進制數據也是通過nginx獲取。這種請求是HTTP的。
            這里整理的是如何在平臺部署 【負載均衡的集群的分布式的文件服務】

            nginx :               http服務,提供反向代理和負載均衡服務(集群可用DNS或考慮LVS方案)
            mongodb+gridfs : 用于文件服務提供,其內置gridfs提供了分布式,海量存儲的方案
            gevent+webpy : nginx直接讀取gridfs是不合適的,配置了cgi才能完成特定功能,這里使用webpy,比django更輕更好用。
                                     webpy的作用是接收到上傳和下傳文件的請求,讀寫gridfs文件內容給移動端。
                                      gevent是高效的通信框架,雖然單線程工作,但性能非常的好;
                                     用好gevent關鍵在與外部的io必須全部都是異步的,例如: 數據庫,文件磁盤訪問等等。
                                     mongodb對gevent已經支持,gevent對webpy,django,psycopg2支持也相當的好,所以要提供webservice服務那就考慮用gevent+webpy或django把,性能是杠杠的,比 apache+mod_wsgi要好很多 ,而且gevent是進程內的不同的HTTP REQUEST可以是共享數據的,這一點非常誘惑(apache+mod_wsgi的REQUEST可是隔離的哦!除非您通過redis的PUB/SUB實現兩個REQUEST的通信)
                                   
            關注的問題:
            1.下傳大文件時的處理
               如果直接用nginx當然沒有這個問題 ,但用webpy讀取文件返回HttpResponse時問題來了,總不至于讀取整個文件,然后再return。
                     這種方式在php有flush方法,python只能用yield來做
             2.上傳大文件時的處理
                    當接收到http的文件POST請求時,文件已經全部緩存到web服務器,如果同時幾千個文件上傳在進行,服務器就會被擠爆,這也是很多網站不允許大文件上傳的緣故吧。關于這個問題,我想就需要修改一下webpy關于文件上傳的處理代碼了,將接收到的文件數據以流的形式寫入到gridfs里去作為臨時文件被緩存,等完全接收文件時,才通知到handler代碼,這樣必定高效很多(新的問題又來了,會不會把gridfs搞爆掉! 處理時考慮延時緩存提交gridfs把)。
            BUF_SIZE = 262144
            class download:
                
            def GET(self):
                    file_name 
            = 'file_name'
                    file_path 
            = os.path.join('file_path', file_name)
                    f 
            = None
                    
            try:
                        f 
            = open(file_path, "rb")
                        webpy.header(
            'Content-Type','application/octet-stream')
                        webpy.header(
            'Content-disposition''attachment; filename=%s.dat' % file_name)
                        
            while True:
                            c 
            = f.read(BUF_SIZE)
                            
            if c:
                                
            yield c
                            
            else:
                                
            break
                    
            except Exception, e:
                        
            print e
                        
            yield 'Error'
                    
            finally:
                        
            if f:
                            f.close()



            links:
            http://api.mongodb.org/python
            http://webpy.org/cookbook/storeupload.zh-cn
            http://webpy.org/cookbook/streaming_large_files
            http://gevent.org   下份代碼 demo很值得看哦 gevent 1.0 由libev 替換了libevent

             
            posted @ 2014-03-29 21:27 放屁阿狗 閱讀(1831) | 評論 (0)編輯 收藏

                 摘要: 貼代碼 Code highlighting produced by Actipro CodeHighlighter (freeware)http://www.CodeHighlighter.com/-->   1 #--coding:utf-8--   2    3  ...  閱讀全文
            posted @ 2013-12-07 01:54 放屁阿狗 閱讀(864) | 評論 (0)編輯 收藏

            多樣的文本消息
            -----------------
            struct MimeText_t{
                 int type;
                 string text;
            };
            MimeText_t 可以包含普通的文本、圖像和音頻文件的id 
            圖像和音頻數據發送到服務器,服務器并不直接將數據發送到接收者,而是發送 音頻和圖像的描述uri信息 
            接收者解釋json,顯示text文本,讀取emoticon編號,顯示表情圖片;  image,audio則顯示占位(如果當前wifi可用,則自己自動加載image和audio資源) ,如果非wifi信號則待用戶點擊此占位,然后從服務器請求image和audio資源到本地。
            文本描述: 字體大小,顏色,文本link,表情符號 
            文本用json組織 ,
            {
              set:[
                 text:{text:'this is',bg-color:#ff0000,color:#ffffff,font-name:'arial',font-size:20,bold:true,italic:true},
                 text:{text:'shanghai',color:#ff0000,font-name:'arial',font-size:20,bold:true,italic:true,link:'http://sw2us.com/images/shanghai.png'},
                 image:{id:1001,width:200,height:200,uri:'http://sw2us.com/images/bear.png'},
                 audio:{id:2001,duration:5,uri:'http://sw2us.com/clips/a001.mp3'},
                 location:{lon:121.221,lat,time,speed,direction,text:'立月路2001號浦星公路口'},
                 emoticon:{id:201}
              ],
            }
            屬性名簡化: 
            ---------------------
            -----------------------
            1 - text               [ 1: text , 2: bg-color , 3: color , 4: font-name, 5:font-size, 6:bold, 7:italic ]
            2 - image            [ 1: id , 2:width , 3:height , 4:uri]
            3 - audio             [ 1:id , 2:duration,3:uri]
            4 - location          [ 1:lon, 2:lat, 3:time, 4:speed, 5:direction, 6:text]
            5 - emoticon        [ 1: id ]
            -----------------------
            0 - false
            1 - true 
            posted @ 2013-11-30 00:34 放屁阿狗 閱讀(720) | 評論 (0)編輯 收藏

            狠狠精品干练久久久无码中文字幕| 久久亚洲精品成人av无码网站| 久久久久久久精品成人热色戒| 99久久精品国产麻豆| 欧美亚洲国产精品久久| 久久最近最新中文字幕大全| 99久久99久久精品国产片| 国产偷久久久精品专区| 性做久久久久久久久久久| 欧美精品一区二区精品久久| 日韩人妻无码一区二区三区久久99| 丁香五月综合久久激情| 国内精品久久久人妻中文字幕| 精品久久久久久国产| 伊人久久成人成综合网222| 久久精品国产亚洲Aⅴ香蕉| 青青青伊人色综合久久| 996久久国产精品线观看| 国产V亚洲V天堂无码久久久| 伊人久久成人成综合网222| 亚洲а∨天堂久久精品9966| 久久美女网站免费| 久久se这里只有精品| 久久久久久久国产免费看| 久久久久久久亚洲精品 | 欧美黑人激情性久久| 久久综合视频网站| av色综合久久天堂av色综合在| 久久毛片一区二区| 欧美丰满熟妇BBB久久久| 亚洲精品无码成人片久久| 亚洲欧美伊人久久综合一区二区| 99久久综合国产精品免费| 久久久SS麻豆欧美国产日韩| 日韩久久无码免费毛片软件| 国产成人久久777777| 久久久久亚洲AV无码去区首| 精品无码久久久久久国产| 欧美精品一区二区久久| 国产成人久久精品一区二区三区| 国内精品人妻无码久久久影院导航|