• <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++博客 :: 首頁(yè) :: 聯(lián)系 :: 聚合  :: 管理
              246 Posts :: 4 Stories :: 312 Comments :: 0 Trackbacks

            常用鏈接

            留言簿(54)

            我參與的團(tuán)隊(duì)

            搜索

            •  

            最新評(píng)論

            閱讀排行榜

            評(píng)論排行榜

            置頂隨筆 #

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

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

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

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


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



            附錄  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 放屁阿狗 閱讀(16208) | 評(píng)論 (1)編輯 收藏

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


            訪問sf,記錄下一下代碼

            (注冊(cè)sf的app,登記 callback-url,執(zhí)行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 放屁阿狗 閱讀(918) | 評(píng)論 (0)編輯 收藏


            python內(nèi)部數(shù)據(jù)容器有dict和list兩種 ,工作中最常用的方式是定義一些數(shù)據(jù)結(jié)構(gòu)(數(shù)據(jù)即代碼),例如: 

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

            frog對(duì)象定義了小動(dòng)物的某些屬性,訪問frog對(duì)象屬性時(shí),通過 dict,list的取值方法進(jìn)行訪問,例如:  
            print frog['name']
            print frog['friend'][0]  
            有時(shí)覺得這種表達(dá)方式太原始了,需要改進(jìn),最好是以 '.'方式訪問對(duì)象屬性,例如:  
            print frog.name
            代碼來開始和結(jié)束吧, class _x 
             1 class _x:
             2     """
             3     從簡(jiǎn)單數(shù)據(jù)類型轉(zhuǎn)換成python對(duì)象
             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 放屁阿狗 閱讀(628) | 評(píng)論 (0)編輯 收藏

            相關(guān)技術(shù):  haproxy_keepalived_nginx_uwsgi_gevent_django 

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

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


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

            服務(wù)器通過頁(yè)面請(qǐng)求的session-id來區(qū)分之后提交的驗(yàn)證碼。 第一次請(qǐng)求查詢頁(yè)面時(shí),服務(wù)器將訪問session(cookie)傳到客戶端,之后的查詢和驗(yàn)證碼獲取時(shí)客戶端攜帶之前的cookie傳送到服務(wù)器,服務(wù)器端保存著當(dāng)前 session-id與驗(yàn)證碼 的對(duì)應(yīng)關(guān)系。 

            查詢返回記錄可通過 xpath或者 beautifulsoup進(jìn)行解析

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

            交通網(wǎng)的驗(yàn)證碼生成還是比較簡(jiǎn)單,做自動(dòng)識(shí)別可找?guī)讉€(gè)簡(jiǎn)單的圖形識(shí)別程序即可。
            如若不行,則人工輸入嘍
            posted @ 2014-10-08 00:45 放屁阿狗 閱讀(1340) | 評(píng)論 (0)編輯 收藏

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

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

            http請(qǐng)求回來的商品分類條目用<a href=>, 但這個(gè)href不能直接使用,因?yàn)轫?yè)面加載之后會(huì)啟動(dòng)js程序(一般都是jquery)對(duì)頁(yè)面element進(jìn)行配置和處理,例如:設(shè)置風(fēng)格、事件等等。 

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


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

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

            但如果用戶點(diǎn)擊(左鍵或者右鍵)此 node對(duì)象時(shí),js代碼會(huì)動(dòng)態(tài)插入一個(gè)YTAG的變量 

            未點(diǎn)擊:
            <a ytag="40037" target="_blank">路由器</a>

            點(diǎn)擊:   
            <a ytag="40037" target="_blank">路由器</a>

            變量生成方式在這個(gè)js中實(shí)現(xiàn):

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

            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對(duì)象,并進(jìn)行初始化init() ,query()是用戶點(diǎn)擊查詢時(shí)觸發(fā)使用 
            init()內(nèi)部配置了query函數(shù),用于鼠標(biāo)點(diǎn)擊時(shí)候生成YTAG屬性
            看代碼就很簡(jiǎn)單了

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

            posted @ 2014-05-15 01:00 放屁阿狗 閱讀(786) | 評(píng)論 (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 放屁阿狗 閱讀(955) | 評(píng)論 (0)編輯 收藏

            俺不是果粉,但開發(fā)必須mac
            參加的開發(fā)者大會(huì),老外沒一個(gè)不是mac的,也的確如此,mac是開發(fā)神器,雖然貴點(diǎn),但還是很值,對(duì)得起他的身價(jià) 。
            這是一種態(tài)度,價(jià)值觀世界觀的體現(xiàn)
            linux+windows的完美結(jié)合,不!! ui遠(yuǎn)超windows

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


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

            寫代碼,寫好代碼其實(shí)并不難,但如果要做好文檔,能完整闡述清楚自己的構(gòu)思、想法和邏輯結(jié)構(gòu),這比較難,自己也缺少這方面的耐心。
            很多opensource的代碼根本不需要文檔也能一目了然,這是一種定力
            多年前的項(xiàng)目中使用到python和ffmpeg, 網(wǎng)絡(luò)上搜索了一下,均不能滿足自己的要求。ffmpeg的python綁定提供的均是文件級(jí)的訪問控制,也就是說沒有暴露更多的可控接口來用。
            所以還是一切都自己來做
            ffmpeg采用0.81版本以上,當(dāng)時(shí)發(fā)現(xiàn)mov文件在0.71以下無法正常解碼,到0.81則解決了此問題。
            python包裝ffmpeg的方式很多,最好的可能就是swig,但太煩了,最后選擇ctypes來訪問ffmpeg接口。 
            如果直接使用ffmpeg的api接口也不太合適,因?yàn)橐┞逗芏鄁fmpeg的接口、數(shù)據(jù)類型、常數(shù)定義等。
            所以我是這么處理:   
              1. 編寫一個(gè)功能動(dòng)態(tài)庫(kù)來包裝ffmpeg,提供基本的業(yè)務(wù)功能 ,屏蔽ffmpeg細(xì)節(jié),這里叫ffmpeg_media_codec.dll
              2. 用ctypes包裝此ffmpeg_media_codec.dll,這里是ffmpeg.py
              3. 業(yè)務(wù)代碼使用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; //視頻流編號(hào)
            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; //播放時(shí)間
            27 };
            28 
            29 struct MediaPacket_t{
            30      StreamByte_t*    data;
            31      size_t            size;
            32     AVPacket    *    pkt;
            33     int                stream;    //流編號(hào) 
            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; //流編號(hào)
            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();         //初始化解碼庫(kù)
            71 void Cleanup();    //
            73 MediaCodecContext_t* InitAvCodec(MediaStreamInfo_t* si);    //根據(jù)媒體類型分配解碼器對(duì)象
            74 void FreeAvCodec(MediaCodecContext_t* codec);                  //釋放解碼器對(duì)象
            76 MediaVideoFrame_t * DecodeVideoFrame(MediaCodecContext_t* ctx,MediaPacket_t* pkt);  //送入媒體包進(jìn)行解碼,返回視頻幀
            77 void FreeVideoFrame(MediaVideoFrame_t* frame);                  //釋放視頻幀
            79 MediaPacket_t * AllocPacket();                                             //分配一個(gè)流媒體包對(duì)象(用于網(wǎng)傳)
            80 void FreePacket(MediaPacket_t* pkt);                                    //釋放流媒體包
            82 MediaFormatContext_t* InitAvFormatContext(char * file);          //媒體文件訪問上下文,申請(qǐng)
            83 void FreeAvFormatContext(MediaFormatContext_t* ctx);          //釋放
            84 MediaPacket_t* ReadNextPacket(MediaFormatContext_t* ctx);   //讀媒體文件一個(gè)數(shù)據(jù)包
            85 void ReadReset(MediaFormatContext_t* ctx) ;                //重置媒體訪問讀取位置
            86 int SeekToTime(int timesec) ;                                     //跳躍到指定時(shí)間

            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表數(shù)據(jù)
             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 放屁阿狗 閱讀(5849) | 評(píng)論 (2)編輯 收藏

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

            目前從事im,移動(dòng)互聯(lián)網(wǎng)平臺(tái)框架,p2p,并行計(jì)算方面研究
            posted @ 2014-04-13 14:27 放屁阿狗 閱讀(1426) | 評(píng)論 (4)編輯 收藏

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

            應(yīng)用中經(jīng)常用pyCrypto 來生成用戶Token等相關(guān)信息,夠簡(jiǎn)單,所以貼代碼分享
            部分代碼被關(guān)閉或者打開,使用者請(qǐng)自行調(diào)整,如果了解rsa很簡(jiǎn)單理解一下代碼 

              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和待加密明文數(shù)據(jù)text
             50         自動(dòng)生成8字節(jié)長(zhǎng)度隨機(jī)密碼P,用P將text進(jìn)行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加密的數(shù)據(jù)
             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         用戶信息轉(zhuǎn)換為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 放屁阿狗 閱讀(3363) | 評(píng)論 (1)編輯 收藏

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

            nginx :               http服務(wù),提供反向代理和負(fù)載均衡服務(wù)(集群可用DNS或考慮LVS方案)
            mongodb+gridfs : 用于文件服務(wù)提供,其內(nèi)置gridfs提供了分布式,海量存儲(chǔ)的方案
            gevent+webpy : nginx直接讀取gridfs是不合適的,配置了cgi才能完成特定功能,這里使用webpy,比django更輕更好用。
                                     webpy的作用是接收到上傳和下傳文件的請(qǐng)求,讀寫gridfs文件內(nèi)容給移動(dòng)端。
                                      gevent是高效的通信框架,雖然單線程工作,但性能非常的好;
                                     用好gevent關(guān)鍵在與外部的io必須全部都是異步的,例如: 數(shù)據(jù)庫(kù),文件磁盤訪問等等。
                                     mongodb對(duì)gevent已經(jīng)支持,gevent對(duì)webpy,django,psycopg2支持也相當(dāng)?shù)暮茫砸峁﹚ebservice服務(wù)那就考慮用gevent+webpy或django把,性能是杠杠的,比 apache+mod_wsgi要好很多 ,而且gevent是進(jìn)程內(nèi)的不同的HTTP REQUEST可以是共享數(shù)據(jù)的,這一點(diǎn)非常誘惑(apache+mod_wsgi的REQUEST可是隔離的哦!除非您通過redis的PUB/SUB實(shí)現(xiàn)兩個(gè)REQUEST的通信)
                                   
            關(guān)注的問題:
            1.下傳大文件時(shí)的處理
               如果直接用nginx當(dāng)然沒有這個(gè)問題 ,但用webpy讀取文件返回HttpResponse時(shí)問題來了,總不至于讀取整個(gè)文件,然后再return。
                     這種方式在php有flush方法,python只能用yield來做
             2.上傳大文件時(shí)的處理
                    當(dāng)接收到http的文件POST請(qǐng)求時(shí),文件已經(jīng)全部緩存到web服務(wù)器,如果同時(shí)幾千個(gè)文件上傳在進(jìn)行,服務(wù)器就會(huì)被擠爆,這也是很多網(wǎng)站不允許大文件上傳的緣故吧。關(guān)于這個(gè)問題,我想就需要修改一下webpy關(guān)于文件上傳的處理代碼了,將接收到的文件數(shù)據(jù)以流的形式寫入到gridfs里去作為臨時(shí)文件被緩存,等完全接收文件時(shí),才通知到handler代碼,這樣必定高效很多(新的問題又來了,會(huì)不會(huì)把gridfs搞爆掉! 處理時(shí)考慮延時(shí)緩存提交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 放屁阿狗 閱讀(1832) | 評(píng)論 (0)編輯 收藏

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

            多樣的文本消息
            -----------------
            struct MimeText_t{
                 int type;
                 string text;
            };
            MimeText_t 可以包含普通的文本、圖像和音頻文件的id 
            圖像和音頻數(shù)據(jù)發(fā)送到服務(wù)器,服務(wù)器并不直接將數(shù)據(jù)發(fā)送到接收者,而是發(fā)送 音頻和圖像的描述uri信息 
            接收者解釋json,顯示text文本,讀取emoticon編號(hào),顯示表情圖片;  image,audio則顯示占位(如果當(dāng)前wifi可用,則自己自動(dòng)加載image和audio資源) ,如果非wifi信號(hào)則待用戶點(diǎn)擊此占位,然后從服務(wù)器請(qǐng)求image和audio資源到本地。
            文本描述: 字體大小,顏色,文本link,表情符號(hào) 
            文本用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號(hào)浦星公路口'},
                 emoticon:{id:201}
              ],
            }
            屬性名簡(jiǎn)化: 
            ---------------------
            -----------------------
            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) | 評(píng)論 (0)編輯 收藏

            2016年9月18日 #

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

            2016年8月23日 #

            干了17,8年一線技術(shù)工作,還不如剛畢業(yè)的985學(xué)生,真是好笑。 現(xiàn)在覺得也沒啥多想的,現(xiàn)在樂于出去跟不同公司談?wù)劶夹g(shù)問題,面試完,基本也給對(duì)方上完一通技術(shù)課程。 晚上看一17歲小朋友在直播寫帶代碼,滿有意思,自己也想玩玩。 tce工程加入csharp支持中,本地代碼差不多一半,lex分析還沒開動(dòng),要抓緊了,早點(diǎn)能在unity上跑起來。 公司這兩個(gè)月要搞個(gè)證照系統(tǒng),設(shè)計(jì)完框架了,要寫代碼了。
            posted @ 2016-08-23 04:09 放屁阿狗 閱讀(443) | 評(píng)論 (2)編輯 收藏

            2016年3月24日 #

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

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

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


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



            附錄  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 放屁阿狗 閱讀(16208) | 評(píng)論 (1)編輯 收藏

            2016年1月29日 #

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

            2015年6月29日 #


            訪問sf,記錄下一下代碼

            (注冊(cè)sf的app,登記 callback-url,執(zhí)行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 放屁阿狗 閱讀(918) | 評(píng)論 (0)編輯 收藏

            2015年5月26日 #


            python內(nèi)部數(shù)據(jù)容器有dict和list兩種 ,工作中最常用的方式是定義一些數(shù)據(jù)結(jié)構(gòu)(數(shù)據(jù)即代碼),例如: 

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

            frog對(duì)象定義了小動(dòng)物的某些屬性,訪問frog對(duì)象屬性時(shí),通過 dict,list的取值方法進(jìn)行訪問,例如:  
            print frog['name']
            print frog['friend'][0]  
            有時(shí)覺得這種表達(dá)方式太原始了,需要改進(jìn),最好是以 '.'方式訪問對(duì)象屬性,例如:  
            print frog.name
            代碼來開始和結(jié)束吧, class _x 
             1 class _x:
             2     """
             3     從簡(jiǎn)單數(shù)據(jù)類型轉(zhuǎn)換成python對(duì)象
             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 放屁阿狗 閱讀(628) | 評(píng)論 (0)編輯 收藏

            2015年1月1日 #

            相關(guān)技術(shù):  haproxy_keepalived_nginx_uwsgi_gevent_django 

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

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

            2014年10月8日 #


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

            服務(wù)器通過頁(yè)面請(qǐng)求的session-id來區(qū)分之后提交的驗(yàn)證碼。 第一次請(qǐng)求查詢頁(yè)面時(shí),服務(wù)器將訪問session(cookie)傳到客戶端,之后的查詢和驗(yàn)證碼獲取時(shí)客戶端攜帶之前的cookie傳送到服務(wù)器,服務(wù)器端保存著當(dāng)前 session-id與驗(yàn)證碼 的對(duì)應(yīng)關(guān)系。 

            查詢返回記錄可通過 xpath或者 beautifulsoup進(jìn)行解析

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

            交通網(wǎng)的驗(yàn)證碼生成還是比較簡(jiǎn)單,做自動(dòng)識(shí)別可找?guī)讉€(gè)簡(jiǎn)單的圖形識(shí)別程序即可。
            如若不行,則人工輸入嘍
            posted @ 2014-10-08 00:45 放屁阿狗 閱讀(1340) | 評(píng)論 (0)編輯 收藏

            2014年5月20日 #

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

            久久久久国色AV免费看图片| 成人综合久久精品色婷婷| 狠狠综合久久综合中文88| 综合久久一区二区三区| 久久久久久久亚洲Av无码| 精品国产91久久久久久久| 天天综合久久一二三区| 新狼窝色AV性久久久久久| 99久久久久| 无码超乳爆乳中文字幕久久| 九九久久精品国产| 亚洲国产欧美国产综合久久| 国产精品欧美久久久久天天影视 | 久久人妻少妇嫩草AV蜜桃| 亚洲中文久久精品无码ww16| 99久久综合国产精品二区| 亚洲女久久久噜噜噜熟女| 国产成人久久久精品二区三区| 久久人做人爽一区二区三区| 亚洲国产天堂久久综合网站| 热99RE久久精品这里都是精品免费| 久久久综合九色合综国产| 中文国产成人精品久久不卡| 久久久久亚洲精品中文字幕| 97久久精品无码一区二区天美| 久久这里有精品| 久久综合九色综合久99| 午夜精品久久久久久99热| 久久国产福利免费| 久久精品中文字幕无码绿巨人| 久久这里只精品99re66| 国产毛片久久久久久国产毛片| 久久久久亚洲AV无码网站| 久久毛片一区二区| 狠狠人妻久久久久久综合蜜桃| AV无码久久久久不卡蜜桃| 亚洲精品高清一二区久久| 久久激情亚洲精品无码?V| 青青国产成人久久91网| 国产精品禁18久久久夂久| 色偷偷久久一区二区三区|