socketref,再见!高德

https://github.com/adoggie

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

常用链接

留言簿(54)

我参与的团队

搜索

  •  

最新评论

阅读排行榜

评论排行榜

#

Queue用于生产者、消费者模型 
gevent提供了'Queue', 'PriorityQueue', 'LifoQueue', 'JoinableQueue' 四种队列,文档介绍不全 ,看了代码方才了解

所有队列类型都是安全的(synchronized queue) ,数据推入和提取无需访问保护

LifoQueue - 后进先出队列,同数据堆栈结构
JoinableQueue -  增加join,所有数据提取完毕join解除阻塞 
PriorityQueue - 优先级队列,提取根据置入时的优先级别
Queue - 超类消息队列,提供同步数据置入和提取功能,其他队列均从Queue派生
posted @ 2013-09-19 14:44 放屁阿狗 阅读(485) | 评论 (0)编辑 收藏

TCE
项目全称Tiny Communication Engine,意味着小型的通信引擎




RPC技术:
    RPC是指远程过程调用(Remote Procedure Call),这种技术被定义出来应该有成长的历史时间。
    RPC技术意在消除网络通信的细节,让开发者只需关心具体的业务而不必考虑由于网络、硬件、系统的异构复杂环境。相关的RPC有DCOM,java的RMI,CORBA,VISIBROKER,ICE(zeroc.com)等等。
    xmlRPC是基于xml数据格式的RPC封装,相关的使用项目也不老少,但这东东由于是xml格式,数据流量太大,不建议使用。

使用RPC的原因:
     传统端到端的通信方式一般都是基于流的数据传递,应用消息在发送端编码并传送到接收端解码。 这是一个重复造轮子的过程,不同的应用协议由于规格不同,消息到流的序列化和反序列化过程不可避免。这个过程是个容易出错的过程,应用协议的改动则必须再次修改编解码代码,这不该是提倡的,且显得异常无奈和低端。
    流式的数据在接收之后必须进行应用类型的消息分拣,以便分派消息到不同的处理函数,这个过程同样也会被重复的编写。
    


TCE是RPC的实现:
    因为是轻量级的,所以很容易被修改、扩展或者被重新定义。 
    目前已经支持多种开发语言和通信方式。

TCE的功能特点: 
     1.多通信协议:   rpc的消息可以在多种协议上被交换,协议包括:socket,websocket,MQ,http。 socket应用于最常见的端端通信,c,s两端直接socket完成通信; websocket支持html5的javascript与服务器的通信; MQ 指集群系统之间消息队列作为数据传递总线时,Rpc消息作为MQ的消息包被传递交换。

     2.基于接口级别的调用:  这种模式完全不同与流消息传递,用户无需关心消息如何被序列化和反序列化,并且无需参与消息类型到处理业务函数的分拣,这一切都是自动的,A只需调用B的一个函数接口即可

     3.多语言支持: TCE目前实现的语言有c++,java,javascript,as3,python 支持在这些语言之间互相接口调用。

     4.一致的通信服务:   
           tce内置高性能的通信服务器,c++版本采用boost::asio,python版本采用gevent作为通信引擎

     5. 多种调用模式:
            normal-call (twoway) - client调用server接口,此刻线程被阻塞,直到server处理返回
               oneway-call - client调用server接口之后即刻返回,这种适用于挥发性的调用请求类型,例如:心跳包  
               timeout-call - client调用server接口,此刻线程被阻塞,直到server处理返回,如果超时,线程会被解除阻塞
               async-call - client调用server接口之后即刻返回,server处理返回之后将回调client的异步处理函数
               reversed-call - NAT网络模式下,client发起RPC调用时将建立与server的socket连接,并请求server端RPC接口;反向调用指server端凭借此连接调用client端的RPC接口

接口定义语言(IDL):
    不同的Rpc的实现都有自己的定义规格,TCE的规格类似与ICE。
    文件命名:<interface>.idl 
    1. 数据类型: 
      --name       size    c++                java             python             as3           javascript 
        byte              1      int8                 byte             int                  byte
        short             2      int16               short            int
        int                 4      int32               int                int
        float              4      float                float              float
        long              8       int64              long              int
        double           8      double             long              float
        string            -       std::string       String           str
        bool              1       bool                boolean         True/False
        sequence                std::vector      Vector           []                 Array               Array
        dictionary                std::map         HashMap       {}                HashMap          Hash
        struct                     struct             class               class           class               function

    1. module:  系统模块定义,同一个接口文件中可以包含多个module定义
          module first{ ... }
          module second{ ... }

     2. struct :  数据结构定义
               struct Student{
                   int no;
                   string name;
                   int grade;
                };
       
     3. sequence: 数组 
         sequence<int> IdList;
         sequence<string> StrList;

      4. dictionary: 哈希结构
         dictionary<string,Student>   StudentList;

      5. interface :  接口定义
          interface GisServer{
                string Authorize(string user,string passwd);
                GpsData  getGpsData(string device_id);
          };

             
