-
python kivy 开发经验总结
2018-01-19 19:09:05python kivy 开发经验总结 kivy 是一款 python 的GUI开发框架,特点是样式可以和代码分离,绘图功能基于OpenGL编写,可以用来开发比较炫的界面,并且可以打包为Android、iOS等移动应用,还能运行在Linux、Windows、...python kivy 开发经验总结
kivy 是一款 python 的GUI开发框架,特点是样式可以和代码分离,绘图功能基于OpenGL编写,可以用来开发比较炫的界面,并且可以打包为Android、iOS等移动应用,还能运行在Linux、Windows、MacOS上。
这篇博客将记录我使用kivy开发的经验,所以会持续更新,且篇幅较长,是一篇kivy开发的技术笔记,欢迎大家留言交流。
缘起-项目介绍
我们塔尔旺科技有限公司准备开发一款能对图片进行画框标注的程序,因为是内部使用,所以选用 python kivy 作为GUI框架。之前从网上已经得知 kivy 虽然有专业团队支撑,但是框架不如 pyQt 或者 wxWindow 成熟,由于太容易上手,并且很喜欢kivy的样式分离的模式,所以依然决定使用一次。
入门
首选需要阅读 kivy 入门教程,读一遍Introduction 和 Programming Guide,写几个小例子,基本就差不多了。
kivy 中的几个概念还是比较容易理解,如果做过 android 开发,会发现和 android 程序的开发模式很相似。例如都有 app 生命周期,通过重写 app 的 on_start() 等方法可以在各种生命周期状态下执行操作。
主要的概念有:
1. Application
2. Widget
3. Event
4. Property
5. KV Design Language
6. Layout
7. OpenGL Drawing Instructions上面这些内容,都可以在 kivy 入门教程 中找到。
下面记录的就是我们在开发中积累的一些经验了。
Layout 相关经验总结
关于 FloatLayout
这个布局,会看子 Widget 的
pos_hint
和size_hint
,依据他们来计算子 Widget 的位置和大小,还可以用子 Widget 的pos
属性来指定自己的位置 (用的是窗口坐标系)。pos_hint
和size_hint
这两个属性的取值都是 0 到 1,并且 size_hint 默认值是 1 , 所以可以用 FloatLayout 实现完全填充父容器的效果。因此,可以简单的理解为:
1. FloatLayout 的子 Widget 可以定位到任意位置
2. FloatLayout 的子 Widget 大小可以充满整个父容器,或为父容器的几分之一。关于 AnchorLayout
这个布局需要注意,它只能设置一种位置关系,所有的子容器都使用该关系进行定位。
定位的参数要靠 AnchorLayout 对象的 anchor_x 和 anchor_y 属性来确定,而不是像其他的 Layout 类,依靠子 Widget 的 pos_hint 属性来设置Widget的位置。这给使用带来了不便,也是容易误解的一大问题。
小技巧:可以用 FloatLayout + AnchorLayout 来实现居中的效果。例如下面的KV language:
<MainWindow>: # float layout AnchorLayout: # 小技巧,居中子Widget LabelManager: # relative layout id: label_manager size_hint: None, None size: '800dp', '800dp' # canvas: # Color: # rgb: 0, 1, 0 # Rectangle: # pos: (0, 0) # relative 的容器,位置要使用0,0,对自己的canvas已经使用了局部坐标系 # size: self.size ImageWidget: id: image label_manager: label_manager pos_hint: {'x':0, 'y':0} size: self.parent.size Button: pos_hint: {'x':0, 'y':0} size_hint: None, None size: '150dp', '50dp' text: '打开图片目录' font_size: '16sp' color: .5, .7, .9, 1 on_press: root.show_load()
当然,我们还有一个更简单的居中方法:
<MainWindow>: # float layout LabelManager: # relative layout id: label_manager size_hint: None, None size: '800dp', '800dp' center: self.parent.center
关于 RelativeLayout
RelativeLayout 可以让子Widget的定位坐标原点变成Widget的左下角,而不是顶层窗口的左下角;当RelativeLayout的位置移动时,子Widget的位置会联动,以保持父子位置不变。
触控点的坐标:如果一个Widget的父容器有RelativeLayout、ScatterLayout、Scatter 和ScrollView 那么当触控(touch)事件传递到这些容器的子容器时,坐标点会被转换为容器坐标系的数值,而不再是顶层窗口的坐标了。要注意的是,对于这些特殊容器而言,触控坐标不会转换,只有他们的子Widget会收到转换后的坐标。
文档中用三种坐标系统来描述这些关系,分别是:
Window Coordinates 窗口坐标系
是最顶层窗口的坐标系,以窗口的左下角为原点。Parent Coordinates 父坐标系
距离本Widget最近的一个特殊父容器的局部坐标系。Local / Widget Coordinates 局部或Widget坐标系
以本Widget的左下角为原点的坐标系。
Widget 类提供了4个方法来对这三种坐标系进行转换,分别是:
to_widget()
接收窗口坐标,返回局部坐标。to_window()
接收局部坐标 ,返回窗口坐标。to_parent()
接收局部坐标,返回父坐标。to_local()
接收父坐标,返回局部坐标。
关于键盘输入
关于 Clock 的几种调度机制
kivy 的
Clock
类提供了几种时钟调度机制,分别是Clock.scheduled_once()
,Clock.schedule_interval()
和Clock.create_trigger()
。
使用的例子:def my_callback(dt): pass // call my_callback every 0.5 seconds event = Clock.schedule_interval(my_callback, 0.5) // call my_callback in 5 seconds event2 = Clock.schedule_once(my_callback, 5) event_trig = Clock.create_trigger(my_callback, 5) event_trig() // unschedule using cancel event.cancel() // unschedule using Clock.unschedule Clock.unschedule(event2)
遇到的问题和解决方案
自定义的 Kivy Widget size 设定无效
原来是因为把自定义的
Widget
放到了FloatLayout
下,FloatLayout
会根据size_hit
管理子 Widget 的大小,所以自己修改的 size 不起作用。解决的方法是设置子widget的size_hit 为(None, None)
,需要在创建对象时作为构造函数的参数传入,例如:BBox(size_hint=(None, None))
但是不能是设置
pos_hint=(None, None)
否则报错,想想也对,因为 FloatLayout 的主要作用就是能根据子Widget的 pos_hint 来定位,如果不用这个属性,那干脆就不用 FloatLayout 好了。如何设置 kivy desktop app 启动时全屏显示?
分下面几步即可实现:
1. 重写 App.on_start() 方法
2. 在其中调用 self.root_window.maximize() 即可。
代码如下:def on_start(self): self.root_window.maximize()
-
Erlang 游戏开发经验总结
2016-03-20 22:43:55现在回头看下这个问题,总结下erlang 游戏开发经验。就当是,为我过去一段时间的erlang开发经历,画上一个小句号。在写这篇文章前,我看过孔庆泉同学写过的Erlang 性能优化总结,字里行间有一点自己的体会,使得我...早早就想写这篇文章,但这段时间忙于工作的事情,就不自觉地给了自己各种懒惰的理由。现在回头看下这个问题,总结下erlang 游戏开发经验。就当是,为我过去一段时间的erlang开发经历,画上一个小句号。
在写这篇文章前,我看过孔庆泉同学写过的Erlang 性能优化总结[2],字里行间有一点自己的体会,使得我心血来潮,好像重新做回了erlang开发的感觉。所以,现在回过头,整理下游戏开发对erlang的使用。1. 架构设计
很多人都说Erlang天生分布式,归结原因是erlang分布式这块实现比较完善。节点间的通信是透明的,无论是节点内的进程,还是不同节点的进程,都可以使用 erlang:send/2 发送消息,而且数据不需要做任何转换。所以,很多项目会选用多节点架构,可以通过横向拓展(增加机器数量)来支撑更多负载,把性能压力大的子系统分配到不同的节点,这样,就可以支持更多的在线玩家。这样做的出发点是好的,但会引起一系列的问题:1、业务逻辑的问题:跨节点逻辑变得复杂,玩家数据同步、一致性问题,节点断开及重连的处理等2、语言局限性问题:节点间消息通讯要序列化和反序列化,原子传输要转成字符串,二进制复制等那架构选择单节点,还是多节点?没有绝对,这要看游戏而定。假如你的游戏像页游那样,分服而且各个服之间交互较少,单节点会比较适合。但如果像lol那种对战玩法的游戏,多节点会比较合适,登录和玩法在不同的节点,玩家对战时选择集群内压力较小的节点做战斗计算。单节点,好处是玩家数据容易保证一致,运维方便。以常见的MMORPG游戏,单节点在16G内存,8核心CPU,可以支撑2k人稳定在线,考虑非活跃玩家,达到5000也是可能的。当然,游戏的框架要合理设计,做一些妥协,比如玩家寻路不能在服务端做,地图九宫格的设计,排行榜不实时刷新,控制同屏玩家数量等等。现在,单节点做游戏服,还有一个重要原因是,现在的机器性能相较以前高很多了,加上erlang无锁的Actor设计在并发场合下解放了cpu,从某种程度上讲提高了cpu的运算能力。单节点的设计:
多节点的设计:
erlang节点注意一个问题,默认erlang节点是全联通的,也就是当一个节点加入集群时,集群其他所有节点会和新加入的节点建立联系。全联通带来的问题,集群节点间两两连接,随着节点增加,连接数量呈N*(N-1)/2增长,越发恐怖,连接本身占用了端口资源。更坏的是,为了检测节点的存活,erlang会定期发心跳包检查,即使一分钟一个tick,节点多的话也会造成大量的网络风暴。解决方法就是在集群中隐藏节点,就可以避免全联通,只要erlang启动加个参数即可 -hidden2. 数据库
数据库io向来都是游戏的主要性能瓶颈,处理不好容易导致游戏卡顿,甚至崩溃。而通用的持久化策略就是,内存读写+定时持久化。玩家上线时,加载玩家频繁用到的数据到内存,玩家大多时候就是在读写这些数据。然后定时把这些数据从内存刷到磁盘,在玩家下线时也做一次持久化。说下erlang自带数据库 - mnesia实际上,erlang已实现了这样一套持久化机制,也就是 mnesia数据库。mnesia数据存储是基于ets和dets实现,对于ram_copies表使用ets;disc_copies表同时使用ets和dets,数据读写使用ets,dets做持久化;而disc_only_copies表使用的是dets这里先讨论 disc_copies的情况,mnesia启动时,会将 disc_copies表所有数据加载到ets表中,每次读数据都是读ets,写数据则会先写到ets,然后再写一份到日志文件中,等待定时(或定量)持久化刷到dets。通常disc_copies表可以满足我们的业务需求,但使用mnesia要注意一个问题。前面也提到了,mnesia启动会将表中的数据加载到ets,假如你的表过大,就会导致内存被急剧消耗掉。(特征就是,ets所占的内存比率过大)所以,使用mnesia表时,经常都是要disc_copies表和disc_only_copies表配合使用。那问题来了,什么时候使用disc_copies表,什么时候disc_only_copies表。最简单的就是,对玩家数据动刀。玩家数据默认用disc_copies表,如果长时间没登录后将这个玩家的数据移到disc_only_copies表,等到他下次登录时再将数据移到disc_copies表。之所以可以这么做,理由有两个:1. 游戏中玩家数据所占的比例较大,调整玩家数据可以获得明显收益。2. 玩家流失后回到游戏的可能性很小,就算有的话比例也不大。这么做的弊端就是玩家流失后重新登录的时间较长,但通过这种方式减少的内存很可观。mnesia的使用,还要注意3个问题:1. mnesia单个表2G文件大小限制,所以要自己分表,或者使用表分片2. mnesia集群功能,过多的人说有坑,但我没有这方面的经验,就不做讨论3. mnesia事务并发性太差,尽可能不用mnesia事务,多脏写;事务可利用进程实现,保证数据安全3. 进程
每个玩家一个进程的设计已经成为了erlang游戏开发的潜规则了。这个没什么好讲,玩家进程修改自己的数据,进程消息同步处理机制保证数据一致性。可能有些游戏还会将玩家进程和scoket进程独立开,负责连接的建立和维护,协议封包解包,甚至做攻击的防范等。但如果玩家进程和socket进程同在一个节点内,显然整合在一个进程较好,erlang消息基于复制,中间多了一个进程,一次前后端交互要多了2次内存复制。那么,除玩家外,其他进程怎么确定?1. 地图进程每个玩家都是独立的进程,玩家pk要交换两个进程的私有数据,就要发消息给另一个进程处理。假如是强pk的游戏,同时有N个玩家一起打斗,消息就会繁多。因为数据一致性问题,进程间的并发机制就会弱化成同步机制,增加了战斗时延。所以,这里会引入地图进程,通常以一个地图一个进程。玩家进入地图时,会同步战斗相关数据到地图进程,玩家离开地图时,再将战斗数据同步回玩家进程。而在玩家进入地图到离开前的这段时间,一切的战斗计算都由地图进程完成。或者有人会有疑惑,就算有了地图进程,还是有同步问题,地图进程还是要同步处理pk请求,无法并发处理,玩家进程还是要等待地图进程操作完成。其实,对于玩家的pk请求,处理至少有两个过程,第一个过程是验证攻击的合法性,如是否有这个技能,技能cd,等等。第二个过程才是战斗计算,玩家进程检查合法性,再由地图进程做核心的战斗计算。另外一个,玩家进程除了战斗请求外,还有其他业务逻辑上的消息,容易出现进程挂起的情况,这时候,玩家进程不可能处理到战斗计算,就会导致战斗卡顿。2.公共进程公共进程指的是那些提供公共服务的进程,比如:1. 社交类,有好友、帮派、组队等,这些服务管理着多数玩家的数据,都需要一个进程来管理。2. 计算类,这类有一定的计算量,比如说排行榜,要有一个进程来承担计算。3. 广播类,有聊天室、世界聊天、帮派聊天、地图广播等4. 开关类,有活动系统,比赛系统等等,控制游戏活动的开启和关闭erlang进程虽然廉价,但是不要太过随意创建进程,比如创建一个临时进程异步传输数据等等。虽然这在某种程度上提高了并发性,但进程的创建和销毁需要一定的系统消耗,而且会导致项目中进程数量不可控,可能系统莫名其妙多了很多进程,这些维护起来也麻烦。再说,erlang同时存在的进程有最大数量限制4. 进程字典与ets
进程字典是erlang游戏开发中最为常用的数据记录方式,理由很简单,因为它够快,差不多比ets快了一个数量级。但是,进程字典的数据为所在进程私有,无法跨进程直接get到进程字典的数据,而且,在进程被销毁时,进程字典的数据也会被回收。再说下ets,对比进程字典,ets的适用场景是跨进程读写数据。遇到一个数据频繁被多个进程读到,就要考虑使用ets了。另外,ets有归属进程,但归属进程销毁时,ets的数据就会被系统回收。对比进程字典和ets的实现,区别如下:1. 锁方面,进程字典为无锁操作,ets是读写锁2. 数据方面,进程字典数据在进程中,查询没有多余的复制操作;而ets,因为数据不在进程中,查询时会复制一份到进程。所以,进程字典通常是最优先的选择。假如玩家的数据是存储在mnesia,特别是玩家的核心数据,就有必要从mnesia读到放在进程字典中。前面讲到了mnesia是利用ets和dets实现的,玩家上线时将核心数据读到进程字典,这样,读写都在进程字典,就可以利用进程字典带来的性能提升。这个提升是很可观,毕竟快了一个数量级。前面提到了ets归属进程销毁时,ets数据也会被回收?那么如果预防数据丢失的问题,ets也提供了方法,通过设置继承者进程就可以了。ets:new(person, [named_table, {heir, HeirPid, HeirData}])当归属进程崩溃时,继承者进程就会收到信息 {'ETS-TRANSFER', Tid, FromPid, HeirData},并且,ets的归属权就会转交到继承者进程。5. 消息广播
消息广播是游戏中的性能消耗大头,主要包括地图的行走、战斗广播,世界聊天广播。世界聊天广播可以通过控制玩家发送时间间隔来限制,地图中的广播包,比如行走和战斗包的广播实时性高,只需发给视野内的玩家就可以,不用全地图广播。所以常见的处理方式是,玩家的视野通过九宫格划分,玩家的地图广播只发送给九宫格内的玩家。如何在服务器压力大时,进一步优化广播消息:
针对时效性高的数据包,不重要的广播包,可以选择性丢弃:1、挂机玩家不发送战斗包,特别是战斗buff。2、每N个包丢弃一个挂机玩家的判定,前端以玩家长时间没动作来判定,或者将游戏切到后台运行时判定。等玩家在游戏内点击鼠标,或键盘时解除挂机状态。这里再谈下,消息广播还可能进一步优化。通常,后端发数据给前端都会对协议数据进行序列化(封包),然后再发给前端反序列化(解包)。而广播数据,对于每个玩家可能都是一样的,没必要每个玩家发给前端时都各自序列化一次,就只要序列化一次,然后每个玩家拿到数据后直接发给前端。erlang消息广播要注意什么问题?1、reduction计数通常会启动一个消息管理进程,这个进程就负责把广播消息转发给对应的所有玩家进程。启用管理进程的一个好处是,进程发消息会扣除reduction,而且这个reduction扣除大小还受到接收者进程影响。假如直接在地图进程做消息广播,就会导致地图进程受到的调度极度减少,影响战斗计算。2、消息复制erlang消息发送基于复制,但对于比较大的二进制数据,则会优化成二进制引用,减少二进制复制带来的开销。所以,当一个消息要发给多个进程,特别是协议数据(发给前端也要先转成二进制),可以先转成二进制再发送。结束语
文章到这里就结束了,这是我做 Erlang 游戏开发经验总结的一些经验,后续,我还会找时间总结更多的开发经验。最后呢,建议大家少上复制网站,如红黑联盟,这些网站复制了还会把文章来源网址删了,然后给了搜索引擎几个钱就排到前面去了。这样带来的问题是,文章我一开始写错了,但后来改过来了,这些网站是不会更新的,看到的人还以为原来的内容是对的。
最后补充下,庆亮同学在知乎上提到的 erlang 游戏开发的情况:
1. 捷游的梦幻飞仙在线人数峰值过了 4700(不分线、回合制)
2. 明朝的仙落凡尘在线人数峰值到了 4300(不分线、ARPG)
有兴趣的同学不妨看看这篇知乎讨论, 为什么一些网页游戏喜欢用Erlang做服务端
参考:
[1] http://blog.csdn.net/mycwq/article/details/50939354
[2] http://www.kongqingquan.com/archives/221
-
开发经验和屁股的关系
2012-03-17 08:39:32昨晚为CSDN俱乐部的同学们做了一个讲座《微博开发、云平台及一个微博...按照预先的准备,要讲如何在校积累开发经验,突然冒出了批评某些官员“屁股决定脑袋”的观点,也就将屁股和开发经验放在一起发挥了一下。 当昨晚为CSDN俱乐部的同学们做了一个讲座《微博开发、云平台及一个微博应用开发的简单方案》。已经用屏幕录相机记录下来了,不想讲完一边和同学聊着,一边收拾,直接关机,教室中带有保护卡的电脑自然不给面子,录相文件就此完蛋。
讲座中,难免要对同学们的学习做些指导。按照预先的准备,要讲如何在校积累开发经验,突然冒出了批评某些官员“屁股决定脑袋”的观点,也就将屁股和开发经验放在一起发挥了一下。
当讲到了为什么可以尝试微博应用开发,我讲了三点:好玩、就业、创业,提纲如下:
和同学们分析如何达到职位的要求。其中,最令人纠结的可能就是“两年以上开发经验”的问题。听到过不少同学的抱怨:“用人单位招应届毕业生,还要开发经验,坑的什么爹?”同学们的这种声音,似乎有道理。但细思量,这是一种典型的屁股决定论:屁股坐在大学校园中,还能有开发经验?
我接触过不少的同学,他们真的是在校时就拥有了开发经验的。在校期间,利用可以支配的时间,选择合适的切入点,同学们完全可以开展课外的学习。学IT相关专业的,这种课外学习,一定是要结合实际,要奔着开发而去的,开发经验由此而来。其实,由于在校期间能够自由选择,开发经验所涉及的领域、层次可以更广些,多变些,随着自己的兴趣走。这个定在校园中的腚,在开发经验积累中还是有其优势的。
开发要面向实际,面向生产一线,身在校园中,这一点如何做到?放在其他行业可能真是障碍。但在IT界,我们有的是优势。放眼整个行业,开源、共享、开放平台、外包,种种不受地域、时间、身份的机会,以各种各样的形式呈现在我们的面前。例如,Web开发、移动应用,门槛不是很高,同学们完全可以借助各种资源将自己的课外学习安排的有声有色,由做案例教程中的应用开始,到做出属于自己(最好是一个小的团队)的作品来。甚至,在不少场合,开发出的应用可以直接在互联网中发布,实现赢利的。这种模式在多年前似乎是个奇迹,但在网络发达的今天,在这样一个开放的世界中,应该是一个自然的事情了。
注意到一些公司(尤其是大公司)的表述,要的是“开发经验”,而不是“工作经验”。没有讲开发应该是在哪儿开发的,为什么我们自己都不能接受在校园中积累开发经验的观点呢?当你在求职面试时,将自己在互联网中已经运行良好的作品呈现给用人单位,谁还会在乎这是几年的开发经验呢?当看到两年、三年的表述时,也千万不要掰着手指数自己几年了。有人开发了十年也就那水平,而有人一个月就能牛起来。人和人不一样,不承认不行。此语可能引出一些人的消极,看人家某某某,牛,我就不行。何不换种思维想问题:他能做,我为何不能?我现在不能,他能了,区别何在?我的应对方法何在?我没有方法,是否观察并仿效他,逐渐找到自己的节奏和方法?Everyone can cook. (《料理鼠王》中的名言,我喜欢。)不在乎能不能,只在于做不做。在校学习期间,同学们也正好处在一个可塑性非常强的时期,我给自己改变的机会,要倾力实施这个改变。
实际用人单位,尤其是企业,真没有把“两年以上开发经验”太放在心上,似乎更在乎有个借口,将那些读了几年死书的人挡在门外。请看大量招聘要求中的最后一条:欢迎优秀应届毕业生加入。应届毕业生有的是优势,只在于你是否优秀。这个优秀也并非是门门功课90分以上。具体标准,不言自明。
反观有些人,在校没有投入开发经验的积累,出了校门做了些杂事。如果真的不愿从事开发或者有机会做其他事情也倒罢了,只是有些人等来了两年,却没有积累上经验。大家想想,在“两年以上开发经验”中,是“两年”重要,还是“开发经验”重要?
所以最重要的是尽快地投入,将自己的课外时间个性化地安排起来。如果做起来了,大学里有的是机会;反之,日子也就这样一天天地度过。
屁股坐在了大学校园里,培养方案中规定的课程是要学的,非富的课余生活也是要的,对IT学生,开发经验也是可以积累的。只是需要同学们有一颗不断求变的心,抓住有利于你健康发展的机会。
这么说来,屁股在哪的问题,对开发经验并无决定性的意义。=================== 迂者 贺利坚 CSDN博客专栏================= |== IT学子成长指导专栏 专栏文章的分类目录(不定期更新) ==| |== C++ 课堂在线专栏 贺利坚课程教学链接(分课程年级) ==| |== 我写的书——《逆袭大学——传给IT学子的正能量》 ==| ===== 为IT菜鸟起飞铺跑道,和学生一起享受快乐和激情的大学 =====
-
ONVIF开发经验总结
2016-05-10 15:19:51学习ONVIF技术也有一个月了,实现了发现网络摄像机、获取设备信息、获取RTSP流地址并播放RTSP视频这些工作,借鉴了很多网上的大牛的开发经验,主要借鉴的有两个:http://my.csdn.net/ghostyu、...但是我在这里做一学习ONVIF技术也有一个月了,实现了发现网络摄像机、获取设备信息、获取RTSP流地址并播放RTSP视频这些工作,借鉴了很多网上的大牛的开发经验,主要借鉴的有两个:http://my.csdn.net/ghostyu、http://gaohtao.blog.163.com/blog/static/58241823201362334222265/、从这两个大牛的博客里学到了很多东西,但是我在这里做一个我自己的总结。
ONVIF开发主要是分为client端和server端,如果是实现基于ONVIF的client端开发,主要的工作就是调用soapClient.c里面的函数来实现,这部分工作的难度就是配置各种需要的结构体信息。ONVIF官网资料里面我没有找到具体的关于配置这些信息的资料,如果大家找到了麻烦跟我分享下。我自己的做法是借助ONVIF官方的ONVIF Device Test Tool,通过抓包软件获取这个工具发出的SOAP消息,根据SOAP消息就可以配置出需要的结构体信息,这样就可以很容易的开发了。
如果是基于ONVIF的server端的开发,首先是配置一个socket来通信,socket的配置就不多说了,然后监听soapServer.c里面的soap_serve(struct soap *soap)函数,这个函数根据收到的信息,调用soap_serve_request(struct soap *soap)函数,可以解析出收到的信息要完成的要求。然后把要求的内容发送出去,发送出去调用的是soapClient.c里面的函数,这和client端类似。
我在接下来的几篇博客里面把ONVIF Device Test Tool发送的SOAP消息贴出来。
probe.xml
<?xml version="1.0" encoding="utf-8"?> <Envelope xmlns:tds="http://www.onvif.org/ver10/device/wsdl" xmlns="http://www.w3.org/2003/05/soap-envelope"> <Header> <wsa:MessageID xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing"> uuid:e2726d13-1db9-4892-9216-7cc5a7e9f173 </wsa:MessageID> <wsa:To xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing"> urn:schemas-xmlsoap-org:es:2005:04:discovery </wsa:To> <wsa:Action xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing"> http://schemas.xmlsoap.org/ws/2005/04/discovery/Probe </wsa:Action> </Header> <Body> <Probe xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://schemas.xmlsoap.org/ws/2005/04/discovery"> <Types> tds:Device </Types> <Scopes /> </Probe> </Body> </Envelope>
-
Unity游戏开发经验点滴
2019-10-07 18:26:03游戏开发中会遇到各种各样的问题,只有经历过了才会深刻,这里就游戏开发的一些经验点滴给读者分享一下,先从代码说起。 从事IT行业这么多年了,写过或者看过很多代码,有的项目代码写的不错的,大家经过多年的努力... -
BAE 百度开发经验谈
2015-05-23 10:20:30BAE 百度开发经验谈 1.及时查看BAE通告 例如:BAE2.0已经在2015年3月下线,开发时还根据2.0版本文档,怎么能正常使用呢? BAE2.0迁移BAE3.0说明 ... -
只有2~3年左右的开发经验,为什么年薪就可以达到50万+?
2017-12-22 19:16:36只有2~3年左右的开发经验,为什么年薪就可以达到50万+? -
[分布式]到底啥是分布式系统开发经验
2019-03-28 10:46:325、一句话总结:什么是分布式系统设计和开发经验 6、补充说明:中间件系统及大数据系统 前言 现在有很多Java技术方向的同学在找工作的时候,肯定都会去招聘网站上找职位投递简历。 但是在很多职位JD上往往会... -
IM开发经验
2015-08-06 20:26:05已经连续写了7天的代码了。现在应该可以叫做有点经验的开发人员了。 脑子有点乱乱的,明天再写。。。 -
-
多年大数据开发经验总结
2018-08-24 10:02:23多年工作经验总结 初入行,搞大数据开发。得高人指点,先学mapreduce,不足一年,tez兴,后入此道。朝夕不倦,发愤图强,才能略知一二。无奈后浪推前浪,tez被spark拍在沙滩上,遂投spark之怀。继而抖擞精神,奋袂... -
微信小程序开发经验总结(五)
2017-09-19 11:24:55微信小程序开发经验总结 常用组件button image input swiper scroll-view form 常用API phone loading Storage -
软件开发经验总结(容错性)
2018-03-09 16:00:4420180206 软件开发经验总结(容错性)容错性:容错性是指软件检测应用程序所运行的软件或硬件中发生的错误并从错误中恢复的能力,通常可以从系统的可靠性、可用性可测性等几个方面来衡量。可靠性对于火箭发射之类关键... -
嵌入式GPS导航系统开发经验
2011-01-21 14:00:00嵌入式GPS导航系统开发经验 一.地图数据篇 1.地图数据引擎与界面显示的代码分离; 2.地图数据与符号显示也就是地图数据显示分离(类似XML与XSL,XSLT关系); 3.地图数据要分层:如街道,国道,小区,... -
-
震惊!GitHub 上教人写烂代码的项目火了...
-
竞斗云2.0官方固件-备份
-
牛客NC13331 城市网络 树上倍增
-
duilib(Troy)------Button下划线可点击实例
-
visual c++ vc修改文件属性中的创建时间,修改时间,访问时间.zip
-
3DEC学习资料.zip
-
自如房源爬取及简单分析——python语言实现
-
(新)备战2021软考信息安全工程师顺利通关套餐
-
基于OpenCV的视频道路车道检测
-
C#文件传输、Socket通信、大文件断点续传
-
Cocos Creator游戏开发-连连看 (接入腾讯优量汇广告)
-
21年新接口自动化测试视频postman教程 零基础接口测试
-
2分钟演示开发CTP行情源码.rar
-
(新)备战2021软考网络工程师终极解密培训套餐
-
ArcGIS Pro2.6和ArcGIS Enterprise学习
-
算法思想-回溯、分治、动态规划的关系
-
C++:图书管理系统
-
【数据分析-随到随学】量化交易策略模型
-
3-4Java数组----数组中涉及到的常见算法(7)--快速排序
-
win10右下角蓝牙不见了怎么办