<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>张文杰的博客 &#187; SIP</title>
	<atom:link href="http://zhangwenjie.net/archives/tag/sip/feed" rel="self" type="application/rss+xml" />
	<link>http://zhangwenjie.net</link>
	<description>技术、生活博客</description>
	<lastBuildDate>Mon, 24 Oct 2011 14:23:44 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
<atom:link rel="hub" href="http://pubsubhubbub.appspot.com"/><atom:link rel="hub" href="http://superfeedr.com/hubbub"/>		<item>
		<title>关于暂停PJSIP开发指南中文翻译的通知</title>
		<link>http://zhangwenjie.net/archives/289</link>
		<comments>http://zhangwenjie.net/archives/289#comments</comments>
		<pubDate>Thu, 25 Feb 2010 13:34:17 +0000</pubDate>
		<dc:creator>zhangwenjie</dc:creator>
				<category><![CDATA[Windows]]></category>
		<category><![CDATA[pjsip]]></category>
		<category><![CDATA[PJSIP开发指南]]></category>
		<category><![CDATA[SIP]]></category>

		<guid isPermaLink="false">http://zhangwenjie.net/?p=289</guid>
		<description><![CDATA[前一段时间，我曾经翻译过PJSIP Dev's Guide，中文叫《PJSIP开发指南》，具体可以从这里下载到PDF文件。当时只翻译到第六章，这一段时间也在翻译其它的部分。由于自己近期在研究SIP协议，看到此文档后，决定翻译成中文，方便自己学习，也为学习SIP的朋友提供一些帮助。]]></description>
			<content:encoded><![CDATA[<p>　　前一段时间，我曾经翻译过PJSIP Dev&#8217;s Guide，中文叫《PJSIP开发指南》，具体可以从<a class="wp-caption" title="PJSIP中文开发指南" href="http://zhangwenjie.net/archives/280.html" target="_blank"><span style="color: #ff0000;">这里</span></a>下载到PDF文件。当时只翻译到第六章，这一段时间也在翻译其它的部分。由于自己近期在研究SIP协议，看到此文档后，决定翻译成中文，方便自己学习，也为学习SIP的朋友提供一些帮助。</p>
<p>　　不过，今天发生的一件事，让我决定不再翻译其余的部分。这件事起因于我和PJSIP的作者Benny Prijono的一封邮件，见下图：</p>
<p>　　</p>
<div id="attachment_290" class="wp-caption aligncenter" style="width: 616px"><a href="http://zhangwenjie.net/wp-content/uploads/2010/02/mail.png"><img class="size-full wp-image-290 " title="PJSIP开发指南邮件" src="http://zhangwenjie.net/wp-content/uploads/2010/02/mail.png" alt="PJSIP开发指南邮件" width="606" height="391" /></a><p class="wp-caption-text">PJSIP开发指南</p></div>
<p>　　我给Benny Prijono必了一封邮件询问关于翻译PJSIP开发指南的版权问题，希望作者能同意。很快，Benny回邮件了，非常爽快同意了翻译工作，并且会支持此项目工作。但是作者指出了一个比较严重的问题，这是我没有注意且很沮丧的问题。</p>
<p>　　作者指出的问题是：此份PJSIP Dev&#8217;s Guide是在PJSIP version 0.5时写成的，现在已经到了1.5.5版本了，同时作者指出,”While most of the key concepts stays the same,some of the details may have changed”,以至于”the concern is that you&#8217;re spending a lot of time for something that is not relevant anymore”。也就是说尽管大部分关键概念保持不变，但也有一部分内容改变了，因此很有可能在许多不相关的东西上花费了大量时间。</p>
<p>　　在最后，作者说：”So I would say it&#8217;ll be more effective if we update the PDF doc first,then translate it to Chinese. Unfortunately we can&#8217;t say when we will have time to do this either.”就是说作者希望在先更新了文档后再做翻译工作。但作者又说他他不好说什么时候能有时间做这个工作。</p>
<p>　　看了这封邮件后，我觉得没有必须再翻译这份文档了。主要原因是<span style="color: #ff0000;">它太旧了，很多概念已经变化了，翻译出来会对使用它的朋友产生误导结果</span>。<span style="color: #000000;">对于已经下载了1-6章的朋友，请仔细研究以确认哪些内容可用，哪些内容已经过时。谢谢！</span></p>
<p><span style="color: #000000;">　　不过，现在我仍在研究PJSIP的源代码，以后会不时将自己的心得分享给大家，请大家多多关注。</span></p>
<p><span style="color: #000000;">　　</span></p>
<p>　　原创文章如转载，请注明：转载自<a title="张文杰的博客" href="http://zhangwenjie.net/">张文杰的博客</a> [ <a title="张文杰的博客" href="http://zhangwenjie.net/">http://zhangwenjie.net</a> ]</p>
<p>　　本文链接地址：<a href="http://zhangwenjie.net/archives/289.html">http://zhangwenjie.net/archives/289.html</a></p>
]]></content:encoded>
			<wfw:commentRss>http://zhangwenjie.net/archives/289/feed</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>PJSIP开发指南中文版(1-6章)</title>
		<link>http://zhangwenjie.net/archives/280</link>
		<comments>http://zhangwenjie.net/archives/280#comments</comments>
		<pubDate>Mon, 08 Feb 2010 03:17:48 +0000</pubDate>
		<dc:creator>zhangwenjie</dc:creator>
				<category><![CDATA[Windows]]></category>
		<category><![CDATA[pjsip]]></category>
		<category><![CDATA[SIP]]></category>

		<guid isPermaLink="false">http://zhangwenjie.net/?p=280</guid>
		<description><![CDATA[PJSIP开发指南详细解释了大多数PJSIP对象的概念、关系("类图")以及其他描述；此文档也可以作为PJSIP协议栈的通用设计文档。点这里下载PJSIP开发指南中文版(1-6章)。]]></description>
			<content:encoded><![CDATA[<p>     PJSIP是一个SIP协议栈，它支持多种SIP的扩展功能，下面列出其重要的几种优点：<br />
   1.高度的可移殖性 <br />
      只需简单的编译一次，它能够在多种平台上运行（所有Windows 系统列, Windows Mobile, Linux, 所有Unix 系列, MacOS X, RTEMS, Symbian OS, 等等）。 </p>
<p>2.极小的内存需求 <br />
      完全实现SIP的功能只需要150K的内存空间，这使得PJISP不仅仅是嵌入开发的理想平台，并且实用于那些内存运行于极小内存平台的应用，这也意味着极小的用户下载时间。</p>
<p> 3.高效的性能 <br />
      这意味着极小的CPU运算需求下能同时实现更多的通话。</p>
<p>4.支持多种SIP功能及扩展功能 <br />
      多种SIP功能和扩展功能，例如多人会话，事件驱动框架，会话控制（presence），即时信息，电话传输，等等在库文件里得以实现。 </p>
<p>5.丰富文档资料 <br />
      对于软件开发人员来说，文档资料从来都是多多益善，因此我们要求PJSIP开发人员提供了大量的极有价值的文档资料供大家使用。</p>
<p>      PJSIP开发指南详细解释了大多数PJSIP对象的概念、关系(“类图”)以及其他描述；此文档也可以作为PJSIP协议栈的通用设计文档。点<a class="wpGallery" title="PJSIP开发指南中文版1-6章" href="http://zhangwenjie.net/wp-content/uploads/2010/02/PJSIP开发指南中文版1-6章.pdf" target="_self">这里</a>下载PJSIP开发指南中文版(1-6章)。</p>
<p>   首发张文杰的博客:http://zhangwenjie.net （转载请保留，谢谢。） 本文地址:http://zhangwenjie.net/archives/280.html</p>
]]></content:encoded>
			<wfw:commentRss>http://zhangwenjie.net/archives/280/feed</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>PJSIP开发指南翻译系列之第二章</title>
		<link>http://zhangwenjie.net/archives/274</link>
		<comments>http://zhangwenjie.net/archives/274#comments</comments>
		<pubDate>Wed, 03 Feb 2010 14:28:41 +0000</pubDate>
		<dc:creator>zhangwenjie</dc:creator>
				<category><![CDATA[Windows]]></category>
		<category><![CDATA[pjsip]]></category>
		<category><![CDATA[SIP]]></category>

		<guid isPermaLink="false">http://zhangwenjie.net/?p=274</guid>
		<description><![CDATA[模块框架是在PJSIP程序中的各个软件组件中派发SIP消息的主要方法。PJSIP中的所有软件组件，像事务层(transaction layer)和对话层(dialog layer)，都以模块的方式来实现。如果没有模块，核心协议栈(pjsip_endpoint和transport)根本不知道如何去处理SIP消息。]]></description>
			<content:encoded><![CDATA[<p>　　<span style="color: #ff0000;">说明：此系列文章是根据PJSIP Dev&#8217; Guide文档翻译而来，所有版权归原作者所有。这里的翻译仅仅是用作学习、交流等用途。本人近期在学习SIP，鉴于网上SIP资料比较少，自己就翻译了此文章，限于自己的SIP及英语水平，错误之处在所难免，希望高手多多指教，也希望有此爱好者一起学习交流。</span></p>
<h1 style="text-align: center;">第二章 模块</h1>
<p>模块框架是在PJSIP程序中的各个软件组件中派发SIP消息的主要方法。PJSIP中的所有软件组件，像事务层(transaction layer)和对话层(dialog layer)，都以模块的方式来实现。如果没有模块，核心协议栈(pjsip_endpoint和transport)根本不知道如何去处理SIP消息。</p>
<p>模块框架是基于简单但强大的接口抽象。对到来的消息，endpoint(pjsip_endpoint)从优先级高的模块开始向所有的模块派发消息，直到其中一个模块告诉框架它自己处理了此消息。对出去的消息，endpoint在消息真正开始发送到网络之前派发这些消息到所有模块，允许所有模块有机会对消息做最后的修改。</p>
<h2>2.1模块特性</h2>
<h3>2.1.1模块声明</h3>
<p>模块接口是在&lt;pjsip/sip_module.h&gt;中声明的：</p>
<div id="attachment_275" class="wp-caption aligncenter" style="width: 568px"><a href="http://zhangwenjie.net/wp-content/uploads/2010/02/m.jpg"><img class="size-full wp-image-275" title="模块声明" src="http://zhangwenjie.net/wp-content/uploads/2010/02/m.jpg" alt="" width="558" height="267" /></a><p class="wp-caption-text">模块声明</p></div>
<p>在此声明中，所有的函数指针都是可选的；如果没有指定这些函数指针，那么他们将被认为是成功返回值的。</p>
<p>其中的四个函数指针，load、start、stop、unload是由endpoint调用来控制模块的状态。下面的图显示了模块状态的生命期：</p>
<div id="attachment_276" class="wp-caption aligncenter" style="width: 568px"><a href="http://zhangwenjie.net/wp-content/uploads/2010/02/s.jpg"><img class="size-full wp-image-276" title="状态图" src="http://zhangwenjie.net/wp-content/uploads/2010/02/s.jpg" alt="状态图" width="558" height="112" /></a><p class="wp-caption-text">状态图</p></div>
<p>on_rx_request()和on_rx_response()函数指针是模块从endpoint(pjsip_endpt)或其它模块接受SIP消息的主要方法。这些回调函数的返回值是很重要的。如果回调函数返回非0值，从语义上意味着这个模块处理了这个消息；这个情况下，endpoint将停止向其它模块派发此消息。在节2.1.3 <strong>模块对到来消息的处理</strong>中会详细描述这个问题。</p>
<p>on_tx_request()和on_tx_response()函数指针在消息传送之前由传输管理器来调用。这使一些类型的模块(如sigcomp、message signaling)有机会对消息做最后的修改。所有的模块<strong>必须</strong>返回PJ_SUCCESS(如0状态)，否则消息传输将会取消。在节2.1.4 <strong>模块对外出消息的处理</strong>中会详细描述这个问题。</p>
<p>on_tsx_state()用来在每次事务状态改变时接受通知消息。事务状态改变可能由接受到消息、消息发了出去、定时器消息、传输错误事件等引起。更多关于这个回调函数将在节2.1.5“事务用户和状态回调”中描述。</p>
<h3>2.1.2模块优先级</h3>
<p>模块优先级指定了哪个模块将被优先调用来处理回调函数的顺序。拥有高优先级的模块(优先级的数字较小)的on_rx_request()和on_rx_response()将先被调用，它的on_tx_request()和on_tx_response()将最后被调用。</p>
<p>下面表出了标准的可设置的模块优先级：</p>
<div id="attachment_277" class="wp-caption aligncenter" style="width: 568px"><a href="http://zhangwenjie.net/wp-content/uploads/2010/02/p.jpg"><img class="size-full wp-image-277" title="优先级" src="http://zhangwenjie.net/wp-content/uploads/2010/02/p.jpg" alt="优先级" width="558" height="136" /></a><p class="wp-caption-text">优先级</p></div>
<p><strong>记住：较低的优先级数字意味着较高的优先级。</strong></p>
<p>优先级PJSIP_MOD_PRIORITY_TRANSPORT_LAYER是由传输管理器使用的。这个优先级当前只是用于控制消息的传输，比如比这个优先级低的模块(也就是优先级数字较高)，它的on_tx_request()/on_tx_response()函数将在消息被传输层(transport layer)处理之<strong>前</strong>被调用；而有高优先级的模块的on_tx_request()/on_tx_response()函数将在消息被传输层(transport layer)处理之<strong>后</strong>被调用。参见2.1.4<strong>模块对外出消息的处理</strong>以获得更多信息。</p>
<p>PJSIP_MOD_PRIORITY_TSX_LAYER是被传输层(transport layer)模块使用的优先级。传输层(transport layer)将吸收所有属于同一个事务的到来消息。</p>
<p>PJSIP_MOD_PRIORITY_UA_PROXY_LAYER是由UA(如dialog framework)或代理层(proxy layer)使用的优先级。UA层吸收所有属于同一个对话集(dialog set)的到来消息(这也意味着有分歧的回应)。(<strong>这里的翻译可能不准确：this means forked responses as well</strong>)。</p>
<p>PJSIP_MOD_PRIORITY_DIALOG_USAGE由dialog usages使用。当前PJSIP实现了两种类型的dialog usages：邀请会话(INVITE session)和事件订阅会话(event subscription session)(包括REFER订阅)。Dialog Usage吸收所有在同一个对话中属于一个特定会话的消息。(The dialog usage absorbs messages inside a dialog that belong to particular session)。</p>
<p>PJSIP_MOD_PRIORITY_APPLICATION是典型应用程序模块想使用transactions、dialogs、及dialog usages时可使用的合适优先级值。</p>
<p>　　首发张文杰的博客:http://zhangwenjie.net（转载请保留，谢谢）（第二章翻译未结束，待续）</p>
]]></content:encoded>
			<wfw:commentRss>http://zhangwenjie.net/archives/274/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>PJSIP开发指南翻译系列之第一章</title>
		<link>http://zhangwenjie.net/archives/266</link>
		<comments>http://zhangwenjie.net/archives/266#comments</comments>
		<pubDate>Wed, 03 Feb 2010 14:08:46 +0000</pubDate>
		<dc:creator>zhangwenjie</dc:creator>
				<category><![CDATA[Windows]]></category>
		<category><![CDATA[pjsip]]></category>
		<category><![CDATA[SIP]]></category>

		<guid isPermaLink="false">http://zhangwenjie.net/?p=266</guid>
		<description><![CDATA[此系列文章是根据PJSIP Dev' Guide文档翻译而来，所有版权归原作者所有。这里的翻译仅仅是用作学习、交流等用途。。。]]></description>
			<content:encoded><![CDATA[<p><span style="color: #ff0000;">　　说明：此系列文章是根据PJSIP Dev&#8217; Guide文档翻译而来，所有版权归原作者所有。这里的翻译仅仅是用作学习、交流等用途。本人近期在学习SIP，鉴于网上SIP资料比较少，自己就翻译了此文章，限于自己的SIP及英语水平，错误之处在所难免，希望高手多多指教，也希望有此爱好者一起学习交流。</span></p>
<p><span style="color: #ff0000;">　　</span></p>
<h1 style="text-align: center;">第一章 通用设计</h1>
<h2>1.1架构</h2>
<h3>1.1.1通信图</h3>
<p>下面的示意图显示了(SIP)消息是如何在PJSIP组件之间来回传递的。</p>
<div id="attachment_270" class="wp-caption aligncenter" style="width: 568px"><a href="http://zhangwenjie.net/wp-content/uploads/2010/02/11.jpg"><img class="size-full wp-image-270" title="图表1：协作图" src="http://zhangwenjie.net/wp-content/uploads/2010/02/11.jpg" alt="图表1：协作图" width="558" height="337" /></a><p class="wp-caption-text">图表1：协作图</p></div>
<h3>1.1.2类图</h3>
<p>下面的示意图显示了“类图”:</p>
<div id="attachment_269" class="wp-caption aligncenter" style="width: 568px"><a href="http://zhangwenjie.net/wp-content/uploads/2010/02/2.jpg"><img class="size-full wp-image-269" title="图表2：类图" src="http://zhangwenjie.net/wp-content/uploads/2010/02/2.jpg" alt="图表2：类图" width="558" height="363" /></a><p class="wp-caption-text">图表2：类图</p></div>
<h2>1.2 Endpoint</h2>
<p>SIP协议栈的核心就是SIP Endpoint，由不透明的类型pjsip_endpoint来表示。Endpoint具体有以下的属性和职责：</p>
<ul>
<li>它有内存池工厂，为所有SIP组件分配内存池；</li>
<li>它有定时器堆实例，为所有SIP组件调度定时器；</li>
<li>它有传输管理器实例。传输管理器有SIP传输商品，且控制消息解析和显示；</li>
<li>它拥有单实例的PJSIP ioqueue类型。Ioqueue是用来分派网络事件的proactor 模式；</li>
<li>它提供线程安全的轮询功能，这样应用程序中的线程可以轮询定时器和网络事件(PJSIP本身不创建任何线程)；</li>
<li>它管理模块。PJSIP模块是扩展协议栈的主要方法，而协议栈扩展并不局限于消息的解析和显示；</li>
<li>它从传输管理器接受到来的消息，并将这些消息分派到模块。</li>
</ul>
<p>一些基本功能将会在下面的部分讲述，其余的会在后面的章节讲述。</p>
<h3>1.2.1 内存池的分配和释放</h3>
<p>SIP组件的所有内存分配都是通过endpoint来完成的，以在整个应用程序中保证线程安全及强制策略的一致性。可应用策略的一个例子是内存池缓存，这里未使用的内存将保留以备将来使用，而不是释放。</p>
<p>Endpoint提供以下方法来分配和释放内存池：</p>
<pre lang="C++">	pjsip_endpt_create_pool()
	pjsip_endpt_release_pool()</pre>
<p>当创建endpoint时(使用pjsip_endpt_create())，应用程序必须指定endpoint使用的内存池工厂。Endpont将在自己的生命期内保持此内存池工厂的指针，并由此来分配和释放内存池。</p>
<h3>1.2.2定时器管理</h3>
<p>Endpoint保留一个单实例的定时器堆来管理定时器。所有定时器的创建和所有SIP组件的定时器调度皆由endpoint来完成。</p>
<p>Endpoint提供以下方法来管理定时器：</p>
<pre lang="c++">	pjsip_endpt_schedule_timer()
	pjsip_endpt_cancel_timer()</pre>
<p>当endpont的轮询函数被调用时，endpoint将检查定时器是否过期。</p>
<h3>1.2.3轮询协议栈</h3>
<p>Endpoint提供了一个单一的函数调用(pjsip_endpt_handle_events())来检查定时器和网络事件的出现。应用程序可以指定它将等待多长时间后去检查这些事件的出现。</p>
<p>PJSIP协议栈从不创建线程。整个协议栈中的代码执行完全代表着应用程序创建的线程，无论是在一个API被调用时，或是应用程序调用轮询方法时。</p>
<p>轮询功能是可以基于定时器堆的内容来优化等待时间的(The polling function is also able to optimize the waiting time based on the timer heap’s contents.)。例如，如果它知道一个定时器将在下一个5秒过期，它等待网络事件的时间将不会超过这5秒；在无网络事件出现时这样做将无必要地延长等待时间。当然定时器的精度在每个平台上都不同。</p>
<h2>1.3线程安全和线程复杂性</h2>
<h3>1.3.1线程安全</h3>
<p>线程安全的讨论是一个相当复杂的事情。但是，比较幸运的是，下面的设计原则在整个协议栈中的一致应用：</p>
<p><strong>对象<span style="color: #ff0000;">必须是</span>线程安全的；而数据结构<span style="color: #ff0000;">必须不是</span>线程安全的。</strong></p>
<p>具体到现在的话题，很自然，对象和简单数据结构的区别不是非常清楚。但是一些例子将会使你对此更明白一点。</p>
<p>数据结构的例子有：</p>
<ul>
<li>PJSIP的数据结构，如链表(lists)、数组(arrays)、哈希表(hash tables)、字符串(strings)、以及内存池。</li>
<li>SIP的消息元素，如URLs、header fields、以及SIP消息。</li>
</ul>
<p>这些数据结构不是线程安全的；这些数据结构的线程安全由包含它们的对象来保证。如果使数据结构也线程安全，这将严重影响协议栈的性能，并消耗操作系统的资源。</p>
<p>相比之下，SIP对象<strong>必须是</strong>线程安全的。我们称之为对象的例子有：</p>
<ul>
<li>PJLIB对象，如ioqueue</li>
<li>PJSIP对象，如endpoint、transactions、dialogs、dialog usages,等等</li>
</ul>
<h3>1.3.2线程复杂性</h3>
<p>使事情变糟的是，一些对象在头文件中暴露了它们的声明(例如pjsip_transaction和pjsip_dialog)。尽管这些对象暴露的API是保证线程安全的，应用程序代码在访问这些数据结构之前仍然<strong>必须</strong>在对象的互斥变量(mutex)上调用pj_mutex_lock()来获取正确的锁。</p>
<p>使事情变得更糟的是，一个dialog提供不同的API来锁定dialog。这样应用程序<strong>应该</strong>调用pjsip_dlg_inc_lock()和pjsip_dlg_dec_lock()，而不是pj_mutex_lock()和pj_mutex_unlock()。这两种方法的区别是，dialog的inc/dec锁保证dialog不会在函数调用过程中被销毁；不然由于gialog已经被销毁，会使pj_mutex_unlock()崩溃。</p>
<p>考虑下面的例子：</p>
<pre lang="c++">	pj_mutex_lock(dlg-&gt;mutex);
	psip_dlg_end_session(dlg,…);
	pj_mutex_unlock(dlg-&gt;mutex);</pre>
<p>在上面的例子中(假想的)，程序<strong>可能</strong>会在第三行代码处崩溃，因为psip_dlg_end_session()有可能在一定情况下销毁dialog。例如，出去的初始INVITE事务没有得到任何回应，因此事务会马上被销毁，造成dialog也被销毁。Dialog的inc/dec锁通过临时增加dialog会话的计数器来避免这个问题，因而在end_session()中dialog不会被销毁。Dialog可能会在dec_lock()方法中销毁。因此正确锁定dialog的顺序应该像这样：</p>
<pre lang="c++">	pj_mutex_lock(dlg-&gt;mutex);
	psip_dlg_end_session(dlg,…);
	pj_mutex_unlock(dlg-&gt;mutex);</pre>
<p>最后，真正使情事变糟的是，锁定的顺序必须正确，否则可能发现死锁。例如，应用程序在dialog中想既锁定dialog，又锁定transaction，应用程序必须在获取transaction锁之前获取dialog锁，否则当另一个线程正在以相反的顺序获取相同dialog和transaction的锁时，死锁将会发生。</p>
<h3>1.3.3解决方法(The Relief)</h3>
<p>幸运的是，应用程序很少需要直接获取对象的锁。因此几乎不会出现以上所述的问题。</p>
<p>如果可用，应用程序应该使用对象的API 来存取对象。由于会对对象进行检查，对象的API保证加锁的正确性及避免死锁和崩溃的出现。</p>
<p>当一个对象调用应用程序的回调函数时(如dialog和transaction)，这此回调函数在对象的锁获取后正常调用，因此应用程序可以安全访问对象的数据结构而不用获取对象的锁。</p>
<p>　　首发张文杰的博客:http://zhangwenjie.net（转载请保留，谢谢）（未完待续）</p>
]]></content:encoded>
			<wfw:commentRss>http://zhangwenjie.net/archives/266/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>SIP协议之ReSIProcate环境搭建</title>
		<link>http://zhangwenjie.net/archives/223</link>
		<comments>http://zhangwenjie.net/archives/223#comments</comments>
		<pubDate>Thu, 07 Jan 2010 14:25:27 +0000</pubDate>
		<dc:creator>zhangwenjie</dc:creator>
				<category><![CDATA[Windows]]></category>
		<category><![CDATA[ReSIProcate]]></category>
		<category><![CDATA[SIP]]></category>

		<guid isPermaLink="false">http://zhangwenjie.net/?p=223</guid>
		<description><![CDATA[文章描述了使用开源ReSIProcate搭建了一个简单的SIP测试环境的步骤。。。]]></description>
			<content:encoded><![CDATA[<p>　　这几天在研究SIP协议，并使用开源ReSIProcate搭建了一个简单的测试环境。现在分享给大家，希望对同样研究SIP协议的朋友有一些帮助。</p>
<ul>
<li>首先下载resiprocate的最新版本:目前是resiprocate-1.6。</li>
<li>取消resiprocate-1.6目录的只读属性,同时 删除resiprocate-1.6目录下的.svn文件夹。此文件夹是隐藏的，需要在Windows系统中设置一下让它显示出来。</li>
<li>然后使用Visual Studio 2008打开resiprocate-1.6下的reSIProcate_9_0.sln解决方案。 </li>
<li>右击reSIProcate_9_0解决方案下的resiprocate项目，选择重新生成，等编译完成后，会在resiprocate-1.6\repro\Debug下生成repro.exe可执行文件。</li>
<li> 拷贝resiprocate-1.6\contrib\popt\win32下的libiconv-2.dll、libintl-2.dll、popt1.dll三个dll文件到resiprocate-1.6\repro\Debug。即将libiconv-2.dll、libintl-2.dll、popt1.dll三个dll文件与repro.exe放到同一个目录下，否则repro.exe执行时会出错。</li>
<li> 启动一个命令行(控制台)窗口,导航到resiprocate-1.6\repro\Debug目录下，运行repro.exe文件。</li>
<li> 打开浏览器,输入地址：<a href="http://127.0.0.1:5080">http://127.0.0.1:5080</a>。可以看到登录页面：</li>
<li>点击登录链接，输入用户名和密码(均为admin)。出现设置页面。</li>
<li> 设置域名：如果是在局域网，域名直接设置为IP地址，如127.0.0.1。点击Add按钮添加域名。</li>
<li> 添加用户：这个比较简单，见图所示。注意填写密码。其它选项暂时可以不用去管。如此这样添加两个用户，方便下面对BasicCall项目进行测试。 </li>
<li>右击reSIProcate_9_0解决方案下的basicCall项目，选择重新生成，并设置为启动项目。等编译完成后，右击basicCall项目，选择属性，在弹出的basicCall属性页对话框中，设置basicCall项目的命令行参数。</li>
<li> 在basicCall项目中注释掉#define NO_REGISTRATION 1一句。并且，对main函数的开头做如下发动，将日志输出到文件中。</li>
<li> 运行basicCall项目，等程序运行结果后，会在resiprocate-1.6\resip\dum\test目录下看到basicCall.txt文件，可以对其进行分析。</li>
</ul>
<p>　　更详细的带图的步骤见这个文章:<a class="wpGallery" title="SIP协议之reSIProcate环境" href="http://zhangwenjiesoft.gbaopan.com/files/29bfc217d7d7429ca75ff27053a231a3.gbp" target="_blank">SIP协议之reSIProcate环境</a>。</p>
<p> 　　首发<a class="wp-caption-dd" title="张文杰的博客" href="http://zhangwenjie.net" target="_blank">张文杰的博客</a>:<a class="wp-caption-dd" title="张文杰的博客" href="http://zhangwenjie.net" target="_blank">http://zhangwenjie.net</a>(转载请保留)</p>
]]></content:encoded>
			<wfw:commentRss>http://zhangwenjie.net/archives/223/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>