posted @ 2013-09-15 22:25 放屁阿狗 阅读(2289) | 评论 (0)编辑 收藏

由于最近也是比较有时间,想着将Windows版本的地图绘制引擎移植到Linux。
地图Render部分采用的是Qt,所以过程非常顺利,用Eclipse+CDT重建工程,略微几个小改动便完成了移植。
但之后发现了Qt带来的问题了,地图绘制引擎支持并发处理多个绘制请求,不同的绘制请求将在不同的线程Thread中被执行,多线程的情况便出现了问题,提示QPixmap不能在非UI线程被构造,如果强行构造,便出现了内存数据访问违例的异常错误,进程直接coredump,这个问题困扰了一些时间;
之后改了改代码,将数据处理和绘制代码隔离开,线程thread中进行数据加载、分析、计算,绘制代码采用Qt的signal/slot机制完成,就是工作线程处理好数据之后通过emit signal将绘制请求发送给ui主线程的slot处理函数。这种实现方法的问题在于绘制工作都将被串行执行,性能下降。
几年前在移植libsvg到wince时采用过cairo( cairographices.org) ,有点使用经验,且cairo是gnome的标准图形库,性能应该不错,所以直接改为cairo。
cairomm是cairo的c++包装,编译还需sig++,cairo的api还是挺丰富的,字体,反走样,矩阵... 操作也是相当简单 
很快移植完成,运行效果还是比较满意,现在正考虑地图引擎移植到ios设备,目前需要琢磨cairomm,sig++,pixmap之类的东西如何移植问题(或者直接采用ios的Fundation的绘图api)

posted @ 2013-08-31 15:39 放屁阿狗 阅读(2540) | 评论 (1)编辑 收藏

看到 AsyncResult这个类,想到我之前自己写的处理异步返回值的类 

 1 class MutexObject:
 2     def __init__(self):
 3         self.mtx = threading.Condition()
 4         self.d = None
 5         
 6     def waitObject(self,timeout):
 7         d = None
 8         self.mtx.acquire()
 9         if self.d == None:
10             if timeout:
11                 self.mtx.wait(timeout)
12             else:
13                 self.mtx.wait()
14             d = self.d
15             self.d = None
16         self.mtx.release()
17         return d
18         
19     def notify(self,d):
20         self.mtx.acquire()
21         self.d = d
22         self.mtx.notify()
23         self.mtx.release()
posted @ 2013-05-14 01:04 放屁阿狗 阅读(474) | 评论 (0)编辑 收藏

 1 class SimpleConfig:
 2     def __init__(self):
 3         self.confile =''
 4         self.props={}
 5 
 6     def load(self,file):
 7         try:
 8             f = open(file,'r')
 9             lines = f.readlines()
10             f.close()
11             self.props={}
12             for line in lines:
13                 line = line.strip()
14                 if not line or line[0]=='#':
15                     continue
16                 line = line.split('#')[0]
17                 pp = line.split('=')
18                 if len(pp)!=2:
19                     continue
20                 k,v = pp[0].strip(),pp[1].strip()
21                 self.props[k] = v
22         except:
23             traceback.print_exc()
24             self.props ={}
25         return True
26 
27     def get(self,key,default=None):
28         return self.props.get(key,default)
posted @ 2013-04-02 13:36 放屁阿狗 阅读(338) | 评论 (0)编辑 收藏

聊聊草草
实现一套通信框架
A - 移动终端; B - 接入服务器(网关) , C,D,E - 内部服务系统 , M -内部服务系统的消息队列
B 用于接入成千上万的A,B不具备业务能力,只有CDE才能与A进行业务交互,M充当消息管道。
一般的做法,各个系统模块指定标准协议,可以是xml或者二进制的,然后各开发各的,socket或者http等部件,开发语言也是cpp,python,java齐上阵。
这种开发模式过于繁琐,模块之间的耦合比较紧密,应该把应用和通信细节剥离出来。
我的做法是所有有系统对象之间的消息传递都是基于Rpc接口级的调用,更本不设计通信、协议编码,只要根据IDL就可以,A请求C的服务,那A只需要调用C的接口函数即可,底部的工作:
A到B的socket通信,B将A的消息转换到M,M再传输到C,这些工作都可以透过Rpc层完成透明,反过来C的调用请求也安原路返回到A。
C要发送消息到A,那调用A的接口,rpc层自动将请求转化未MQ协议,被路由到B,B找到A的链接,并将Mq消息转化未socket消息传递到A,A端接收消息转换成Rpc函数回调到A的应用代码。

除了简单的调用、返回方式还有
单项调用请求、异步调用请求、消息广播请求

B端可以通过外部配置使得A的请求路由到C,或者D,或者全部接收,取决与应用需求(应用还是集群)
MQ如果系统总线一般,将各个服务子系统链接成网络,是构成整个系统的基础。Rpc可以解脱程序员,让其将经历花在具体业务上,而且基本只要编写若干的服务接口函数即可。

当然要实现以上功能特点,很多可用的框架,CORBA,DCOM,ICE等等,但这些过于庞大,对环境要求也有限制,如果要更高效、灵活的运用和包装需要大量修改其底层代码,与第三方的整合只能工作在他们的上层接口上,这个令人很沮丧,会导致产生更多的依赖和复杂的编程技巧。
这些全都丢弃,还是自己的rpc
posted @ 2012-11-22 10:50 放屁阿狗 阅读(3514) | 评论 (0)编辑 收藏

     摘要: 弄Rpc有一段时间了,从定义IDL规则,自动生成存根代码给应用使用,相继做了c++,java,python,actionscript四个版本,且都都能互相调用,协议是自定义的二进制格式。公司的项目要求我从事android的开发,编写一些小的应用,要与平台服务器通信。与服务器的通信采用xml交换,之前做的二进制编码便不能使用。不想很弱智的去重复的编解码xml消息格式,去编写socket通信代码,工作...  阅读全文
posted @ 2012-11-22 10:17 放屁阿狗 阅读(2746) | 评论 (0)编辑 收藏

w3.org定义了websocket的规范,但仅限于草案。
websocket的出现可以提高用户交互体验,减少网络io负荷
当初http的出现,只是那个时代的产物,我觉得现在其已经是一种负担和糟粕,应该推行出一套全新的符合时代潮流的互联网协议,但又如何简单。
看了websocket与node.js的应用demo,由于还是 基于http链路的,所以消息的marshall/unmarshall必须是明文编码,以 00开始ff结束一个封包。这很令我想不明白为何这么定义,也许草案阶段的产物。那xml,json是格式化的最终选择,两端都是javascript引擎驱动数据转换,某种应用角度来讲不错,但如果做实时的应用我觉得存在io浪费、时延等诸多问题。
这个问题在于http的规范,且互联网上充斥着对http支持的设备和系统,路由、网管都能识别http的报文并进行处理、分析。
也许还再等等看看

自己在写的rpc可以实现python与flex进行rpc通信,等有时间实现一下websocket的rpc
posted @ 2012-09-15 14:15 放屁阿狗 阅读(436) | 评论 (0)编辑 收藏

提高水平总是靠学习他人代码来的快

看看这个代码,摘录自gameobject
 1   def __init__(self, x=0., y=0.):
 2         """Initialise a vector
 3 
 4         @type x: number
 5         @param x: The x value (defaults to 0.), or a container of 2 values
 6         @type x: number
 7         @param y: The y value (defaults to 0.)
 8 
 9         """
10         if hasattr(x, "__getitem__"):
11             x, y = x
12             self._v = [float(x), float(y)]
13         else:
14             self._v = [float(x), float(y)]
挺好的,参数带入可以支持 a(1,2)形式,也可支持a( (1,2) )形式 ,非常灵活,自已以前总是想不到用hasattr来判断


posted @ 2012-07-10 10:04 放屁阿狗 阅读(398) | 评论 (0)编辑 收藏

应用中会有输入gps坐标,计算返回所处地理位置文本描述
例如: (x,y) => 虹梅路2007号 宜山路200号 苏宁电器正南方向300米

当然数据必须要有,包括 poi和道路数据
为了实现快速检索,将feature数据进行分幅存储,把全国地图进行切割成固定网格大小,并将不同层feature存储这个网格内
切割存储feature到网格,实现的方法很多:
 postgis , oracle sde ,arcgis sde , osge算法库,ogr....
我采用postgis将切割的feature放入数据表,建立好相关索引
输入gps坐标,先转换成地图坐标,然后检索出以地图坐标为中心的九宫格地理网格,然后在这些网格内计算不同的feature与当前gps坐标的位置描述

例如: 输入 121.20,31.20
返回 :
上海旺而固实业有限公司    71.6009040754    165.190566006 degree正北方
上海起帆电缆有限公司    77.4887765243    168.290539492 degree正北方
塔星集团新塔星石材    78.9584224298    161.627196901 degree正北方
上海大宝化工制品有限公司    87.7190868822    151.671844699 degree东北方
第二个参数是距离(米) ,第三个为两点之间的夹角,最后一个表示方位

  1 #计算点a,b,c的夹角
  2 def abc_angle(a,b,c):
  3     ba= Vector2.from_points(b,a)
  4     bc = Vector2.from_points(b,c)
  5     #点乘计算夹角
  6     dot = (ba[0]*bc[0]+ba[1]*bc[1] )
  7     x =  dot/ (ba.get_magnitude()*bc.get_magnitude() )
  8     angle =  (math.acos(x) / math.pi) * 180
  9     return angle
 10 
 11 #print abc_angle(b,a,c)
 12 
 13 
 14 def whereis(p1,p2):
 15     '''
 16         判别p2所处p1的方向位置
 17     '''
 18     txt=''
 19     a,b,c = (p1[0],0),p1,p2
 20     a =  abc_angle(a,b,c)
 21     if a <= 20:
 22         txt=u'正南方'
 23     elif a>=160:
 24         txt = u'正北方'
 25     elif a>20 and a<=70:
 26         if p2[0] <= p1[0]:
 27             txt =u'西南方'
 28         else:
 29             txt = u'东南方'
 30     elif a>=70 and a<=110:
 31         if p2[0] <= p1[0]:
 32             txt = u'正西方'
 33         else:
 34             txt = u'正东方'
 35     else:
 36         if p2[0] <= p1[0]:
 37             txt = u'西北方'
 38         else:
 39             txt = u'东北方'
 40     return a,txt
 41 
 42 '''
 43 设定查找九宫格,xy位置处于MIDDLE_CENTER
 44 select name,st_distance(ST_MAKEPOINT(121.2,31.2),the_geom) as dist , * from data_c31_point order by dist limit 100;
 45 
 46 cast(x'fff' as int)
 47 
 48 select distinct(layerid),count(*) from data_c31_point group by layerid
 49 '''
 50 def searchPoints(xy,layers):
 51     '''
 52         xy - (lon,lat) gps坐标点
 53         layers - ()  查询的层编号列表
 54     '''
 55     xy = point_g2m(xy[0],xy[1])
 56     bid = breadth.getBreadthId(xy)
 57     x = breadth.getX(bid)
 58     y = breadth.getY(bid)
 59     xx = x-1,x+1
 60     yy = y-1,y+1 #在9个网格内检索
 61     layers = ','.join(map(str,layers))
 62 
 63     sql ='''
 64         select st_x(the_geom) as x,st_y(the_geom) as y,name,st_distance(ST_MAKEPOINT(%s,%s),the_geom) as dist
 65         from data_c31_point
 66         where
 67         layerid in ( %s )
 68         and
 69         ( (bid>>12) &4095 ) >=%s
 70         and
 71         ( (bid>>12) &4095 ) <=%s
 72         and
 73         ( bid&4095 ) >=%s
 74         and
 75         ( bid&4095 ) <=%s
 76         order by dist
 77         limit 100;
 78         '''%(xy[0],xy[1],layers,xx[0],xx[1],yy[0],yy[1])
 79 
 80     #print sql
 81 
 82     '''
 83     不同层检索出的poi要选择性的输出
 84     计算每个点处于输入gps坐标的方向: 正南,东南. + 距离
 85     '''
 86     db = getDBConn()
 87     cr = db.cursor()
 88     cr.execute(sql)
 89     rs=[]
 90     while True:
 91         r = dbconn.fetchoneDict(cr)
 92         if not r:
 93             break
 94         a,postxt = whereis((r['x'],r['y']),xy)  #gps坐标处于地理poi的方位
 95         rs.append([r['name'],r['dist'],postxt,a] )
 96     return rs
 97 
 98 if __name__=='__main__':
 99     rs = searchPoints((121.20,31.2),range(17,22))
100     f = open('geotxt.txt','w')
101     for r in rs:
102         f.write(r[0].decode('utf8').encode('gbk'))
103         f.write('    %s    %s degree'%(r[1]*1000*11,r[3]))
104         f.write(r[2].encode('gbk'))
105         f.write('\n')
106         #print r[0].decode('utf8').encode('gbk')
107     f.close()
posted @ 2012-07-07 02:26 放屁阿狗 阅读(2024) | 评论 (1)编辑 收藏

仅列出标题
共25页: 1 2 3 4 5 6 7 8 9 Last