<?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"
	>

<channel>
	<title>IT时代</title>
	<atom:link href="http://www.oursit.com/feed" rel="self" type="application/rss+xml" />
	<link>http://www.oursit.com</link>
	<description>IT时代是记录现今(Linux,ajax,php,FLEX,actionscript,air,javascript,apache,mysql,服务器技术)比较流行的技术文档和实例，并与大家共同讨论各种技术的解决方案和IT的奥秘</description>
	<pubDate>Sat, 23 Jan 2010 02:38:14 +0000</pubDate>
	<generator>http://wordpress.org/?v=2.6.1</generator>
	<language>en</language>
			<item>
		<title>如何对memcache的数据(key-value)进行遍历操作</title>
		<link>http://www.oursit.com/archives/143.html</link>
		<comments>http://www.oursit.com/archives/143.html#comments</comments>
		<pubDate>Sat, 23 Jan 2010 02:33:56 +0000</pubDate>
		<dc:creator>Skylin</dc:creator>
		
		<category><![CDATA[memcache]]></category>

		<guid isPermaLink="false">http://www.oursit.com/?p=143</guid>
		<description><![CDATA[目前，用到memcache的公司和网站也越来越多。Memcache的客户端操作一般都只提供了get,set等简单的操作，这些操作都是非常高效的。   虽然memcache是个key-value存储的系统，但是在某些时候，我们可能需要遍历memcache的数据。(比如需要同步多台服务器中的memcache数据)]]></description>
			<content:encoded><![CDATA[<p><strong>stats命令</strong></p>
<p align="left">memcache的stats命令包括：</p>
<p align="left">
<div class="dp-highlighter">
<div class="bar">&nbsp;</div>
<ol start="1" class="dp-c">
<li class="alt"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; stats&nbsp;&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; stats&nbsp;reset&nbsp;&nbsp;&nbsp;&nbsp;</span></li>
<li><span>&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; stats&nbsp;malloc&nbsp;&nbsp;&nbsp;&nbsp;</span></li>
<li><span>&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; stats&nbsp;maps&nbsp;&nbsp;&nbsp;&nbsp;</span></li>
<li><span>&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; stats&nbsp;sizes&nbsp;&nbsp;&nbsp;&nbsp;</span></li>
<li><span>&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; stats&nbsp;slabs&nbsp;&nbsp;&nbsp;&nbsp;</span></li>
<li><span>&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; stats&nbsp;items&nbsp;&nbsp;&nbsp;&nbsp;</span></li>
<li><span>&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; stats&nbsp;cachedump&nbsp;slab_id&nbsp;limit_num&nbsp;&nbsp;&nbsp;&nbsp;</span></li>
<li><span>&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; stats&nbsp;detail&nbsp;[on|off|dump]&nbsp;&nbsp;&nbsp;&nbsp;</span></li>
</ol>
</div>
<div style="display: none;" class="php">1.        stats    2.        stats reset    3.        stats malloc    4.        stats maps    5.        stats sizes    6.        stats slabs    7.        stats items    8.        stats cachedump slab_id limit_num    9.        stats detail [on|off|dump]</div>
<link rel="stylesheet" type="text/css" href="/wp-content/plugins/fckeditor_for_wordpress/fckeditor/editor/plugins/highlighter/dp.SyntaxHighlighter/Styles/SyntaxHighlighter.css" /><strong>通过命令完成遍历</strong></p>
<p align="left">通过这些stats命令我们就可以完成memcache存储的内容的遍历，OK，下面我们通过telnet直接连接到memcache通过这些命令来完成相关的操作。 <br />
telnet到192.168.15.225（局域网测试机器）的memcache服务器</p>
<p align="left">
<div style="display: none;" class="php">telnet 192.168.15.225</div>
<p><img height="143" width="499" src="http://www.oursit.com/wp-content/uploads/ScreenShot00068.jpg" alt="" /></p>
<p align="left">执行stats items命令，可以看到出现 很多的items行。</p>
<p align="left"><img height="326" width="320" src="http://www.oursit.com/wp-content/uploads/ScreenShot00069.jpg" alt="" /></p>
<p align="left">执行stats cachedump 7 0命令。这里的7表示上面图中items后面的数字，0标示显示全部的数据，如果是1就标示只显示1条。 <br />
下图为执行后的结果，item后面的字符串为key</p>
<p align="left"><img height="104" width="380" src="http://www.oursit.com/wp-content/uploads/ScreenShot00070.jpg" alt="" /></p>
<p align="left">通过上面列出的key我们就可以遍历所有的数据了，下面我们取出某一条数据，key为UserFriendsIds_4的数据。</p>
<p align="left">
<div class="dp-highlighter">
<div class="bar">&nbsp;</div>
<ol start="1" class="dp-c">
<li class="alt"><span><span>get&nbsp;UserFriendsIds_4&nbsp;&nbsp;</span></span></li>
</ol>
</div>
<div style="display: none;" class="php">get UserFriendsIds_4</div>
</p>
<p align="left">到这里，你也许明白了怎么去遍历memcache的数据了。 </p>
<p align="left">&nbsp;</p>
<p align="left"><strong>代码实现</strong></p>
<p align="left">
<div class="dp-highlighter">
<div class="bar">&nbsp;</div>
<ol start="1" class="dp-c">
<li class="alt"><span><span>&lt;?php&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="vars">$host</span><span>=</span><span class="string">&#8216;192.168.15.225&#8242;</span><span>;&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="vars">$port</span><span>=11211;&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="vars">$mem</span><span>=</span><span class="keyword">new</span><span>&nbsp;Memcache();&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="vars">$mem</span><span>-&gt;connect(</span><span class="vars">$host</span><span>,</span><span class="vars">$port</span><span>);&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="vars">$items</span><span>=</span><span class="vars">$mem</span><span>-&gt;getExtendedStats&nbsp;(&lsquo;items&rsquo;);&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="vars">$items</span><span>=</span><span class="vars">$items</span><span>[</span><span class="string">&quot;$host:$port&quot;</span><span>][</span><span class="string">'items'</span><span>];&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">foreach</span><span>(</span><span class="vars">$items</span><span>&nbsp;</span><span class="keyword">as</span><span>&nbsp;</span><span class="vars">$key</span><span>=&gt;</span><span class="vars">$values</span><span>){&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="vars">$number</span><span>=</span><span class="vars">$key</span><span>;;&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="vars">$str</span><span>=</span><span class="vars">$mem</span><span>-&gt;getExtendedStats&nbsp;(</span><span class="string">&quot;cachedump&quot;</span><span>,</span><span class="vars">$number</span><span>,0);&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="vars">$line</span><span>=</span><span class="vars">$str</span><span>[</span><span class="string">&quot;$host:$port&quot;</span><span>];&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">if</span><span>(&nbsp;</span><span class="func">is_array</span><span>(</span><span class="vars">$line</span><span>)&nbsp;&amp;&amp;&nbsp;</span><span class="func">count</span><span>(</span><span class="vars">$line</span><span>)&gt;0){&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">foreach</span><span>(</span><span class="vars">$line</span><span>&nbsp;</span><span class="keyword">as</span><span>&nbsp;</span><span class="vars">$key</span><span>=&gt;</span><span class="vars">$value</span><span>){&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="func">echo</span><span>&nbsp;</span><span class="vars">$key</span><span>.</span><span class="string">&#8216;=&gt;&#8217;</span><span>;&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;print_r(<span class="vars">$mem</span><span>-&gt;get(</span><span class="vars">$key</span><span>));&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="func">echo</span><span>&nbsp;</span><span class="string">&quot;\r\n&quot;</span><span>;&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</span></li>
<li><span>&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</span></li>
<li><span>&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</span></li>
<li><span>&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;?&gt;&nbsp;&nbsp;</span></li>
</ol>
</div>
<div style="display: none;" class="php">&lt;?php          $host=&#8217;192.168.15.225&#8242;;          $port=11211;          $mem=new Memcache();          $mem-&gt;connect($host,$port);          $items=$mem-&gt;getExtendedStats (&lsquo;items&rsquo;);          $items=$items[&quot;$host:$port&quot;]['items'];          foreach($items as $key=&gt;$values){              $number=$key;;           $str=$mem-&gt;getExtendedStats (&quot;cachedump&quot;,$number,0);           $line=$str[&quot;$host:$port&quot;];           if( is_array($line) &amp;&amp; count($line)&gt;0){               foreach($line as $key=&gt;$value){                   echo $key.&#8217;=&gt;&#8217;;                   print_r($mem-&gt;get($key));                   echo &quot;\r\n&quot;;               }           }       }       ?&gt;</div></p>
]]></content:encoded>
			<wfw:commentRss>http://www.oursit.com/archives/143.html/feed</wfw:commentRss>
		</item>
		<item>
		<title>JS做的树导航控件</title>
		<link>http://www.oursit.com/archives/141.html</link>
		<comments>http://www.oursit.com/archives/141.html#comments</comments>
		<pubDate>Sat, 06 Jun 2009 04:50:01 +0000</pubDate>
		<dc:creator>Skylin</dc:creator>
		
		<category><![CDATA[JAVASCRIPT]]></category>

		<category><![CDATA[控件]]></category>

		<category><![CDATA[树导航]]></category>

		<guid isPermaLink="false">http://www.oursit.com/?p=141</guid>
		<description><![CDATA[根据公司之前的需求需要做一个树导航栏，所有就编写了一个树导航控件，这个控件采用DOM方式来添加元素和XML数据方式来传输树结构。如果您有什么问题或疑问，欢迎一起讨论]]></description>
			<content:encoded><![CDATA[<p>近段时间根据公司的需要，使用JS做了一个树导航控件，如下图：</p>
<p><img height="565" width="201" alt="" src="http://www.oursit.com/wp-content/uploads/2.JPG" /></p>
<p>&nbsp;</p>
<p><strong>手动添加</strong></p>
<p>&nbsp;</p>
<div class="dp-highlighter">
<div class="bar">&nbsp;</div>
<ol class="dp-c" start="1">
<li class="alt"><span><span>window.onload&nbsp;=&nbsp;</span><span class="keyword">function</span><span>()&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;&nbsp;{&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">var</span><span>&nbsp;navigation&nbsp;=&nbsp;</span><span class="keyword">new</span><span>&nbsp;Navigation(document.getElementById(</span><span class="string">&#8216;aa&#8217;</span><span>),</span><span class="string">&#8216;我的导航&#8217;</span><span>);&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;navigation.addLayer(<span class="string">&#8216;学校管理&#8217;</span><span>);&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;navigation.addLayer(<span class="string">&#8216;教师管理&#8217;</span><span>);&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;navigation.addLayer(<span class="string">&#8216;杨潇管理&#8217;</span><span>);&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;navigation.getTree(0).createRootNode(1000,<span class="string">&#8216;我是谁&#8217;</span><span>,undefined,</span><span class="string">&#8216;aa&#8217;</span><span>);&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;navigation.getTree(0).createRootNode(1001,<span class="string">&#8216;我是杨潇&#8217;</span><span>);&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;navigation.getTree(1).createRootNode(1001,<span class="string">&#8216;我是杨潇&#8217;</span><span>);&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;navigation.getTree(0).getRootNode(0).createChildNode(1002,<span class="string">&#8216;我是杨潇&#8217;</span><span>);&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;navigation.getTree(0).getRootNode(0).createChildNode(1002,<span class="string">&#8216;我是杨潇&#8217;</span><span>);&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;navigation.getTree(0).getRootNode(0).createChildNode(1002,<span class="string">&#8216;我是杨潇&#8217;</span><span>);&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;navigation.getTree(0).getRootNode(0).createChildNode(1002,<span class="string">&#8216;我是杨潇&#8217;</span><span>);&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;navigation.getTree(0).getRootNode(0).createChildNode(1002,<span class="string">&#8216;我是杨潇&#8217;</span><span>);&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;navigation.getTree(0).getRootNode(0).createChildNode(1002,<span class="string">&#8216;我是杨潇&#8217;</span><span>);&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;navigation.getTree(0).getRootNode(0).createChildNode(1002,<span class="string">&#8216;我是杨潇&#8217;</span><span>);&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;navigation.getTree(0).getRootNode(0).createChildNode(1002,<span class="string">&#8216;我是杨潇&#8217;</span><span>);&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;navigation.getTree(0).getRootNode(0).createChildNode(1002,<span class="string">&#8216;我是杨潇&#8217;</span><span>);&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;navigation.getTree(0).getRootNode(0).createChildNode(1002,<span class="string">&#8216;我是杨潇&#8217;</span><span>);&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;navigation.getTree(0).getRootNode(0).createChildNode(1002,<span class="string">&#8216;我是杨潇&#8217;</span><span>);&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;navigation.getTree(0).getRootNode(0).createChildNode(1002,<span class="string">&#8216;我是杨潇&#8217;</span><span>);&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;navigation.getTree(0).getRootNode(0).createChildNode(1002,<span class="string">&#8216;我是杨潇&#8217;</span><span>);&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;navigation.getTree(0).getRootNode(0).createChildNode(1002,<span class="string">&#8216;我是杨潇&#8217;</span><span>);&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;navigation.getTree(0).getRootNode(0).createChildNode(1002,<span class="string">&#8216;我是杨潇&#8217;</span><span>);&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;navigation.getTree(0).getRootNode(0).createChildNode(1002,<span class="string">&#8216;我是杨潇&#8217;</span><span>);&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;navigation.getTree(0).getRootNode(0).createChildNode(1002,<span class="string">&#8216;我是杨潇&#8217;</span><span>);&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;navigation.getTree(0).getRootNode(0).createChildNode(1002,<span class="string">&#8216;我是杨潇&#8217;</span><span>);&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;navigation.getTree(0).getRootNode(0).createChildNode(1002,<span class="string">&#8216;我是杨潇&#8217;</span><span>);&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;navigation.getTree(0).getRootNode(0).createChildNode(1002,<span class="string">&#8216;我是杨潇&#8217;</span><span>);&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;navigation.getTree(0).getRootNode(0).createChildNode(1002,<span class="string">&#8216;我是杨潇&#8217;</span><span>);&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;navigation.getTree(0).getRootNode(0).createChildNode(1002,<span class="string">&#8216;我是杨潇&#8217;</span><span>);&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;navigation.getTree(0).getRootNode(0).createChildNode(1002,<span class="string">&#8216;我是杨潇&#8217;</span><span>);&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;navigation.getTree(0).getRootNode(0).createChildNode(1002,<span class="string">&#8216;我是杨潇&#8217;</span><span>);&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;navigation.getTree(0).getRootNode(0).getChildNode(0).createChildNode(1002,<span class="string">&#8216;我是郑宇&#8217;</span><span>);&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;navigation.getTree(0).getRootNode(0).getChildNode(0).getChildNode(0).parentNode.parentNode.createChildNode(1002,<span class="string">&#8216;我是丁双文&#8217;</span><span>,</span><span class="string">&#8221;</span><span>,</span><span class="string">&#8216;aa&#8217;</span><span>);&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></li>
<li><span>&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">function</span><span>&nbsp;aa()&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;{&nbsp;&nbsp;</span></li>
<li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;window.location&nbsp;=&nbsp;<span class="string">&#8216;www.google.com&#8217;</span><span>;&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</span></li>
</ol>
</div>
<div class="javascript" style="display: none;">window.onload = function() 	{ 		var navigation = new Navigation(document.getElementById(&#8217;aa&#8217;),&#8217;我的导航&#8217;); 		navigation.addLayer(&#8217;学校管理&#8217;); 		navigation.addLayer(&#8217;教师管理&#8217;); 		navigation.addLayer(&#8217;杨潇管理&#8217;); 		navigation.getTree(0).createRootNode(1000,&#8217;我是谁&#8217;,undefined,&#8217;aa&#8217;); 		navigation.getTree(0).createRootNode(1001,&#8217;我是杨潇&#8217;); 		navigation.getTree(1).createRootNode(1001,&#8217;我是杨潇&#8217;); 		navigation.getTree(0).getRootNode(0).createChildNode(1002,&#8217;我是杨潇&#8217;); 		navigation.getTree(0).getRootNode(0).createChildNode(1002,&#8217;我是杨潇&#8217;); 		navigation.getTree(0).getRootNode(0).createChildNode(1002,&#8217;我是杨潇&#8217;); 		navigation.getTree(0).getRootNode(0).createChildNode(1002,&#8217;我是杨潇&#8217;); 		navigation.getTree(0).getRootNode(0).createChildNode(1002,&#8217;我是杨潇&#8217;); 		navigation.getTree(0).getRootNode(0).createChildNode(1002,&#8217;我是杨潇&#8217;); 		navigation.getTree(0).getRootNode(0).createChildNode(1002,&#8217;我是杨潇&#8217;); 		navigation.getTree(0).getRootNode(0).createChildNode(1002,&#8217;我是杨潇&#8217;); 		navigation.getTree(0).getRootNode(0).createChildNode(1002,&#8217;我是杨潇&#8217;); 		navigation.getTree(0).getRootNode(0).createChildNode(1002,&#8217;我是杨潇&#8217;); 		navigation.getTree(0).getRootNode(0).createChildNode(1002,&#8217;我是杨潇&#8217;); 		navigation.getTree(0).getRootNode(0).createChildNode(1002,&#8217;我是杨潇&#8217;); 		navigation.getTree(0).getRootNode(0).createChildNode(1002,&#8217;我是杨潇&#8217;); 		navigation.getTree(0).getRootNode(0).createChildNode(1002,&#8217;我是杨潇&#8217;); 		navigation.getTree(0).getRootNode(0).createChildNode(1002,&#8217;我是杨潇&#8217;); 		navigation.getTree(0).getRootNode(0).createChildNode(1002,&#8217;我是杨潇&#8217;); 		navigation.getTree(0).getRootNode(0).createChildNode(1002,&#8217;我是杨潇&#8217;); 		navigation.getTree(0).getRootNode(0).createChildNode(1002,&#8217;我是杨潇&#8217;); 		navigation.getTree(0).getRootNode(0).createChildNode(1002,&#8217;我是杨潇&#8217;); 		navigation.getTree(0).getRootNode(0).createChildNode(1002,&#8217;我是杨潇&#8217;); 		navigation.getTree(0).getRootNode(0).createChildNode(1002,&#8217;我是杨潇&#8217;); 		navigation.getTree(0).getRootNode(0).createChildNode(1002,&#8217;我是杨潇&#8217;); 		navigation.getTree(0).getRootNode(0).createChildNode(1002,&#8217;我是杨潇&#8217;); 		navigation.getTree(0).getRootNode(0).createChildNode(1002,&#8217;我是杨潇&#8217;); 		navigation.getTree(0).getRootNode(0).getChildNode(0).createChildNode(1002,&#8217;我是郑宇&#8217;); 		navigation.getTree(0).getRootNode(0).getChildNode(0).getChildNode(0).parentNode.parentNode.createChildNode(1002,&#8217;我是丁双文&#8217;,&#8221;,&#8217;aa&#8217;); 	} 	 	function aa() 	{ 		window.location = &#8216;www.google.com&#8217;; 	}</div>
<link href="/wp-content/plugins/fckeditor_for_wordpress/fckeditor/editor/plugins/highlighter/dp.SyntaxHighlighter/Styles/SyntaxHighlighter.css" type="text/css" rel="stylesheet" />
<p>&nbsp;</p>
<p>基本采用DOM风格来进行编写的。下面说明一下各个函数参数的用法。</p>
<p>&nbsp;</p>
<div class="dp-highlighter">
<div class="bar">&nbsp;</div>
<ol class="dp-c" start="1">
<li class="alt"><span><span class="comment">/*</span>&nbsp;</span></li>
<li><span><span class="comment">&nbsp;*&nbsp;导航构造函数</span>&nbsp;</span></li>
<li class="alt"><span><span class="comment">&nbsp;*&nbsp;targetObj:目标对象,导航显示区域</span>&nbsp;</span></li>
<li><span><span class="comment">&nbsp;*&nbsp;title:标题名称</span>&nbsp;</span></li>
<li class="alt"><span><span class="comment">&nbsp;*/</span><span>&nbsp;&nbsp;</span></span></li>
<li><span>Navigation(targetObj,title)&nbsp;&nbsp;</span></li>
</ol>
</div>
<div class="javascript" style="display: none;">/*  * 导航构造函数  * targetObj:目标对象,导航显示区域  * title:标题名称  */ Navigation(targetObj,title)</div>
<p>&nbsp;</p>
<p>&nbsp;</p>
<div>
<div class="dp-highlighter">
<div class="bar">&nbsp;</div>
<ol class="dp-c" start="1">
<li class="alt"><span><span class="comment">/*</span>&nbsp;</span></li>
<li><span><span class="comment">&nbsp;*&nbsp;添加层级</span>&nbsp;</span></li>
<li class="alt"><span><span class="comment">&nbsp;*&nbsp;layerTitle:层级标题文本</span>&nbsp;</span></li>
<li><span><span class="comment">&nbsp;*&nbsp;isShow:添加的层级是否打开;如果所有层级不填写，则默认第一个是打开状态</span>&nbsp;</span></li>
<li class="alt"><span><span class="comment">&nbsp;*/</span><span>&nbsp;&nbsp;</span></span></li>
<li><span>addLayer(layerTitle,isShow)&nbsp;&nbsp;</span></li>
</ol>
</div>
<div class="javascript" style="display: none;">/*  * 添加层级  * layerTitle:层级标题文本  * isShow:添加的层级是否打开;如果所有层级不填写，则默认第一个是打开状态  */ addLayer(layerTitle,isShow)</div>
</div>
<p>&nbsp;</p>
<div>
<div class="dp-highlighter">
<div class="bar">&nbsp;</div>
<ol class="dp-c" start="1">
<li class="alt"><span><span class="comment">/*</span>&nbsp;</span></li>
<li><span><span class="comment">&nbsp;*&nbsp;获取层级树</span>&nbsp;</span></li>
<li class="alt"><span><span class="comment">&nbsp;*&nbsp;num:层级索引，获取指定层级的树节点</span>&nbsp;</span></li>
<li><span><span class="comment">&nbsp;*/</span><span>&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>getTree(num)&nbsp;&nbsp;</span></li>
</ol>
</div>
<div class="javascript" style="display: none;">/*  * 获取层级树  * num:层级索引，获取指定层级的树节点  */ getTree(num)</div>
</div>
<p>&nbsp;</p>
<div>
<div class="dp-highlighter">
<div class="bar">&nbsp;</div>
<ol class="dp-c" start="1">
<li class="alt"><span><span class="comment">/*</span>&nbsp;</span></li>
<li><span><span class="comment">&nbsp;*&nbsp;创建主节点</span>&nbsp;</span></li>
<li class="alt"><span><span class="comment">&nbsp;*&nbsp;nodeId:节点id,可以用来存储数据库中的ID值</span>&nbsp;</span></li>
<li><span><span class="comment">&nbsp;*&nbsp;nodeText:节点文本,用来显示</span>&nbsp;</span></li>
<li class="alt"><span><span class="comment">&nbsp;*&nbsp;picStyle：节点样式</span>&nbsp;</span></li>
<li><span><span class="comment">&nbsp;*&nbsp;func：点击回调的函数</span>&nbsp;</span></li>
<li class="alt"><span><span class="comment">&nbsp;*/</span><span>&nbsp;&nbsp;</span></span></li>
<li><span>createRootNode(nodeId,nodeText,picStyle,func)&nbsp;&nbsp;</span></li>
</ol>
</div>
<div class="javascript" style="display: none;">/*  * 创建主节点  * nodeId:节点id,可以用来存储数据库中的ID值  * nodeText:节点文本,用来显示  * picStyle：节点样式  * func：点击回调的函数  */ createRootNode(nodeId,nodeText,picStyle,func)</div>
</div>
<p>&nbsp;</p>
<div>
<div class="dp-highlighter">
<div class="bar">&nbsp;</div>
<ol class="dp-c" start="1">
<li class="alt"><span><span class="comment">/*</span>&nbsp;</span></li>
<li><span><span class="comment">&nbsp;*&nbsp;获取主节点</span>&nbsp;</span></li>
<li class="alt"><span><span class="comment">&nbsp;*&nbsp;num:主节点索引,可以用来获取指定主节点</span>&nbsp;</span></li>
<li><span><span class="comment">&nbsp;*/</span><span>&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>getRootNode(num)&nbsp;&nbsp;</span></li>
</ol>
</div>
<div class="javascript" style="display: none;">/*  * 获取主节点  * num:主节点索引,可以用来获取指定主节点  */ getRootNode(num)</div>
</div>
<p>&nbsp;</p>
<div>
<div class="dp-highlighter">
<div class="bar">&nbsp;</div>
<ol class="dp-c" start="1">
<li class="alt"><span><span class="comment">/*</span>&nbsp;</span></li>
<li><span><span class="comment">&nbsp;*&nbsp;创建子节点</span>&nbsp;</span></li>
<li class="alt"><span><span class="comment">&nbsp;*&nbsp;nodeId:节点id,可以用来存储数据库中的ID值</span>&nbsp;</span></li>
<li><span><span class="comment">&nbsp;*&nbsp;nodeText:节点文本,用来显示</span>&nbsp;</span></li>
<li class="alt"><span><span class="comment">&nbsp;*&nbsp;picStyle：节点样式</span>&nbsp;</span></li>
<li><span><span class="comment">&nbsp;*&nbsp;func:点击回调的函数</span>&nbsp;</span></li>
<li class="alt"><span><span class="comment">&nbsp;*/</span><span>&nbsp;&nbsp;</span></span></li>
<li><span>createChildNode(nodeId,nodeText,picStyle,func)&nbsp;&nbsp;</span></li>
</ol>
</div>
<div class="javascript" style="display: none;">/*  * 创建子节点  * nodeId:节点id,可以用来存储数据库中的ID值  * nodeText:节点文本,用来显示  * picStyle：节点样式  * func:点击回调的函数  */ createChildNode(nodeId,nodeText,picStyle,func)</div>
</div>
<p>&nbsp;</p>
<div>
<div class="dp-highlighter">
<div class="bar">&nbsp;</div>
<ol class="dp-c" start="1">
<li class="alt"><span><span class="comment">/*</span>&nbsp;</span></li>
<li><span><span class="comment">&nbsp;*&nbsp;获取子节点</span>&nbsp;</span></li>
<li class="alt"><span><span class="comment">&nbsp;*&nbsp;num:节点索引,可以用来获取指定子节点</span>&nbsp;</span></li>
<li><span><span class="comment">&nbsp;*/</span><span>&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>getChildNode(num)&nbsp;&nbsp;</span></li>
</ol>
</div>
<div class="javascript" style="display: none;">/*  * 获取子节点  * num:节点索引,可以用来获取指定子节点  */ getChildNode(num)</div>
</div>
<p>以上是手动操作的例子和相关的方法参数说明。</p>
<p>另外，我们还可以使用XML来形成树导航，XML格式如下：</p>
<p>文件：<strong>tree.xml</strong></p>
<p>&nbsp;</p>
<div class="dp-highlighter">
<div class="bar">&nbsp;</div>
<ol class="dp-xml" start="1">
<li class="alt"><span><span class="tag">&lt;?</span><span class="tag-name">xml</span><span>&nbsp;</span><span class="attribute">version</span><span>=</span><span class="attribute-value">&quot;1.0&quot;</span><span>&nbsp;</span><span class="attribute">encoding</span><span>=</span><span class="attribute-value">&quot;utf-8&quot;</span><span class="tag">?&gt;</span><span>&nbsp;&nbsp;</span></span></li>
<li><span><span class="tag">&lt;</span><span class="tag-name">Navigation</span><span>&nbsp;</span><span class="attribute">title</span><span>=</span><span class="attribute-value">&quot;我的导航1&quot;</span><span class="tag">&gt;</span><span>&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;<span class="tag">&lt;</span><span class="tag-name">Layer</span><span>&nbsp;</span><span class="attribute">title</span><span>=</span><span class="attribute-value">&quot;学校管理&quot;</span><span>&nbsp;</span><span class="attribute">isShow</span><span>=</span><span class="attribute-value">&quot;&quot;</span><span class="tag">&gt;</span><span>&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="tag">&lt;</span><span class="tag-name">Node</span><span>&nbsp;</span><span class="attribute">nodeId</span><span>=</span><span class="attribute-value">&quot;&quot;</span><span>&nbsp;</span><span class="attribute">title</span><span>=</span><span class="attribute-value">&quot;我是谁&quot;</span><span>&nbsp;</span><span class="attribute">picStyle</span><span>=</span><span class="attribute-value">&quot;tree-map-img-show&quot;</span><span>&nbsp;</span><span class="attribute">func</span><span>=</span><span class="attribute-value">&quot;&quot;</span><span class="tag">&gt;</span><span>&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="tag">&lt;</span><span class="tag-name">Node</span><span>&nbsp;</span><span class="attribute">nodeId</span><span>=</span><span class="attribute-value">&quot;&quot;</span><span>&nbsp;</span><span class="attribute">title</span><span>=</span><span class="attribute-value">&quot;我是谁&quot;</span><span>&nbsp;</span><span class="attribute">picStyle</span><span>=</span><span class="attribute-value">&quot;tree-map-img-show&quot;</span><span>&nbsp;</span><span class="attribute">func</span><span>=</span><span class="attribute-value">&quot;&quot;</span><span class="tag">/&gt;</span><span>&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="tag">&lt;</span><span class="tag-name">Node</span><span>&nbsp;</span><span class="attribute">nodeId</span><span>=</span><span class="attribute-value">&quot;&quot;</span><span>&nbsp;</span><span class="attribute">title</span><span>=</span><span class="attribute-value">&quot;我是谁&quot;</span><span>&nbsp;</span><span class="attribute">picStyle</span><span>=</span><span class="attribute-value">&quot;tree-map-img-show&quot;</span><span>&nbsp;</span><span class="attribute">func</span><span>=</span><span class="attribute-value">&quot;&quot;</span><span class="tag">/&gt;</span><span>&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="tag">&lt;/</span><span class="tag-name">Node</span><span class="tag">&gt;</span><span>&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="tag">&lt;</span><span class="tag-name">Node</span><span>&nbsp;</span><span class="attribute">nodeId</span><span>=</span><span class="attribute-value">&quot;&quot;</span><span>&nbsp;</span><span class="attribute">title</span><span>=</span><span class="attribute-value">&quot;我是郑宇&quot;</span><span>&nbsp;</span><span class="attribute">picStyle</span><span>=</span><span class="attribute-value">&quot;tree-map-img-show&quot;</span><span>&nbsp;</span><span class="attribute">func</span><span>=</span><span class="attribute-value">&quot;&quot;</span><span class="tag">&gt;</span><span>&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="tag">&lt;</span><span class="tag-name">Node</span><span>&nbsp;</span><span class="attribute">nodeId</span><span>=</span><span class="attribute-value">&quot;&quot;</span><span>&nbsp;</span><span class="attribute">title</span><span>=</span><span class="attribute-value">&quot;我是郑宇&quot;</span><span>&nbsp;</span><span class="attribute">picStyle</span><span>=</span><span class="attribute-value">&quot;tree-map-img-show&quot;</span><span>&nbsp;</span><span class="attribute">func</span><span>=</span><span class="attribute-value">&quot;&quot;</span><span class="tag">&gt;</span><span>&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="tag">&lt;</span><span class="tag-name">Node</span><span>&nbsp;</span><span class="attribute">nodeId</span><span>=</span><span class="attribute-value">&quot;&quot;</span><span>&nbsp;</span><span class="attribute">title</span><span>=</span><span class="attribute-value">&quot;我是谁&quot;</span><span>&nbsp;</span><span class="attribute">picStyle</span><span>=</span><span class="attribute-value">&quot;tree-map-img-show&quot;</span><span>&nbsp;</span><span class="attribute">func</span><span>=</span><span class="attribute-value">&quot;aa&quot;</span><span class="tag">/&gt;</span><span>&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="tag">&lt;</span><span class="tag-name">Node</span><span>&nbsp;</span><span class="attribute">nodeId</span><span>=</span><span class="attribute-value">&quot;&quot;</span><span>&nbsp;</span><span class="attribute">title</span><span>=</span><span class="attribute-value">&quot;我是谁&quot;</span><span>&nbsp;</span><span class="attribute">picStyle</span><span>=</span><span class="attribute-value">&quot;tree-map-img-show&quot;</span><span>&nbsp;</span><span class="attribute">func</span><span>=</span><span class="attribute-value">&quot;&quot;</span><span class="tag">/&gt;</span><span>&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="tag">&lt;/</span><span class="tag-name">Node</span><span class="tag">&gt;</span><span>&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="tag">&lt;</span><span class="tag-name">Node</span><span>&nbsp;</span><span class="attribute">nodeId</span><span>=</span><span class="attribute-value">&quot;&quot;</span><span>&nbsp;</span><span class="attribute">title</span><span>=</span><span class="attribute-value">&quot;我是谁&quot;</span><span>&nbsp;</span><span class="attribute">picStyle</span><span>=</span><span class="attribute-value">&quot;tree-map-img-show&quot;</span><span>&nbsp;</span><span class="attribute">func</span><span>=</span><span class="attribute-value">&quot;&quot;</span><span class="tag">/&gt;</span><span>&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="tag">&lt;</span><span class="tag-name">Node</span><span>&nbsp;</span><span class="attribute">nodeId</span><span>=</span><span class="attribute-value">&quot;&quot;</span><span>&nbsp;</span><span class="attribute">title</span><span>=</span><span class="attribute-value">&quot;我是谁&quot;</span><span>&nbsp;</span><span class="attribute">picStyle</span><span>=</span><span class="attribute-value">&quot;tree-map-img-show&quot;</span><span>&nbsp;</span><span class="attribute">func</span><span>=</span><span class="attribute-value">&quot;&quot;</span><span class="tag">/&gt;</span><span>&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="tag">&lt;/</span><span class="tag-name">Node</span><span class="tag">&gt;</span><span>&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;&nbsp;<span class="tag">&lt;/</span><span class="tag-name">Layer</span><span class="tag">&gt;</span><span>&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;<span class="tag">&lt;</span><span class="tag-name">Layer</span><span>&nbsp;</span><span class="attribute">title</span><span>=</span><span class="attribute-value">&quot;教师管理&quot;</span><span>&nbsp;</span><span class="attribute">isShow</span><span>=</span><span class="attribute-value">&quot;&quot;</span><span class="tag">&gt;</span><span>&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="tag">&lt;</span><span class="tag-name">Node</span><span>&nbsp;</span><span class="attribute">nodeId</span><span>=</span><span class="attribute-value">&quot;&quot;</span><span>&nbsp;</span><span class="attribute">title</span><span>=</span><span class="attribute-value">&quot;我是杨潇&quot;</span><span>&nbsp;</span><span class="attribute">picStyle</span><span>=</span><span class="attribute-value">&quot;&quot;</span><span>&nbsp;</span><span class="attribute">func</span><span>=</span><span class="attribute-value">&quot;&quot;</span><span class="tag">&gt;</span><span>&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="tag">&lt;</span><span class="tag-name">Node</span><span>&nbsp;</span><span class="attribute">nodeId</span><span>=</span><span class="attribute-value">&quot;&quot;</span><span>&nbsp;</span><span class="attribute">title</span><span>=</span><span class="attribute-value">&quot;我是谁&quot;</span><span>&nbsp;</span><span class="attribute">picStyle</span><span>=</span><span class="attribute-value">&quot;&quot;</span><span>&nbsp;</span><span class="attribute">func</span><span>=</span><span class="attribute-value">&quot;&quot;</span><span class="tag">/&gt;</span><span>&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="tag">&lt;</span><span class="tag-name">Node</span><span>&nbsp;</span><span class="attribute">nodeId</span><span>=</span><span class="attribute-value">&quot;&quot;</span><span>&nbsp;</span><span class="attribute">title</span><span>=</span><span class="attribute-value">&quot;我是谁&quot;</span><span>&nbsp;</span><span class="attribute">picStyle</span><span>=</span><span class="attribute-value">&quot;&quot;</span><span>&nbsp;</span><span class="attribute">func</span><span>=</span><span class="attribute-value">&quot;&quot;</span><span class="tag">/&gt;</span><span>&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="tag">&lt;/</span><span class="tag-name">Node</span><span class="tag">&gt;</span><span>&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;&nbsp;<span class="tag">&lt;/</span><span class="tag-name">Layer</span><span class="tag">&gt;</span><span>&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;<span class="tag">&lt;</span><span class="tag-name">Layer</span><span>&nbsp;</span><span class="attribute">title</span><span>=</span><span class="attribute-value">&quot;教师管理&quot;</span><span>&nbsp;</span><span class="attribute">isShow</span><span>=</span><span class="attribute-value">&quot;&quot;</span><span class="tag">&gt;</span><span>&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="tag">&lt;</span><span class="tag-name">Node</span><span>&nbsp;</span><span class="attribute">nodeId</span><span>=</span><span class="attribute-value">&quot;&quot;</span><span>&nbsp;</span><span class="attribute">title</span><span>=</span><span class="attribute-value">&quot;我是杨潇&quot;</span><span>&nbsp;</span><span class="attribute">picStyle</span><span>=</span><span class="attribute-value">&quot;&quot;</span><span>&nbsp;</span><span class="attribute">func</span><span>=</span><span class="attribute-value">&quot;&quot;</span><span class="tag">&gt;</span><span>&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="tag">&lt;</span><span class="tag-name">Node</span><span>&nbsp;</span><span class="attribute">nodeId</span><span>=</span><span class="attribute-value">&quot;&quot;</span><span>&nbsp;</span><span class="attribute">title</span><span>=</span><span class="attribute-value">&quot;我是谁&quot;</span><span>&nbsp;</span><span class="attribute">picStyle</span><span>=</span><span class="attribute-value">&quot;&quot;</span><span>&nbsp;</span><span class="attribute">func</span><span>=</span><span class="attribute-value">&quot;&quot;</span><span class="tag">/&gt;</span><span>&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="tag">&lt;</span><span class="tag-name">Node</span><span>&nbsp;</span><span class="attribute">nodeId</span><span>=</span><span class="attribute-value">&quot;&quot;</span><span>&nbsp;</span><span class="attribute">title</span><span>=</span><span class="attribute-value">&quot;我是谁&quot;</span><span>&nbsp;</span><span class="attribute">picStyle</span><span>=</span><span class="attribute-value">&quot;&quot;</span><span>&nbsp;</span><span class="attribute">func</span><span>=</span><span class="attribute-value">&quot;&quot;</span><span class="tag">/&gt;</span><span>&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="tag">&lt;/</span><span class="tag-name">Node</span><span class="tag">&gt;</span><span>&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;&nbsp;<span class="tag">&lt;/</span><span class="tag-name">Layer</span><span class="tag">&gt;</span><span>&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;<span class="tag">&lt;</span><span class="tag-name">Layer</span><span>&nbsp;</span><span class="attribute">title</span><span>=</span><span class="attribute-value">&quot;教师管理&quot;</span><span>&nbsp;</span><span class="attribute">isShow</span><span>=</span><span class="attribute-value">&quot;&quot;</span><span class="tag">&gt;</span><span>&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="tag">&lt;</span><span class="tag-name">Node</span><span>&nbsp;</span><span class="attribute">nodeId</span><span>=</span><span class="attribute-value">&quot;&quot;</span><span>&nbsp;</span><span class="attribute">title</span><span>=</span><span class="attribute-value">&quot;我是杨潇&quot;</span><span>&nbsp;</span><span class="attribute">picStyle</span><span>=</span><span class="attribute-value">&quot;&quot;</span><span>&nbsp;</span><span class="attribute">func</span><span>=</span><span class="attribute-value">&quot;&quot;</span><span class="tag">&gt;</span><span>&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="tag">&lt;</span><span class="tag-name">Node</span><span>&nbsp;</span><span class="attribute">nodeId</span><span>=</span><span class="attribute-value">&quot;&quot;</span><span>&nbsp;</span><span class="attribute">title</span><span>=</span><span class="attribute-value">&quot;我是谁&quot;</span><span>&nbsp;</span><span class="attribute">picStyle</span><span>=</span><span class="attribute-value">&quot;&quot;</span><span>&nbsp;</span><span class="attribute">func</span><span>=</span><span class="attribute-value">&quot;&quot;</span><span class="tag">/&gt;</span><span>&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="tag">&lt;</span><span class="tag-name">Node</span><span>&nbsp;</span><span class="attribute">nodeId</span><span>=</span><span class="attribute-value">&quot;&quot;</span><span>&nbsp;</span><span class="attribute">title</span><span>=</span><span class="attribute-value">&quot;我是谁&quot;</span><span>&nbsp;</span><span class="attribute">picStyle</span><span>=</span><span class="attribute-value">&quot;&quot;</span><span>&nbsp;</span><span class="attribute">func</span><span>=</span><span class="attribute-value">&quot;&quot;</span><span class="tag">/&gt;</span><span>&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="tag">&lt;/</span><span class="tag-name">Node</span><span class="tag">&gt;</span><span>&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;&nbsp;<span class="tag">&lt;/</span><span class="tag-name">Layer</span><span class="tag">&gt;</span><span>&nbsp;&nbsp;</span></span></li>
<li class="alt"><span><span class="tag">&lt;/</span><span class="tag-name">Navigation</span><span class="tag">&gt;</span><span>&nbsp;&nbsp;</span></span></li>
</ol>
</div>
<div class="xml" style="display: none;">&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt; <navigation title="我的导航1"> 	<layer title="学校管理" isshow=""> 		<node nodeid="" title="我是谁" picstyle="tree-map-img-show" func=""> 			<node nodeid="" title="我是谁" picstyle="tree-map-img-show" func=""> 			<node nodeid="" title="我是谁" picstyle="tree-map-img-show" func=""> 		</node> 		<node nodeid="" title="我是郑宇" picstyle="tree-map-img-show" func=""> 			<node nodeid="" title="我是郑宇" picstyle="tree-map-img-show" func=""> 			   <node nodeid="" title="我是谁" picstyle="tree-map-img-show" func="aa"> 			   <node nodeid="" title="我是谁" picstyle="tree-map-img-show" func=""> 		    </node> 			<node nodeid="" title="我是谁" picstyle="tree-map-img-show" func=""> 			<node nodeid="" title="我是谁" picstyle="tree-map-img-show" func=""> 		</node> 	</node> 	<layer title="教师管理" isshow=""> 		<node nodeid="" title="我是杨潇" picstyle="" func=""> 			<node nodeid="" title="我是谁" picstyle="" func=""> 			<node nodeid="" title="我是谁" picstyle="" func=""> 		</node> 	</node> 	<layer title="教师管理" isshow=""> 		<node nodeid="" title="我是杨潇" picstyle="" func=""> 			<node nodeid="" title="我是谁" picstyle="" func=""> 			<node nodeid="" title="我是谁" picstyle="" func=""> 		</node> 	</node> 	<layer title="教师管理" isshow=""> 		<node nodeid="" title="我是杨潇" picstyle="" func=""> 			<node nodeid="" title="我是谁" picstyle="" func=""> 			<node nodeid="" title="我是谁" picstyle="" func=""> 		</node> 	</node> </node></layer></node></layer></node></layer></node></node></node></node></node></layer></navigation></div>
<p>&nbsp;</p>
<p>XML格式基本如上例，和相关方法参数对应，比较简单，这里就不做详细介绍了。</p>
<p>下面是使用XML文件创建的代码：</p>
<p>&nbsp;</p>
<div class="dp-highlighter">
<div class="bar">&nbsp;</div>
<ol class="dp-c" start="1">
<li class="alt"><span><span>window.onload&nbsp;=&nbsp;</span><span class="keyword">function</span><span>()&nbsp;&nbsp;</span></span></li>
<li><span>{&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">var</span><span>&nbsp;navigation&nbsp;=&nbsp;</span><span class="keyword">new</span><span>&nbsp;Navigation(document.getElementById(</span><span class="string">&#8216;aa&#8217;</span><span>),</span><span class="string">&#8216;我的导航&#8217;</span><span>);&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;&nbsp;navigation.load(<span class="string">&#8216;tree.xml&#8217;</span><span>);&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>}&nbsp;&nbsp;</span></li>
<li><span>&nbsp;&nbsp;</span></li>
<li class="alt"><span><span class="keyword">function</span><span>&nbsp;aa()&nbsp;&nbsp;</span></span></li>
<li><span>{&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;window.location&nbsp;=&nbsp;<span class="string">&#8216;www.google.com&#8217;</span><span>;&nbsp;&nbsp;</span></span></li>
<li><span>}&nbsp;&nbsp;</span></li>
</ol>
</div>
<div class="javascript" style="display: none;">window.onload = function() 	{ 		var navigation = new Navigation(document.getElementById(&#8217;aa&#8217;),&#8217;我的导航&#8217;); 		navigation.load(&#8217;tree.xml&#8217;); 	} 	 	function aa() 	{ 		window.location = &#8216;www.google.com&#8217;; 	}</div>
<p>&nbsp;</p>
<p>都比较简单。这里也不多讲了：）</p>
<p>下面是例子的链接地址：</p>
<p>http://www.oursit.com/example/tree2/</p>
<p>&nbsp;</p>
<p>下载实例：http://www.oursit.com/example/tree2/tree2.rar</p>
<p>实例里面包含4个js文件，其实这4个JS文件都是相同的。</p>
<p>navigation-max.js&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 有动画效果（未压缩）</p>
<p>navigation.js&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 有动画效果（已压缩）</p>
<p>navigation-1.js&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 无动画效果（未压缩）</p>
<p>navigation-1-min.js&nbsp;&nbsp; 无动画效果（已压缩）</p>
<p>&nbsp;</p>
<p>如果您有什么问题或疑问，欢迎一起讨论：）</p>
]]></content:encoded>
			<wfw:commentRss>http://www.oursit.com/archives/141.html/feed</wfw:commentRss>
		</item>
		<item>
		<title>提高Linux上socket性能&#8212;加速网络应用程序</title>
		<link>http://www.oursit.com/archives/135.html</link>
		<comments>http://www.oursit.com/archives/135.html#comments</comments>
		<pubDate>Wed, 03 Sep 2008 13:13:35 +0000</pubDate>
		<dc:creator>Skylin</dc:creator>
		
		<category><![CDATA[C/C++]]></category>

		<category><![CDATA[网络编程]]></category>

		<category><![CDATA[socket]]></category>

		<guid isPermaLink="false">http://www.oursit.com/?p=135</guid>
		<description><![CDATA[&#160;&#160;&#160;&#160;&#160;&#160; 我们在编写网络应用程序的时候经常会碰到性能上面的问题，在网上看到了这片文章，讲的比较好，所以转载过来。：）
在开发 socket 应用程序时，首要任务通常是确保可靠性并满足一些特定的需求。利用本文中给出的 4 个提示，您就可以从头开始为实现最佳性能来设计并开发 socket 程序。本文内容包括对于 Sockets API 的使用、两个可以提高性能的 socket 选项以及 GNU/Linux 优化。
　　为了能够开发性能卓越的应用程序，请遵循以下技巧：
　　最小化报文传输的延时。
　　最小化系统调用的负载。
　　为 Bandwidth Delay Product 调节 TCP 窗口。
　　动态优化 GNU/Linux TCP/IP 栈。
　　技巧 1. 最小化报文传输的延时
　　在通过 TCP socket 进行通信时，数据都拆分成了数据块，这样它们就可以封装到给定连接的 TCP payload(指 TCP 数据包中的有效负荷)中了。TCP payload 的大小取决于几个因素(例如最大报文长度和路径)，但是这些因素在连接发起时都是已知的。为了达到最好的性能，我们的目标是使用尽可能多的可用数据来填充 每个报文。当没有足够的数据来填充 payload 时(也称为最大报文段长度(maximum segment size) 或 MSS)，TCP 就会采用 Nagle 算法自动将一些小的缓冲区连接到一个报文段中。这样可以通过最小化所发送的报文的数量来提高应用程序的效率，并减轻整体的网络拥塞问题。
　　尽管 John Nagle 的算法可以通过将这些数据连接成更大的报文来最小化所发送的报文的数量，但是有时您可能希望只发送一些较小的报文。一个简单的例子是 telnet 程序，它让用户可以与远程系统进行交互，这通常都是通过一个 shell 来进行的。如果用户被要求用发送报文之前输入的字符来填充某个报文段，那么这种方法就绝对不能满足我们的需要。
　　另外一个例子是 HTTP 协议。通常，客户机浏览器会产生一个小请求(一条 HTTP [...]]]></description>
			<content:encoded><![CDATA[<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 我们在编写网络应用程序的时候经常会碰到性能上面的问题，在网上看到了这片文章，讲的比较好，所以转载过来。：）</p>
<p>在开发 socket 应用程序时，首要任务通常是确保可靠性并满足一些特定的需求。利用本文中给出的 4 个提示，您就可以从头开始为实现最佳性能来设计并开发 socket 程序。本文内容包括对于 Sockets API 的使用、两个可以提高性能的 socket 选项以及 GNU/<a target="_blank" href="http://www.educity.cn/incsearch/search.asp?key=Linux">Linux</a> 优化。</p>
<p>　　为了能够开发性能卓越的应用程序，请遵循以下技巧：</p>
<p>　　最小化报文传输的延时。</p>
<p>　　最小化系统调用的负载。</p>
<p>　　为 Bandwidth Delay Product 调节 TCP 窗口。</p>
<p>　　动态优化 GNU/Linux TCP/IP 栈。</p>
<p>　　技巧 1. 最小化报文传输的延时</p>
<p>　　在通过 TCP socket 进行通信时，数据都拆分成了数据块，这样它们就可以封装到给定连接的 TCP payload(指 TCP 数据包中的有效负荷)中了。TCP payload 的大小取决于几个因素(例如最大报文长度和路径)，但是这些因素在连接发起时都是已知的。为了达到最好的性能，我们的目标是使用尽可能多的可用数据来填充 每个报文。当没有足够的数据来填充 payload 时(也称为最大报文段长度(maximum segment size) 或 MSS)，TCP 就会采用 Nagle 算法自动将一些小的缓冲区连接到一个报文段中。这样可以通过最小化所发送的报文的数量来提高应用程序的效率，并减轻整体的网络拥塞问题。</p>
<p>　　尽管 John Nagle 的算法可以通过将这些数据连接成更大的报文来最小化所发送的报文的数量，但是有时您可能希望只发送一些较小的报文。一个简单的例子是 telnet 程序，它让用户可以与远程系统进行交互，这通常都是通过一个 shell 来进行的。如果用户被要求用发送报文之前输入的字符来填充某个报文段，那么这种方法就绝对不能满足我们的需要。</p>
<p>　　另外一个例子是 HTTP 协议。通常，客户机浏览器会产生一个小请求(一条 HTTP 请求消息)，然后 <a target="_blank" href="http://www.educity.cn/incsearch/search.asp?key=Web">Web</a> <a target="_blank" href="http://www.educity.cn/incsearch/search.asp?key=%B7%FE%CE%F1%C6%F7">服务器</a>就会返回一个更大的响应(Web 页面)。</p>
<p>　　解决方案</p>
<p>　　您应该考虑的第一件事情是 Nagle 算法满足一种需求。由于这种算法对数据进行合并，试图构成一个完整的 TCP 报文段，因此它会引入一些延时。但是这种算法可以最小化在线路上发送的报文的数量，因此可以最小化网络拥塞的问题。</p>
<p>　　但是在需要最小化传输延时的情况中，Sockets API 可以提供一种解决方案。要禁用 Nagle 算法，您可以设置 TCP_NODELAY socket 选项，如清单 1 所示。</p>
<p>　　清单 1. 为 TCP socket 禁用 Nagle 算法</p>
<p>　　int sock, flag, ret;</p>
<p>　　/* Create new stream socket */</p>
<p>　　sock = socket ( AF_INET, SOCK_STREAM, 0 );</p>
<p>　　/* Disable the Nagle (TCP No Delay) algorithm */</p>
<p>　　flag = 1;</p>
<p>　　ret = setsockopt ( sock, IPPROTO_TCP, TCP_NODELAY, (char *)&amp;flag, sizeof(flag) );</p>
<p>　　if (ret == -1) {</p>
<p>　　printf(&quot;Couldn&#8217;t setsockopt(TCP_NODELAY)\n&quot;);</p>
<p>　　exit(-1);</p>
<p>　　}</p>
<p>　　提示： 使用 Samba 的实验表明，在从 <a target="_blank" href="http://www.educity.cn/incsearch/search.asp?key=Microsoft">Microsoft</a>? <a target="_blank" href="http://www.educity.cn/incsearch/search.asp?key=Windows">Windows</a>? 服务器上的 Samba 驱动器上读取数据时，禁用 Nagle 算法几乎可以加倍提高读性能。</p>
<p>　　技巧 2. 最小化系统调用的负载</p>
<p>　　任何时候通过一个 socket 来读写数据时，您都是在使用一个系统调用(system call)。这个调用(例如 read 或 write )跨越了用户空间应用程序与内核的边界。另外，在进入内核之前，您的调用会通过 C 库来进入内核中的一个通用函数( system_call() )。从 system_call() 中，这个调用会进入文件系统层，内核会在这儿确定正在处理的是哪种类型的设备。最后，调用会进入 socket 层，数据就是在这里进行读取或进行排队从而通过 socket 进行传输的(这涉及数据的副本)。</p>
<p>　　这个过程说明系统调用不仅仅是在应用程序和内核中进行操作的，而且还要经过应用程序和内核中的很多层次。这个过程耗费的<a target="_blank" href="http://www.educity.cn/incsearch/search.asp?key=%D7%CA%D4%B4">资源</a>很高，因此调用次数越多，通过这个调用链进行的工作所需要的时间就越长，应用程序的性能也就越低。</p>
<p>　　由于我们无法避免这些系统调用，因此惟一的选择是最小化使用这些调用的次数。幸运的是，我们可以对这个过程进行控制。</p>
<p>　　解决方案</p>
<p>　　在将数据写入一个 socket 时，尽量一次写入所有的数据，而不是执行多次写数据的操作。对于读操作来说，最好传入可以支持的最大缓冲区，因为如果没有足够多的数据，内核也会试图填充 整个缓冲区(另外还需要保持 TCP 的通告窗口为打开状态)。这样，您就可以最小化调用的次数，并可以实现更好的整体性能。</p>
<p>　　技巧 3. 为 Bandwidth Delay Product 调节 TCP 窗口</p>
<p>　　TCP 的性能取决于几个方面的因素。两个最重要的因素是链接带宽(link bandwidth)(报文在网络上传输的速率)和 往返时间(round-trip time) 或 RTT(发送报文与接收到另一端的响应之间的延时)。这两个值确定了称为 Bandwidth Delay Product(BDP)的内容。</p>
<p>　　给定链接带宽和 RTT 之后，您就可以计算出 BDP 的值了，不过这代表什么意义呢?BDP 给出了一种简单的方法来计算理论上最优的 TCP socket 缓冲区大小(其中保存了排队等待传输和等待应用程序接收的数据)。如果缓冲区太小，那么 TCP 窗口就不能完全打开，这会对性能造成限制。如果缓冲区太大，那么宝贵的内存资源就会造成浪费。如果您设置的缓冲区大小正好合适，那么就可以完全利用可用的 带宽。下面我们来看一个例子： BDP = link_bandwidth * RTT</p>
<p>　　如果应用程序是通过一个 100Mbps 的局域网进行通信，其 RRT 为 50 ms，那么 BDP 就是： 100MBps * 0.050 sec / 8 = 0.625MB = 625KB</p>
<p>　　注意： 此处除以 8 是将位转换成通信使用的字节。</p>
<p>　　因此，我们可以将 TCP 窗口设置为 BDP 或 1.25MB。但是在 Linux 2.6 上默认的 TCP 窗口大小是 110KB，这会将连接的带宽限制为 2.2MBps，计算方法如下：</p>
<p>　　throughput = window_size / RTT</p>
<p>　　110KB / 0.050 = 2.2MBps</p>
<p>　　如果使用上面计算的窗口大小，我们得到的带宽就是 12.5MBps，计算方法如下：</p>
<p>　　625KB / 0.050 = 12.5MBps</p>
<p>　　差别的确很大，并且可以为 socket 提供更大的吞吐量。因此现在您就知道如何为您的 socket 计算最优的缓冲区大小了。但是又该如何来改变呢?</p>
<p>　　解决方案</p>
<p>　　Sockets API 提供了几个 socket 选项，其中两个可以用于修改 socket 的发送和接收缓冲区的大小。清单 2 展示了如何使用 SO_SNDBUF 和 SO_RCVBUF 选项来调整发送和接收缓冲区的大小。</p>
<p>　　注意： 尽管 socket 缓冲区的大小确定了通告 TCP 窗口的大小，但是 TCP 还在通告窗口内维护了一个拥塞窗口。因此，由于这个拥塞窗口的存在，给定的 socket 可能永远都不会利用最大的通告窗口。</p>
<p>　　清单 2. 手动设置发送和接收 socket 缓冲区大小</p>
<p>　　int ret, sock, sock_buf_size;</p>
<p>　　sock = socket ( AF_INET, SOCK_STREAM, 0 );</p>
<p>　　sock_buf_size = BDP;</p>
<p>　　ret = setsockopt ( sock, SOL_SOCKET, SO_SNDBUF,</p>
<p>　　(char *)&amp;sock_buf_size, sizeof(sock_buf_size) );</p>
<p>　　ret = setsockopt ( sock, SOL_SOCKET, SO_RCVBUF,</p>
<p>　　(char *)&amp;sock_buf_size, sizeof(sock_buf_size) );</p>
<p>　　在 Linux 2.6 内核中，发送缓冲区的大小是由调用用户来定义的，但是接收缓冲区会自动加倍。您可以进行 getsockopt 调用来验证每个缓冲区的大小。</p>
<p>　　就 window scaling 来说，TCP 最初可以支持最大为 64KB 的窗口(使用 16 位的值来定义窗口的大小)。采用 window scaling(RFC 1323)扩展之后，您就可以使用 32 位的值来表示窗口的大小了。GNU/Linux 中提供的 TCP/IP 栈可以支持这个选项(以及其他一些选项)。</p>
<p>　　提示： Linux 内核还包括了自动对这些 socket 缓冲区进行优化的能力(请参阅下面 表 1 中的 tcp_rmem 和 tcp_wmem )，不过这些选项会对整个栈造成影响。如果您只需要为一个连接或一类连接调节窗口的大小，那么这种机制也许不能满足您的需要了。</p>
<p>　　技巧 4. 动态优化 GNU/Linux TCP/IP 栈</p>
<p>　　<a target="_blank" href="http://www.educity.cn/incsearch/search.asp?key=%B1%EA%D7%BC">标准</a>的 GNU/Linux 发行版试图对各种部署情况都进行优化。这意味着标准的发行版可能并没有对您的环境进行特殊的优化。</p>
<p>　　解决方案</p>
<p>　　GNU/Linux 提供了很多可调节的内核参数，您可以使用这些参数为您自己的用途对<a target="_blank" href="http://www.educity.cn/incsearch/search.asp?key=%B2%D9%D7%F7%CF%B5%CD%B3">操作系统</a>进行动态配置。下面我们来了解一下影响 socket 性能的一些更重要的选项。</p>
<p>　　在 /proc 虚拟文件系统中存在一些可调节的内核参数。这个文件系统中的每个文件都表示一个或多个参数，它们可以通过 cat 工具进行读取，或使用 echo 命令进行修改。清单 3 展示了如何查询或启用一个可调节的参数(在这种情况中，可以在 TCP/IP 栈中启用 IP 转发)。</p>
<p>　　清单 3. 调优：在 TCP/IP 栈中启用 IP 转发</p>
<p>　　[root@camus]# cat /proc/sys/net/ipv4/ip_forward</p>
<p>　　0</p>
<p>　　[root@camus]# echo &quot;1&quot; &gt; /poc/sys/net/ipv4/ip_forward</p>
<p>　　[root@camus]# cat /proc/sys/net/ipv4/ip_forward</p>
<p>　　1</p>
<p>　　[root@camus]#</p>
<p>　　表 1 给出了几个可调节的参数，它们可以帮助您提高 Linux TCP/IP 栈的性能。</p>
<p>　　表 1. TCP/IP 栈性能使用的可调节内核参数 可调节的参数 默认值 选项说明</p>
<p>　　/proc/sys/net/core/rmem_default &quot;110592&quot; 定义默认的接收窗口大小;对于更大的 BDP 来说，这个大小也应该更大。</p>
<p>　　/proc/sys/net/core/rmem_max &quot;110592&quot; 定义接收窗口的最大大小;对于更大的 BDP 来说，这个大小也应该更大。</p>
<p>　　/proc/sys/net/core/wmem_default &quot;110592&quot; 定义默认的发送窗口大小;对于更大的 BDP 来说，这个大小也应该更大。</p>
<p>　　/proc/sys/net/core/wmem_max &quot;110592&quot; 定义发送窗口的最大大小;对于更大的 BDP 来说，这个大小也应该更大。</p>
<p>　　/proc/sys/net/ipv4/tcp_window_scaling　　　 &quot;1&quot; 启用 RFC 1323 定义的 window scaling;要支持超过 64KB 的窗口，必须启用该值。</p>
<p>　　/proc/sys/net/ipv4/tcp_sack &quot;1&quot; 启用有选择的应答(Selective Acknowledgment)，这可以通过有选择地应答乱序接收到的报文来提高性能(这样可以让发送者只发送丢失的报文段);(对于广域网通信来说)这 个选项应该启用，但是这会增加对 CPU 的占用。</p>
<p>　　/proc/sys/net/ipv4/tcp_fack &quot;1&quot; 启用转发应答(Forward Acknowledgment)，这可以进行有选择应答(SACK)从而减少拥塞情况的发生;这个选项也应该启用。</p>
<p>　　/proc/sys/net/ipv4/tcp_timestamps &quot;1&quot; 以一种比重发超时更精确的方法(请参阅 RFC 1323)来启用对 RTT 的计算;为了实现更好的性能应该启用这个选项。</p>
<p>　　/proc/sys/net/ipv4/tcp_mem &quot;24576 32768 49152&quot; 确定 TCP 栈应该如何反映内存使用;每个值的单位都是内存页(通常是 4KB)。第一个值是内存使用的下限。第二个值是内存压力模式开始对缓冲区使用应用压力的上限。第三个值是内存上限。在这个层次上可以将报文丢弃，从而减 少对内存的使用。对于较大的 BDP 可以增大这些值(但是要记住，其单位是内存页，而不是字节)。</p>
<p>　　/proc/sys/net/ipv4/tcp_wmem &quot;4096 16384 131072&quot; 为自动调优定义每个 socket 使用的内存。第一个值是为 socket 的发送缓冲区分配的最少字节数。第二个值是默认值(该值会被 wmem_default 覆盖)，缓冲区在系统负载不重的情况下可以增长到这个值。第三个值是发送缓冲区空间的最大字节数(该值会被 wmem_max 覆盖)。</p>
<p>　　/proc/sys/net/ipv4/tcp_rmem &quot;4096 87380 174760&quot; 与 tcp_wmem 类似，不过它表示的是为自动调优所使用的接收缓冲区的值。</p>
<p>　　/proc/sys/net/ipv4/tcp_low_latency &quot;0&quot; 允许 TCP/IP 栈适应在高吞吐量情况下低延时的情况;这个选项应该禁用。</p>
<p>　　/proc/sys/net/ipv4/tcp_westwood &quot;0&quot; 启用发送者端的拥塞控制算法，它可以维护对吞吐量的评估，并试图对带宽的整体利用情况进行优化;对于 WAN 通信来说应该启用这个选项。</p>
<p>　　/proc/sys/net/ipv4/tcp_bic &quot;1&quot; 为快速长距离网络启用 Binary Increase Congestion;这样可以更好地利用以 GB 速度进行操作的链接;对于 WAN 通信应该启用这个选项。</p>
<p>　　与任何调优努力一样，最好的方法实际上就是不断进行实验。您的应用程序的行为、处理器的速度以及可用内存的多少都会影响到这些参数影响性能的方 式。在某些情况中，您认为有益的操作可能恰恰是有害的(反之亦然)。因此，我们需要逐一试验各个选项，然后检查每个选项的结果。换而言之，我们需要相信自 己的经验，但是对每次修改都要进行验证。</p>
<p>　　提示： 下面介绍一个有关永久性配置的问题。注意，如果您重新启动了 GNU/Linux 系统，那么您所需要的任何可调节的内核参数都会恢复成默认值。为了将您所设置的值作为这些参数的默认值，可以使用 /etc/sysctl.conf 在系统启动时将这些参数配置成您所设置的值。</p>
<p>　　GNU/Linux 工具</p>
<p>　　GNU/Linux 对我非常有吸引力，这是因为其中有很多工具可以使用。尽管其中大部分都是命令行工具，但是它们都非常有用，而</p>
]]></content:encoded>
			<wfw:commentRss>http://www.oursit.com/archives/135.html/feed</wfw:commentRss>
		</item>
		<item>
		<title>MYSQL复制功能</title>
		<link>http://www.oursit.com/archives/131.html</link>
		<comments>http://www.oursit.com/archives/131.html#comments</comments>
		<pubDate>Tue, 02 Sep 2008 14:39:46 +0000</pubDate>
		<dc:creator>Skylin</dc:creator>
		
		<category><![CDATA[mysql]]></category>

		<category><![CDATA[mysql复制]]></category>

		<guid isPermaLink="false">http://www.oursit.com/?p=131</guid>
		<description><![CDATA[     在前一个公司工作的时候，因为公司运营的系统的数据库中有金钱买卖相关的很重要的数据，服务器又是在别人那里，所以需要进行时时备份数据库，所以就使用 MYSQL复制功能来达到时时备份的效果，下面我记录下设置过程，其中为了偷懒有些地方是我抄的别人的，呵呵，但是个人觉得又精简又完整。]]></description>
			<content:encoded><![CDATA[<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 在前一个公司工作的时候，因为公司运营的系统的数据库中有金钱买卖相关的很重要的数据，服务器又是在别人那里，所以需要进行时时备份数据库，所以就使用MYSQL复制功能来达到时时备份的效果，下面我记录下设置过程，其中为了偷懒有些地方是我抄的别人的，呵呵，但是个人觉得又精简又完整。</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </p>
<p id="p1-n3">Server_1：公网主服务器（假设为192.168.100.1）<br id="p1-n4" /><br />
创建一个支持备份的用户<br id="p1-n5" /><br />
GRANT REPLICATION SLAVE,RELOAD,SUPER ON *.* TO <a href="mailto:backup@%27%%27" id="p1-n6">backup@&#8217;%&#8217;</a> IDENTIFIED BY &#8216;1234&#8242;;<br id="p1-n7" /><br />
//注意backup为账号1234为密码，请根据具体情况设置<br id="p1-n8" /><br />
用vi打开my.cnf<br id="p1-n9" /><br />
设置：（字段信息可能已经存在，请先搜索位置）<br id="p1-n10" /><br />
server-id = 1<br id="p1-n11" /><br />
log-bin = shop-bin</p>
<p id="p1-n12">Server_2：公网只读服务器（假设为192.168.100.2）<br id="p1-n13" /><br />
用vi 打开 my.cnf<br id="p1-n14" /><br />
设置：<br id="p1-n15" /><br />
server-id = 2<br id="p1-n16" /><br />
master-host=IP地址 //Server_1的IP<br id="p1-n17" /><br />
master-user=backup //Server_1的账号<br id="p1-n18" /><br />
master-password=1234 //Server_1的密码<br id="p1-n19" /><br />
replicate-do-db=shop //Server_1的数据库名称<br id="p1-n20" /><br />
注意：从服务器上的ID不能和主服务器上的ID一样</p>
<p id="p1-n21">#[Mysql双向同步配置]<br id="p1-n22" /><br />
Server_1：公网主服务器（假设为192.168.100.1）<br id="p1-n23" /><br />
设置：<br id="p1-n24" /><br />
log-slave-updates&nbsp; //这一句话很重要,只有加上这一句话,才能将信息copy到从服务器上<br id="p1-n25" /><br />
master-host=IP地址 //Server_3的IP地址<br id="p1-n26" /><br />
master-user=backup //Server_3的账号<br id="p1-n27" /><br />
master-password=1234 //Server_3的密码<br id="p1-n28" /><br />
replicate-do-db=shop //Server_3的数据库</p>
<p id="p1-n29">Server_3服务器配置（假设IP为：192.168.100.3）<br id="p1-n30" /><br />
设置：<br id="p1-n31" /><br />
server-id = 3<br id="p1-n32" /><br />
bin-log=shop-bin<br id="p1-n33" /><br />
master-host=IP地址 //Server_1的IP<br id="p1-n34" /><br />
master-user=backup //Server_1的账号<br id="p1-n35" /><br />
master-password=1234 //Server_1的密码<br id="p1-n36" /><br />
replicate-do-db=shop //Server_1的数据库名称</p>
<p id="p1-n37">三台服务器设置完成后需要重新启动才能生效！<br id="p1-n38" /><br />
重启顺序建议：<br id="p1-n39" /><br />
Server_1<br id="p1-n40" /><br />
Server_3<br id="p1-n41" /><br />
Server_2</p>
<p id="p1-n43">&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<div class="post-content" id="p1-n57">
<p id="p1-n58">主服务器： 192.168.1.222</p>
<p id="p1-n59">从服务器： 192.168.1.205</p>
<p id="p1-n60">主服务器：</p>
<p id="p1-n61">backup数据库为需要复制的数据库，设置 replicate@192.168.1.205 有访问权限:</p>
<p id="p1-n62">grant file on *.* to &#8216;replicate&#8217;@'192.168.1.205&#8242; IDENTIFIED BY &#8216;password&#8217;;</p>
<p id="p1-n63">my.cnf中设置：</p>
<p id="p1-n64"><a href="http://www.uuki.com/blog/mysqld" id="p1-n65">mysqld</a></p>
<p id="p1-n66">server-id=1</p>
<pre id="p1-n67">
    log-bin</pre>
<pre id="p1-n68">
    sql-bin-update-same</pre>
<pre id="p1-n69">
    binlog-do-db=backup //只做backup数据库日志</pre>
<p id="p1-n70">导出backup数据库重起主服务器运行</p>
<p id="p1-n71">mysql&gt;show master status;获得LOG_FILE和LOG_FILE_POS 从服务器： 设置my.cnf:</p>
<p id="p1-n72"><a href="http://www.uuki.com/blog/mysqld" id="p1-n73">mysqld</a></p>
<p id="p1-n74">server-id=2;不能与master的相同，如果有多台slave，此值必须唯一，如果不填写，slava默认为2</p>
<pre id="p1-n75">
     master-host=192.168.1.222</pre>
<pre id="p1-n76">
     master-user=replicate</pre>
<pre id="p1-n77">
     master-password=password</pre>
<pre id="p1-n78">
     master-port=3306</pre>
<pre id="p1-n79">
     master-connect-retry=60</pre>
<pre id="p1-n80">
     replicate-do-db=backup;数据库名</pre>
<p id="p1-n81">用下述命令启动从mysqld</p>
<p id="p1-n82">mysqld &#8211;skip-slave</p>
<p id="p1-n83">登陆从mysql，导入数据库然后检查数据是否进入，然后运行</p>
<p id="p1-n84">mysql&gt; CHANGE MASTER TO</p>
<pre id="p1-n85">
   -&gt; MASTER_HOST='192.168.1.222',</pre>
<pre id="p1-n86">
   -&gt; MASTER_USER='replicate',</pre>
<pre id="p1-n87">
   -&gt; MASTER_PASSWORD='password',</pre>
<pre id="p1-n88">
   -&gt; MASTER_LOG_FILE='www-bin.001',  // show master status看到的file</pre>
<pre id="p1-n89">
   -&gt;  MASTER_LOG_POS=73;  //show master status看到的pos</pre>
<p id="p1-n90">mysql&gt;slave start;</p>
<p id="p1-n91">如果看见数据库记录和主服务器不符，就运行</p>
<p id="p1-n92">mysql&gt;slave stop;</p>
<p id="p1-n93">删除数据库，重新导入，然后再启动slave</p>
<p id="p1-n94">测试成功后，启动从服务器就不需要再使用&#8211;skip-slave参数</p>
<p id="p1-n95">几个命令：</p>
<p id="p1-n96">show master status；在主服务器上看状态</p>
<p id="p1-n97">show slave status；在从服务器上看状态</p>
<p id="p1-n98">change master &#8230;；在从服务器上更改主服务器信息，如果服务器更改了信息，则更改my.cnf无效，因为已经把信息写入master.info文件中，必须使用此命令更改</p>
<p id="p1-n99">FLUSH PRIVILEGES;不重起服务器，使权限马上更新</p>
<p>如果你想使用<span class="hilite2" id="cda950">复制</span>数据文件的方式来备份数据库，只要在从服务器上的<span class="hilite1" id="cda951">mysql</span>命令行先键入slave stop;然后<span class="hilite2" id="cda952">复制</span>数据库文件，<span class="hilite2" id="cda953">复制</span>好了，再 在<span class="hilite1" id="cda954">mysql</span>命令行键入slave start;启动从服务器，这样就即备份了数据有保证了数据完整性，而且整个过程中主服务器的<span class="hilite1" id="cda955">mysql</span>无需停止。</p>
</div>
]]></content:encoded>
			<wfw:commentRss>http://www.oursit.com/archives/131.html/feed</wfw:commentRss>
		</item>
		<item>
		<title>PHP 真正的ZIP文件操作类</title>
		<link>http://www.oursit.com/archives/127.html</link>
		<comments>http://www.oursit.com/archives/127.html#comments</comments>
		<pubDate>Sun, 31 Aug 2008 03:31:01 +0000</pubDate>
		<dc:creator>Skylin</dc:creator>
		
		<category><![CDATA[PHP]]></category>

		<category><![CDATA[zip压缩]]></category>

		<guid isPermaLink="false">http://www.oursit.com/?p=127</guid>
		<description><![CDATA[  在开发的过程中有时候我们可能需要使用到用zip来压缩和解压缩某个包，但是不是所有服务器我们都能控制（比如虚拟主机商提供的），所以我们可能在很多环境下都不能使用PHP的ZIP扩展库，下面是我经常会用到的一个zip的PHP类，这里我的本意是想说我们大家可以研究下zip的格式，至于压缩数据其实就是使用到了PHP的gz相关的函数。]]></description>
			<content:encoded><![CDATA[<p>&nbsp; 在开发的过程中有时候我们可能需要使用到用zip来压缩和解压缩某个包，但是不是所有服务器我们都能控制（比如虚拟主机商提供的），所以我们可能在很多 环境下都不能使用PHP的ZIP扩展库，下面是我经常会用到的一个zip的PHP类，这里我的本意是想说我们大家可以研究下zip的格式，至于压缩数据其 实就是使用到了PHP的<span><span>gz相关的函数。</span></span></p>
<div>
<div class="dp-highlighter">
<div class="bar">&nbsp;</div>
<ol start="1" class="dp-c">
<li class="alt"><span><span>&lt;?&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span><span class="keyword">class</span><span>&nbsp;zip&nbsp;&nbsp;&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>{&nbsp;&nbsp;&nbsp;</span></li>
<li><span>&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span><span class="keyword">var</span><span>&nbsp;</span><span class="vars">$datasec</span><span>,&nbsp;</span><span class="vars">$ctrl_dir</span><span>&nbsp;=&nbsp;</span><span class="keyword">array</span><span>();&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span><span class="keyword">var</span><span>&nbsp;</span><span class="vars">$eof_ctrl_dir</span><span>&nbsp;=&nbsp;</span><span class="string">&quot;\x50\x4b\x05\x06\x00\x00\x00\x00&quot;</span><span>;&nbsp;&nbsp;&nbsp;</span></span></li>
<li class="alt"><span><span class="keyword">var</span><span>&nbsp;</span><span class="vars">$old_offset</span><span>&nbsp;=&nbsp;0;&nbsp;</span><span class="keyword">var</span><span>&nbsp;</span><span class="vars">$dirs</span><span>&nbsp;=&nbsp;Array(</span><span class="string">&quot;.&quot;</span><span>);&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span><span class="keyword">function</span><span>&nbsp;get_List(</span><span class="vars">$zip_name</span><span>)&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>{&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;<span class="vars">$zip</span><span>&nbsp;=&nbsp;@</span><span class="func">fopen</span><span>(</span><span class="vars">$zip_name</span><span>,&nbsp;</span><span class="string">&#8216;rb&#8217;</span><span>);&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;<span class="keyword">if</span><span>(!</span><span class="vars">$zip</span><span>)&nbsp;</span><span class="keyword">return</span><span>(0);&nbsp;&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>&nbsp;&nbsp;<span class="vars">$centd</span><span>&nbsp;=&nbsp;</span><span class="vars">$this</span><span>-&gt;ReadCentralDir(</span><span class="vars">$zip</span><span>,</span><span class="vars">$zip_name</span><span>);&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;@<span class="func">rewind</span><span>(</span><span class="vars">$zip</span><span>);&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;@<span class="func">fseek</span><span>(</span><span class="vars">$zip</span><span>,&nbsp;</span><span class="vars">$centd</span><span>[</span><span class="string">'offset'</span><span>]);&nbsp;&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;</span></li>
<li><span>&nbsp;&nbsp;<span class="keyword">for</span><span>&nbsp;(</span><span class="vars">$i</span><span>=0;&nbsp;</span><span class="vars">$i</span><span>&lt;</span><span class="vars">$centd</span><span>[</span><span class="string">'entries'</span><span>];&nbsp;</span><span class="vars">$i</span><span>++)&nbsp;&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>&nbsp;&nbsp;{&nbsp;&nbsp;&nbsp;</span></li>
<li><span>&nbsp;&nbsp;&nbsp;<span class="vars">$header</span><span>&nbsp;=&nbsp;</span><span class="vars">$this</span><span>-&gt;ReadCentralFileHeaders(</span><span class="vars">$zip</span><span>);&nbsp;&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;<span class="vars">$header</span><span>[</span><span class="string">'index'</span><span>]&nbsp;=&nbsp;</span><span class="vars">$i</span><span>;</span><span class="vars">$info</span><span>[</span><span class="string">'filename'</span><span>]&nbsp;=&nbsp;</span><span class="vars">$header</span><span>[</span><span class="string">'filename'</span><span>];&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;<span class="vars">$info</span><span>[</span><span class="string">'stored_filename'</span><span>]&nbsp;=&nbsp;</span><span class="vars">$header</span><span>[</span><span class="string">'stored_filename'</span><span>];&nbsp;&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;<span class="vars">$info</span><span>[</span><span class="string">'size'</span><span>]&nbsp;=&nbsp;</span><span class="vars">$header</span><span>[</span><span class="string">'size'</span><span>];</span></span></li>
<li class="alt"><span><span>&nbsp;&nbsp; </span><span class="vars">$info</span><span>[</span><span class="string">'compressed_size'</span><span>]=</span><span class="vars">$header</span><span>[</span><span class="string">'compressed_size'</span><span>];&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;<span class="vars">$info</span><span>[</span><span class="string">'crc'</span><span>]&nbsp;=&nbsp;</span><span class="func">strtoupper</span><span>(</span><span class="func">dechex</span><span>(&nbsp;</span><span class="vars">$header</span><span>[</span><span class="string">'crc'</span><span>]&nbsp;));&nbsp;&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;<span class="vars">$info</span><span>[</span><span class="string">'mtime'</span><span>]&nbsp;=&nbsp;</span><span class="vars">$header</span><span>[</span><span class="string">'mtime'</span><span>];&nbsp;</span><span class="vars">$info</span><span>[</span><span class="string">'comment'</span><span>]&nbsp;=&nbsp;</span><span class="vars">$header</span><span>[</span><span class="string">'comment'</span><span>];&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;<span class="vars">$info</span><span>[</span><span class="string">'folder'</span><span>]&nbsp;=&nbsp;(</span><span class="vars">$header</span><span>[</span><span class="string">'external'</span><span>]==0&#215;41FF0010||</span><span class="vars">$header</span><span>[</span><span class="string">'external'</span><span>]==16)?1:0;&nbsp;&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;<span class="vars">$info</span><span>[</span><span class="string">'index'</span><span>]&nbsp;=&nbsp;</span><span class="vars">$header</span><span>[</span><span class="string">'index'</span><span>];</span><span class="vars">$info</span><span>[</span><span class="string">'status'</span><span>]&nbsp;=&nbsp;</span><span class="vars">$header</span><span>[</span><span class="string">'status'</span><span>];&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;<span class="vars">$ret</span><span>[]=</span><span class="vars">$info</span><span>;&nbsp;unset(</span><span class="vars">$header</span><span>);&nbsp;&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>&nbsp;&nbsp;}&nbsp;&nbsp;&nbsp;</span></li>
<li><span><span class="keyword">return</span><span>&nbsp;</span><span class="vars">$ret</span><span>;&nbsp;&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>}&nbsp;&nbsp;&nbsp;</span></li>
<li><span><span class="keyword">function</span><span>&nbsp;Add(</span><span class="vars">$files</span><span>,</span><span class="vars">$compact</span><span>)&nbsp;&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>{&nbsp;&nbsp;&nbsp;</span></li>
<li><span><span class="keyword">if</span><span>(!</span><span class="func">is_array</span><span>(</span><span class="vars">$files</span><span>[0]))&nbsp;</span><span class="vars">$files</span><span>=Array(</span><span class="vars">$files</span><span>);&nbsp;&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;</span></li>
<li><span><span class="keyword">for</span><span>(</span><span class="vars">$i</span><span>=0;</span><span class="vars">$files</span><span>[</span><span class="vars">$i</span><span>];</span><span class="vars">$i</span><span>++){&nbsp;&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;<span class="vars">$fn</span><span>&nbsp;=&nbsp;</span><span class="vars">$files</span><span>[</span><span class="vars">$i</span><span>];&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;<span class="keyword">if</span><span>(!in_Array(dirname(</span><span class="vars">$fn</span><span>[0]),</span><span class="vars">$this</span><span>-&gt;dirs))&nbsp;&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;<span class="vars">$this</span><span>-&gt;add_Dir(dirname(</span><span class="vars">$fn</span><span>[0]));&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;<span class="keyword">if</span><span>(</span><span class="func">basename</span><span>(</span><span class="vars">$fn</span><span>[0]))&nbsp;&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;<span class="vars">$ret</span><span>[</span><span class="func">basename</span><span>(</span><span class="vars">$fn</span><span>[0])]=</span><span class="vars">$this</span><span>-&gt;add_File(</span><span class="vars">$fn</span><span>[1],</span><span class="vars">$fn</span><span>[0],</span><span class="vars">$compact</span><span>);&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>}&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span><span class="keyword">return</span><span>&nbsp;</span><span class="vars">$ret</span><span>;&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>}&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;</span></li>
<li><span><span class="keyword">function</span><span>&nbsp;get_file()&nbsp;&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>{&nbsp;&nbsp;&nbsp;</span></li>
<li><span>&nbsp;&nbsp;<span class="vars">$data</span><span>&nbsp;=&nbsp;implode(</span><span class="string">&#8221;</span><span>,&nbsp;</span><span class="vars">$this</span><span>&nbsp;-&gt;&nbsp;datasec);&nbsp;&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>&nbsp;&nbsp;<span class="vars">$ctrldir</span><span>&nbsp;=&nbsp;implode(</span><span class="string">&#8221;</span><span>,&nbsp;</span><span class="vars">$this</span><span>&nbsp;-&gt;&nbsp;ctrl_dir);&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;<span class="keyword">return</span><span>&nbsp;</span><span class="vars">$data</span><span>&nbsp;.&nbsp;</span><span class="vars">$ctrldir</span><span>&nbsp;.&nbsp;</span><span class="vars">$this</span><span>&nbsp;-&gt;&nbsp;eof_ctrl_dir&nbsp;.&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;pack(<span class="string">&#8216;v&#8217;</span><span>,&nbsp;sizeof(</span><span class="vars">$this</span><span>&nbsp;-&gt;&nbsp;ctrl_dir)).pack(</span><span class="string">&#8216;v&#8217;</span><span>,&nbsp;sizeof(</span><span class="vars">$this</span><span>&nbsp;-&gt;&nbsp;ctrl_dir)).&nbsp;&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;pack(<span class="string">&#8216;V&#8217;</span><span>,&nbsp;</span><span class="func">strlen</span><span>(</span><span class="vars">$ctrldir</span><span>))&nbsp;.&nbsp;pack(</span><span class="string">&#8216;V&#8217;</span><span>,&nbsp;</span><span class="func">strlen</span><span>(</span><span class="vars">$data</span><span>))&nbsp;.&nbsp;</span><span class="string">&quot;\x00\x00&quot;</span><span>;&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>}&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;</span></li>
<li><span><span class="keyword">function</span><span>&nbsp;add_dir(</span><span class="vars">$name</span><span>)&nbsp;&nbsp;&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>{&nbsp;&nbsp;&nbsp;&nbsp;</span></li>
<li><span>&nbsp;&nbsp;<span class="vars">$name</span><span>&nbsp;=&nbsp;</span><span class="func">str_replace</span><span>(</span><span class="string">&quot;\\&quot;,&nbsp;&quot;</span><span>/&quot;,&nbsp;</span><span class="vars">$name</span><span>);&nbsp;&nbsp;&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>&nbsp;&nbsp;<span class="vars">$fr</span><span>&nbsp;=&nbsp;</span><span class="string">&quot;\x50\x4b\x03\x04\x0a\x00\x00\x00\x00\x00\x00\x00\x00\x00&quot;</span><span>;&nbsp;&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;<span class="vars">$fr</span><span>&nbsp;.=&nbsp;pack(</span><span class="string">&quot;V&quot;</span><span>,0).pack(</span><span class="string">&quot;V&quot;</span><span>,0).pack(</span><span class="string">&quot;V&quot;</span><span>,0).pack(</span><span class="string">&quot;v&quot;</span><span>,&nbsp;</span><span class="func">strlen</span><span>(</span><span class="vars">$name</span><span>)&nbsp;);&nbsp;&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;<span class="vars">$fr</span><span>&nbsp;.=&nbsp;pack(</span><span class="string">&quot;v&quot;</span><span>,&nbsp;0&nbsp;).</span><span class="vars">$name</span><span>.pack(</span><span class="string">&quot;V&quot;</span><span>,&nbsp;0).pack(</span><span class="string">&quot;V&quot;</span><span>,&nbsp;0).pack(</span><span class="string">&quot;V&quot;</span><span>,&nbsp;0);&nbsp;&nbsp;&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>&nbsp;&nbsp;<span class="vars">$this</span><span>&nbsp;-&gt;&nbsp;datasec[]&nbsp;=&nbsp;</span><span class="vars">$fr</span><span>;&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;<span class="vars">$new_offset</span><span>&nbsp;=&nbsp;</span><span class="func">strlen</span><span>(implode(</span><span class="string">&quot;&quot;</span><span>,&nbsp;</span><span class="vars">$this</span><span>-&gt;datasec));&nbsp;&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;<span class="vars">$cdrec</span><span>&nbsp;=&nbsp;</span><span class="string">&quot;\x50\x4b\x01\x02\x00\x00\x0a\x00\x00\x00\x00\x00\x00\x00\x00\x00&quot;</span><span>;&nbsp;&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;<span class="vars">$cdrec</span><span>&nbsp;.=&nbsp;pack(</span><span class="string">&quot;V&quot;</span><span>,0).pack(</span><span class="string">&quot;V&quot;</span><span>,0).pack(</span><span class="string">&quot;V&quot;</span><span>,0).pack(</span><span class="string">&quot;v&quot;</span><span>,&nbsp;</span><span class="func">strlen</span><span>(</span><span class="vars">$name</span><span>)&nbsp;);&nbsp;&nbsp;&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>&nbsp;&nbsp;<span class="vars">$cdrec</span><span>&nbsp;.=&nbsp;pack(</span><span class="string">&quot;v&quot;</span><span>,&nbsp;0&nbsp;).pack(</span><span class="string">&quot;v&quot;</span><span>,&nbsp;0&nbsp;).pack(</span><span class="string">&quot;v&quot;</span><span>,&nbsp;0&nbsp;).pack(</span><span class="string">&quot;v&quot;</span><span>,&nbsp;0&nbsp;);&nbsp;&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;<span class="vars">$ext</span><span>&nbsp;=&nbsp;</span><span class="string">&quot;\xff\xff\xff\xff&quot;</span><span>;&nbsp;&nbsp;&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>&nbsp;&nbsp;<span class="vars">$cdrec</span><span>&nbsp;.=&nbsp;pack(</span><span class="string">&quot;V&quot;</span><span>,&nbsp;16&nbsp;).pack(</span><span class="string">&quot;V&quot;</span><span>,&nbsp;</span><span class="vars">$this</span><span>&nbsp;-&gt;&nbsp;old_offset&nbsp;).</span><span class="vars">$name</span><span>;&nbsp;&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;<span class="vars">$this</span><span>&nbsp;-&gt;&nbsp;ctrl_dir[]&nbsp;=&nbsp;</span><span class="vars">$cdrec</span><span>;&nbsp;&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;<span class="vars">$this</span><span>&nbsp;-&gt;&nbsp;old_offset&nbsp;=&nbsp;</span><span class="vars">$new_offset</span><span>;&nbsp;&nbsp;&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>&nbsp;&nbsp;<span class="vars">$this</span><span>&nbsp;-&gt;&nbsp;dirs[]&nbsp;=&nbsp;</span><span class="vars">$name</span><span>;&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>}&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;</span></li>
<li><span><span class="keyword">function</span><span>&nbsp;add_File(</span><span class="vars">$data</span><span>,&nbsp;</span><span class="vars">$name</span><span>,&nbsp;</span><span class="vars">$compact</span><span>&nbsp;=&nbsp;1)&nbsp;&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>{&nbsp;&nbsp;&nbsp;</span></li>
<li><span>&nbsp;&nbsp;<span class="vars">$name</span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;=&nbsp;</span><span class="func">str_replace</span><span>(</span><span class="string">&#8216;\\&#8217;,&nbsp;&#8217;</span><span>/&#8217;,&nbsp;</span><span class="vars">$name</span><span>);&nbsp;&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>&nbsp;&nbsp;<span class="vars">$dtime</span><span>&nbsp;&nbsp;&nbsp;&nbsp;=&nbsp;</span><span class="func">dechex</span><span>(</span><span class="vars">$this</span><span>-&gt;DosTime());&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;<span class="vars">$hexdtime</span><span>&nbsp;=&nbsp;</span><span class="string">&#8216;\x&#8217;</span><span>&nbsp;.&nbsp;</span><span class="vars">$dtime</span><span>[6]&nbsp;.&nbsp;</span><span class="vars">$dtime</span><span>[7].</span><span class="string">&#8216;\x&#8217;</span><span>.</span><span class="vars">$dtime</span><span>[4]&nbsp;.&nbsp;</span><span class="vars">$dtime</span><span>[5]&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;&nbsp;.&nbsp;<span class="string">&#8216;\x&#8217;</span><span>&nbsp;.&nbsp;</span><span class="vars">$dtime</span><span>[2]&nbsp;.&nbsp;</span><span class="vars">$dtime</span><span>[3].</span><span class="string">&#8216;\x&#8217;</span><span>.</span><span class="vars">$dtime</span><span>[0].</span><span class="vars">$dtime</span><span>[1];&nbsp;&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>&nbsp;&nbsp;<span class="func">eval</span><span>(</span><span class="string">&#8216;$hexdtime&nbsp;=&nbsp;&quot;&#8217;</span><span>&nbsp;.&nbsp;</span><span class="vars">$hexdtime</span><span>&nbsp;.&nbsp;</span><span class="string">&#8216;&quot;;&#8217;</span><span>);&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;<span class="keyword">if</span><span>(</span><span class="vars">$compact</span><span>)&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;<span class="vars">$fr</span><span>&nbsp;=&nbsp;</span><span class="string">&quot;\x50\x4b\x03\x04\x14\x00\x00\x00\x08\x00&quot;</span><span>.</span><span class="vars">$hexdtime</span><span>;&nbsp;&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>&nbsp;&nbsp;<span class="keyword">else</span><span>&nbsp;</span><span class="vars">$fr</span><span>&nbsp;=&nbsp;</span><span class="string">&quot;\x50\x4b\x03\x04\x0a\x00\x00\x00\x00\x00&quot;</span><span>.</span><span class="vars">$hexdtime</span><span>;&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;<span class="vars">$unc_len</span><span>&nbsp;=&nbsp;</span><span class="func">strlen</span><span>(</span><span class="vars">$data</span><span>);&nbsp;</span><span class="vars">$crc</span><span>&nbsp;=&nbsp;crc32(</span><span class="vars">$data</span><span>);&nbsp;&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;</span></li>
<li><span>&nbsp;&nbsp;<span class="keyword">if</span><span>(</span><span class="vars">$compact</span><span>){&nbsp;&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;<span class="vars">$zdata</span><span>&nbsp;=&nbsp;gzcompress(</span><span class="vars">$data</span><span>);&nbsp;</span><span class="vars">$c_len</span><span>&nbsp;=&nbsp;</span><span class="func">strlen</span><span>(</span><span class="vars">$zdata</span><span>);&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;&nbsp;<span class="vars">$zdata</span><span>&nbsp;=&nbsp;</span><span class="func">substr</span><span>(</span><span class="func">substr</span><span>(</span><span class="vars">$zdata</span><span>,&nbsp;0,&nbsp;</span><span class="func">strlen</span><span>(</span><span class="vars">$zdata</span><span>)&nbsp;-&nbsp;4),&nbsp;2);&nbsp;&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>&nbsp;&nbsp;}<span class="keyword">else</span><span>{&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;&nbsp;<span class="vars">$zdata</span><span>&nbsp;=&nbsp;</span><span class="vars">$data</span><span>;&nbsp;&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>&nbsp;&nbsp;}&nbsp;&nbsp;&nbsp;</span></li>
<li><span>&nbsp;&nbsp;<span class="vars">$c_len</span><span>=</span><span class="func">strlen</span><span>(</span><span class="vars">$zdata</span><span>);&nbsp;&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>&nbsp;&nbsp;<span class="vars">$fr</span><span>&nbsp;.=&nbsp;pack(</span><span class="string">&#8216;V&#8217;</span><span>,&nbsp;</span><span class="vars">$crc</span><span>).pack(</span><span class="string">&#8216;V&#8217;</span><span>,&nbsp;</span><span class="vars">$c_len</span><span>).pack(</span><span class="string">&#8216;V&#8217;</span><span>,&nbsp;</span><span class="vars">$unc_len</span><span>);&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;<span class="vars">$fr</span><span>&nbsp;.=&nbsp;pack(</span><span class="string">&#8216;v&#8217;</span><span>,&nbsp;</span><span class="func">strlen</span><span>(</span><span class="vars">$name</span><span>)).pack(</span><span class="string">&#8216;v&#8217;</span><span>,&nbsp;0).</span><span class="vars">$name</span><span>.</span><span class="vars">$zdata</span><span>;&nbsp;&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;</span></li>
<li><span>&nbsp;&nbsp;<span class="vars">$fr</span><span>&nbsp;.=&nbsp;pack(</span><span class="string">&#8216;V&#8217;</span><span>,&nbsp;</span><span class="vars">$crc</span><span>).pack(</span><span class="string">&#8216;V&#8217;</span><span>,&nbsp;</span><span class="vars">$c_len</span><span>).pack(</span><span class="string">&#8216;V&#8217;</span><span>,&nbsp;</span><span class="vars">$unc_len</span><span>);&nbsp;&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;</span></li>
<li><span>&nbsp;&nbsp;<span class="vars">$this</span><span>&nbsp;-&gt;&nbsp;datasec[]&nbsp;=&nbsp;</span><span class="vars">$fr</span><span>;&nbsp;&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>&nbsp;&nbsp;<span class="vars">$new_offset</span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;=&nbsp;</span><span class="func">strlen</span><span>(implode(</span><span class="string">&#8221;</span><span>,&nbsp;</span><span class="vars">$this</span><span>-&gt;datasec));&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;<span class="keyword">if</span><span>(</span><span class="vars">$compact</span><span>)&nbsp;&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="vars">$cdrec</span><span>&nbsp;=&nbsp;</span><span class="string">&quot;\x50\x4b\x01\x02\x00\x00\x14\x00\x00\x00\x08\x00&quot;</span><span>;&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;<span class="keyword">else</span><span>&nbsp;</span><span class="vars">$cdrec</span><span>&nbsp;=&nbsp;</span><span class="string">&quot;\x50\x4b\x01\x02\x14\x00\x0a\x00\x00\x00\x00\x00&quot;</span><span>;&nbsp;&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>&nbsp;&nbsp;<span class="vars">$cdrec</span><span>&nbsp;.=&nbsp;</span><span class="vars">$hexdtime</span><span>.pack(</span><span class="string">&#8216;V&#8217;</span><span>,&nbsp;</span><span class="vars">$crc</span><span>).pack(</span><span class="string">&#8216;V&#8217;</span><span>,&nbsp;</span><span class="vars">$c_len</span><span>).pack(</span><span class="string">&#8216;V&#8217;</span><span>,&nbsp;</span><span class="vars">$unc_len</span><span>);&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;<span class="vars">$cdrec</span><span>&nbsp;.=&nbsp;pack(</span><span class="string">&#8216;v&#8217;</span><span>,&nbsp;</span><span class="func">strlen</span><span>(</span><span class="vars">$name</span><span>)&nbsp;).pack(</span><span class="string">&#8216;v&#8217;</span><span>,&nbsp;0&nbsp;).pack(</span><span class="string">&#8216;v&#8217;</span><span>,&nbsp;0&nbsp;);&nbsp;&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>&nbsp;&nbsp;<span class="vars">$cdrec</span><span>&nbsp;.=&nbsp;pack(</span><span class="string">&#8216;v&#8217;</span><span>,&nbsp;0&nbsp;).pack(</span><span class="string">&#8216;v&#8217;</span><span>,&nbsp;0&nbsp;).pack(</span><span class="string">&#8216;V&#8217;</span><span>,&nbsp;32&nbsp;);&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;<span class="vars">$cdrec</span><span>&nbsp;.=&nbsp;pack(</span><span class="string">&#8216;V&#8217;</span><span>,&nbsp;</span><span class="vars">$this</span><span>&nbsp;-&gt;&nbsp;old_offset&nbsp;);&nbsp;&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;</span></li>
<li><span>&nbsp;&nbsp;<span class="vars">$this</span><span>&nbsp;-&gt;&nbsp;old_offset&nbsp;=&nbsp;</span><span class="vars">$new_offset</span><span>;&nbsp;&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>&nbsp;&nbsp;<span class="vars">$cdrec</span><span>&nbsp;.=&nbsp;</span><span class="vars">$name</span><span>;&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;<span class="vars">$this</span><span>&nbsp;-&gt;&nbsp;ctrl_dir[]&nbsp;=&nbsp;</span><span class="vars">$cdrec</span><span>;&nbsp;&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>&nbsp;&nbsp;<span class="keyword">return</span><span>&nbsp;true;&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>}&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;</span></li>
<li><span><span class="keyword">function</span><span>&nbsp;DosTime()&nbsp;{&nbsp;&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>&nbsp;&nbsp;<span class="vars">$timearray</span><span>&nbsp;=&nbsp;</span><span class="func">getdate</span><span>();&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;<span class="keyword">if</span><span>&nbsp;(</span><span class="vars">$timearray</span><span>[</span><span class="string">'year'</span><span>]&nbsp;&lt;&nbsp;1980)&nbsp;{&nbsp;&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;<span class="vars">$timearray</span><span>[</span><span class="string">'year'</span><span>]&nbsp;=&nbsp;1980;&nbsp;</span><span class="vars">$timearray</span><span>[</span><span class="string">'mon'</span><span>]&nbsp;=&nbsp;1;&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;&nbsp;<span class="vars">$timearray</span><span>[</span><span class="string">'mday'</span><span>]&nbsp;=&nbsp;1;&nbsp;</span><span class="vars">$timearray</span><span>[</span><span class="string">'hours'</span><span>]&nbsp;=&nbsp;0;&nbsp;&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;<span class="vars">$timearray</span><span>[</span><span class="string">'minutes'</span><span>]&nbsp;=&nbsp;0;&nbsp;</span><span class="vars">$timearray</span><span>[</span><span class="string">'seconds'</span><span>]&nbsp;=&nbsp;0;&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;}&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;<span class="keyword">return</span><span>&nbsp;((</span><span class="vars">$timearray</span><span>[</span><span class="string">'year'</span><span>]&nbsp;-&nbsp;1980)&nbsp;&lt;&lt;&nbsp;25)&nbsp;|&nbsp;(</span><span class="vars">$timearray</span><span>[</span><span class="string">'mon'</span><span>]&nbsp;&lt;&lt;&nbsp;21)&nbsp;|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></span></li>
<li class="alt"><span><span>&nbsp;&nbsp; (</span><span class="vars">$timearray</span><span>[</span><span class="string">'mday'</span><span>]&nbsp;&lt;&lt;&nbsp;16)&nbsp;|&nbsp;(</span><span class="vars">$timearray</span><span>[</span><span class="string">'hours'</span><span>]&nbsp;&lt;&lt;&nbsp;11)&nbsp;|&nbsp;&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;(<span class="vars">$timearray</span><span>[</span><span class="string">'minutes'</span><span>]&nbsp;&lt;&lt;&nbsp;5)&nbsp;|&nbsp;(</span><span class="vars">$timearray</span><span>[</span><span class="string">'seconds'</span><span>]&nbsp;&gt;&gt;&nbsp;1);&nbsp;&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>}&nbsp;&nbsp;&nbsp;</span></li>
<li><span>&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span><span class="keyword">function</span><span>&nbsp;Extract&nbsp;(&nbsp;</span><span class="vars">$zn</span><span>,&nbsp;</span><span class="vars">$to</span><span>,&nbsp;</span><span class="vars">$index</span><span>&nbsp;=&nbsp;Array(-1)&nbsp;)&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>{&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;<span class="vars">$ok</span><span>&nbsp;=&nbsp;0;&nbsp;</span><span class="vars">$zip</span><span>&nbsp;=&nbsp;@</span><span class="func">fopen</span><span>(</span><span class="vars">$zn</span><span>,</span><span class="string">&#8216;rb&#8217;</span><span>);&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;<span class="keyword">if</span><span>(!</span><span class="vars">$zip</span><span>)&nbsp;</span><span class="keyword">return</span><span>(-1);&nbsp;&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>&nbsp;&nbsp;<span class="vars">$cdir</span><span>&nbsp;=&nbsp;</span><span class="vars">$this</span><span>-&gt;ReadCentralDir(</span><span class="vars">$zip</span><span>,</span><span class="vars">$zn</span><span>);&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;<span class="vars">$pos_entry</span><span>&nbsp;=&nbsp;</span><span class="vars">$cdir</span><span>[</span><span class="string">'offset'</span><span>];&nbsp;&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;</span></li>
<li><span>&nbsp;&nbsp;<span class="keyword">if</span><span>(!</span><span class="func">is_array</span><span>(</span><span class="vars">$index</span><span>)){&nbsp;</span><span class="vars">$index</span><span>&nbsp;=&nbsp;</span><span class="keyword">array</span><span>(</span><span class="vars">$index</span><span>);&nbsp;&nbsp;}&nbsp;&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>&nbsp;&nbsp;<span class="keyword">for</span><span>(</span><span class="vars">$i</span><span>=0;&nbsp;</span><span class="vars">$index</span><span>[</span><span class="vars">$i</span><span>];</span><span class="vars">$i</span><span>++){&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">if</span><span>(</span><span class="func">intval</span><span>(</span><span class="vars">$index</span><span>[</span><span class="vars">$i</span><span>])!=</span><span class="vars">$index</span><span>[</span><span class="vars">$i</span><span>]||</span><span class="vars">$index</span><span>[</span><span class="vars">$i</span><span>]&gt;</span><span class="vars">$cdir</span><span>[</span><span class="string">'entries'</span><span>])&nbsp;&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">return</span><span>(-1);&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;}&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;</span></li>
<li><span>&nbsp;&nbsp;<span class="keyword">for</span><span>&nbsp;(</span><span class="vars">$i</span><span>=0;&nbsp;</span><span class="vars">$i</span><span>&lt;</span><span class="vars">$cdir</span><span>[</span><span class="string">'entries'</span><span>];&nbsp;</span><span class="vars">$i</span><span>++)&nbsp;&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>&nbsp;&nbsp;{&nbsp;&nbsp;&nbsp;</span></li>
<li><span>&nbsp;&nbsp;&nbsp;&nbsp;@<span class="func">fseek</span><span>(</span><span class="vars">$zip</span><span>,&nbsp;</span><span class="vars">$pos_entry</span><span>);&nbsp;&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;<span class="vars">$header</span><span>&nbsp;=&nbsp;</span><span class="vars">$this</span><span>-&gt;ReadCentralFileHeaders(</span><span class="vars">$zip</span><span>);&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;&nbsp;<span class="vars">$header</span><span>[</span><span class="string">'index'</span><span>]&nbsp;=&nbsp;</span><span class="vars">$i</span><span>;&nbsp;</span><span class="vars">$pos_entry</span><span>&nbsp;=&nbsp;</span><span class="func">ftell</span><span>(</span><span class="vars">$zip</span><span>);&nbsp;&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;@<span class="func">rewind</span><span>(</span><span class="vars">$zip</span><span>);&nbsp;</span><span class="func">fseek</span><span>(</span><span class="vars">$zip</span><span>,&nbsp;</span><span class="vars">$header</span><span>[</span><span class="string">'offset'</span><span>]);&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">if</span><span>(in_array(</span><span class="string">&quot;-1&quot;</span><span>,</span><span class="vars">$index</span><span>)||in_array(</span><span class="vars">$i</span><span>,</span><span class="vars">$index</span><span>))&nbsp;&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="vars">$stat</span><span>[</span><span class="vars">$header</span><span>[</span><span class="string">'filename'</span><span>]]=</span><span class="vars">$this</span><span>-&gt;ExtractFile(</span><span class="vars">$header</span><span>,&nbsp;</span><span class="vars">$to</span><span>,&nbsp;</span><span class="vars">$zip</span><span>);&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;}&nbsp;&nbsp;&nbsp;</span></li>
<li><span>&nbsp;&nbsp;fclose(<span class="vars">$zip</span><span>);&nbsp;&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>&nbsp;&nbsp;<span class="keyword">return</span><span>&nbsp;</span><span class="vars">$stat</span><span>;&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>}&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;</span></li>
<li><span><span class="keyword">function</span><span>&nbsp;ReadFileHeader(</span><span class="vars">$zip</span><span>)&nbsp;&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>{&nbsp;&nbsp;&nbsp;&nbsp;</span></li>
<li><span>&nbsp;&nbsp;&nbsp;<span class="vars">$binary_data</span><span>&nbsp;=&nbsp;</span><span class="func">fread</span><span>(</span><span class="vars">$zip</span><span>,&nbsp;30);&nbsp;&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;<span class="vars">$data</span><span>&nbsp;=&nbsp;unpack(</span><span class="string">&#8216;vchk/vid/vversion/vflag/vcompression/vmtime/vmdate/Vcrc/</span></span></li>
<li class="alt"><span><span class="string">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Vcompressed_size/Vsize/vfilename_len/vextra_len&#8217;</span><span>,&nbsp;</span><span class="vars">$binary_data</span><span>);&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;<span class="vars">$header</span><span>[</span><span class="string">'filename'</span><span>]&nbsp;=&nbsp;</span><span class="func">fread</span><span>(</span><span class="vars">$zip</span><span>,&nbsp;</span><span class="vars">$data</span><span>[</span><span class="string">'filename_len'</span><span>]);&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;<span class="keyword">if</span><span>&nbsp;(</span><span class="vars">$data</span><span>[</span><span class="string">'extra_len'</span><span>]&nbsp;!=&nbsp;0)&nbsp;{&nbsp;&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="vars">$header</span><span>[</span><span class="string">'extra'</span><span>]&nbsp;=&nbsp;</span><span class="func">fread</span><span>(</span><span class="vars">$zip</span><span>,&nbsp;</span><span class="vars">$data</span><span>[</span><span class="string">'extra_len'</span><span>]);&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;}&nbsp;<span class="keyword">else</span><span>&nbsp;{&nbsp;</span><span class="vars">$header</span><span>[</span><span class="string">'extra'</span><span>]&nbsp;=&nbsp;</span><span class="string">&#8221;</span><span>;&nbsp;}&nbsp;&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;</span></li>
<li><span>&nbsp;&nbsp;&nbsp;<span class="vars">$header</span><span>[</span><span class="string">'compression'</span><span>]&nbsp;=&nbsp;</span><span class="vars">$data</span><span>[</span><span class="string">'compression'</span><span>];</span><span class="vars">$header</span><span>[</span><span class="string">'size'</span><span>]&nbsp;=&nbsp;</span><span class="vars">$data</span><span>[</span><span class="string">'size'</span><span>];&nbsp;&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;<span class="vars">$header</span><span>[</span><span class="string">'compressed_size'</span><span>]&nbsp;=&nbsp;</span><span class="vars">$data</span><span>[</span><span class="string">'compressed_size'</span><span>];&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;<span class="vars">$header</span><span>[</span><span class="string">'crc'</span><span>]&nbsp;=&nbsp;</span><span class="vars">$data</span><span>[</span><span class="string">'crc'</span><span>];&nbsp;</span><span class="vars">$header</span><span>[</span><span class="string">'flag'</span><span>]&nbsp;=&nbsp;</span><span class="vars">$data</span><span>[</span><span class="string">'flag'</span><span>];&nbsp;&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;<span class="vars">$header</span><span>[</span><span class="string">'mdate'</span><span>]&nbsp;=&nbsp;</span><span class="vars">$data</span><span>[</span><span class="string">'mdate'</span><span>];</span><span class="vars">$header</span><span>[</span><span class="string">'mtime'</span><span>]&nbsp;=&nbsp;</span><span class="vars">$data</span><span>[</span><span class="string">'mtime'</span><span>];&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;<span class="keyword">if</span><span>&nbsp;(</span><span class="vars">$header</span><span>[</span><span class="string">'mdate'</span><span>]&nbsp;&amp;&amp;&nbsp;</span><span class="vars">$header</span><span>[</span><span class="string">'mtime'</span><span>]){&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;&nbsp;<span class="vars">$hour</span><span>=(</span><span class="vars">$header</span><span>[</span><span class="string">'mtime'</span><span>]&amp;0xF800)&gt;&gt;11;</span><span class="vars">$minute</span><span>=(</span><span class="vars">$header</span><span>[</span><span class="string">'mtime'</span><span>]&amp;0&#215;07E0)&gt;&gt;5;&nbsp;&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;<span class="vars">$seconde</span><span>=(</span><span class="vars">$header</span><span>[</span><span class="string">'mtime'</span><span>]&amp;0&#215;001F)*2;</span><span class="vars">$year</span><span>=((</span><span class="vars">$header</span><span>[</span><span class="string">'mdate'</span><span>]&amp;0xFE00)&gt;&gt;9)+1980;&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;&nbsp;<span class="vars">$month</span><span>=(</span><span class="vars">$header</span><span>[</span><span class="string">'mdate'</span><span>]&amp;0&#215;01E0)&gt;&gt;5;</span><span class="vars">$day</span><span>=</span><span class="vars">$header</span><span>[</span><span class="string">'mdate'</span><span>]&amp;0&#215;001F;&nbsp;&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;<span class="vars">$header</span><span>[</span><span class="string">'mtime'</span><span>]&nbsp;=&nbsp;</span><span class="func">mktime</span><span>(</span><span class="vars">$hour</span><span>,&nbsp;</span><span class="vars">$minute</span><span>,&nbsp;</span><span class="vars">$seconde</span><span>,&nbsp;</span><span class="vars">$month</span><span>,&nbsp;</span><span class="vars">$day</span><span>,&nbsp;</span><span class="vars">$year</span><span>);&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;}<span class="keyword">else</span><span>{</span><span class="vars">$header</span><span>[</span><span class="string">'mtime'</span><span>]&nbsp;=&nbsp;time();}&nbsp;&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;</span></li>
<li><span>&nbsp;&nbsp;&nbsp;<span class="vars">$header</span><span>[</span><span class="string">'stored_filename'</span><span>]&nbsp;=&nbsp;</span><span class="vars">$header</span><span>[</span><span class="string">'filename'</span><span>];&nbsp;&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;<span class="vars">$header</span><span>[</span><span class="string">'status'</span><span>]&nbsp;=&nbsp;</span><span class="string">&quot;ok&quot;</span><span>;&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;<span class="keyword">return</span><span>&nbsp;</span><span class="vars">$header</span><span>;&nbsp;&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>}&nbsp;&nbsp;&nbsp;</span></li>
<li><span>&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span><span class="keyword">function</span><span>&nbsp;ReadCentralFileHeaders(</span><span class="vars">$zip</span><span>){&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;<span class="vars">$binary_data</span><span>&nbsp;=&nbsp;</span><span class="func">fread</span><span>(</span><span class="vars">$zip</span><span>,&nbsp;46);&nbsp;&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;<span class="vars">$header</span><span>&nbsp;=&nbsp;unpack(</span><span class="string">&#8216;vchkid/vid/vversion/vversion_extracted/vflag/vcompression/vmtime/</span></span></li>
<li class="alt"><span><span class="string">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; vmdate/Vcrc/Vcompressed_size/Vsize/vfilename_len/vextra_len/vcomment_len/vdisk/</span></span></li>
<li class="alt"><span><span class="string">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; vinternal/Vexternal/Voffset&#8217;</span><span>,&nbsp;</span><span class="vars">$binary_data</span><span>);&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;<span class="keyword">if</span><span>&nbsp;(</span><span class="vars">$header</span><span>[</span><span class="string">'filename_len'</span><span>]&nbsp;!=&nbsp;0)&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="vars">$header</span><span>[</span><span class="string">'filename'</span><span>]&nbsp;=&nbsp;</span><span class="func">fread</span><span>(</span><span class="vars">$zip</span><span>,</span><span class="vars">$header</span><span>[</span><span class="string">'filename_len'</span><span>]);&nbsp;&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;<span class="keyword">else</span><span>&nbsp;</span><span class="vars">$header</span><span>[</span><span class="string">'filename'</span><span>]&nbsp;=&nbsp;</span><span class="string">&#8221;</span><span>;&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;<span class="keyword">if</span><span>&nbsp;(</span><span class="vars">$header</span><span>[</span><span class="string">'extra_len'</span><span>]&nbsp;!=&nbsp;0)&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="vars">$header</span><span>[</span><span class="string">'extra'</span><span>]&nbsp;=&nbsp;</span><span class="func">fread</span><span>(</span><span class="vars">$zip</span><span>,&nbsp;</span><span class="vars">$header</span><span>[</span><span class="string">'extra_len'</span><span>]);&nbsp;&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;<span class="keyword">else</span><span>&nbsp;</span><span class="vars">$header</span><span>[</span><span class="string">'extra'</span><span>]&nbsp;=&nbsp;</span><span class="string">&#8221;</span><span>;&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;<span class="keyword">if</span><span>&nbsp;(</span><span class="vars">$header</span><span>[</span><span class="string">'comment_len'</span><span>]&nbsp;!=&nbsp;0)&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="vars">$header</span><span>[</span><span class="string">'comment'</span><span>]&nbsp;=&nbsp;</span><span class="func">fread</span><span>(</span><span class="vars">$zip</span><span>,&nbsp;</span><span class="vars">$header</span><span>[</span><span class="string">'comment_len'</span><span>]);&nbsp;&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;<span class="keyword">else</span><span>&nbsp;</span><span class="vars">$header</span><span>[</span><span class="string">'comment'</span><span>]&nbsp;=&nbsp;</span><span class="string">&#8221;</span><span>;&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;<span class="keyword">if</span><span>&nbsp;(</span><span class="vars">$header</span><span>[</span><span class="string">'mdate'</span><span>]&nbsp;&amp;&amp;&nbsp;</span><span class="vars">$header</span><span>[</span><span class="string">'mtime'</span><span>])&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;{&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="vars">$hour</span><span>&nbsp;=&nbsp;(</span><span class="vars">$header</span><span>[</span><span class="string">'mtime'</span><span>]&nbsp;&amp;&nbsp;0xF800)&nbsp;&gt;&gt;&nbsp;11;&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="vars">$minute</span><span>&nbsp;=&nbsp;(</span><span class="vars">$header</span><span>[</span><span class="string">'mtime'</span><span>]&nbsp;&amp;&nbsp;0&#215;07E0)&nbsp;&gt;&gt;&nbsp;5;&nbsp;&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="vars">$seconde</span><span>&nbsp;=&nbsp;(</span><span class="vars">$header</span><span>[</span><span class="string">'mtime'</span><span>]&nbsp;&amp;&nbsp;0&#215;001F)*2;&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="vars">$year</span><span>&nbsp;=&nbsp;((</span><span class="vars">$header</span><span>[</span><span class="string">'mdate'</span><span>]&nbsp;&amp;&nbsp;0xFE00)&nbsp;&gt;&gt;&nbsp;9)&nbsp;+&nbsp;1980;&nbsp;&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="vars">$month</span><span>&nbsp;=&nbsp;(</span><span class="vars">$header</span><span>[</span><span class="string">'mdate'</span><span>]&nbsp;&amp;&nbsp;0&#215;01E0)&nbsp;&gt;&gt;&nbsp;5;&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="vars">$day</span><span>&nbsp;=&nbsp;</span><span class="vars">$header</span><span>[</span><span class="string">'mdate'</span><span>]&nbsp;&amp;&nbsp;0&#215;001F;&nbsp;&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="vars">$header</span><span>[</span><span class="string">'mtime'</span><span>]&nbsp;=&nbsp;</span><span class="func">mktime</span><span>(</span><span class="vars">$hour</span><span>,&nbsp;</span><span class="vars">$minute</span><span>,&nbsp;</span><span class="vars">$seconde</span><span>,&nbsp;</span><span class="vars">$month</span><span>,&nbsp;</span><span class="vars">$day</span><span>,&nbsp;</span><span class="vars">$year</span><span>);&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;}&nbsp;<span class="keyword">else</span><span>&nbsp;{&nbsp;&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="vars">$header</span><span>[</span><span class="string">'mtime'</span><span>]&nbsp;=&nbsp;time();&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;<span class="vars">$header</span><span>[</span><span class="string">'stored_filename'</span><span>]&nbsp;=&nbsp;</span><span class="vars">$header</span><span>[</span><span class="string">'filename'</span><span>];&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;<span class="vars">$header</span><span>[</span><span class="string">'status'</span><span>]&nbsp;=&nbsp;</span><span class="string">&#8216;ok&#8217;</span><span>;&nbsp;&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;<span class="keyword">if</span><span>&nbsp;(</span><span class="func">substr</span><span>(</span><span class="vars">$header</span><span>[</span><span class="string">'filename'</span><span>],&nbsp;-1)&nbsp;==&nbsp;</span><span class="string">&#8216;/&#8217;</span><span>)&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="vars">$header</span><span>[</span><span class="string">'external'</span><span>]&nbsp;=&nbsp;0&#215;41FF0010;&nbsp;&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;<span class="keyword">return</span><span>&nbsp;</span><span class="vars">$header</span><span>;&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>}&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;</span></li>
<li><span><span class="keyword">function</span><span>&nbsp;ReadCentralDir(</span><span class="vars">$zip</span><span>,</span><span class="vars">$zip_name</span><span>)&nbsp;&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>{&nbsp;&nbsp;&nbsp;</span></li>
<li><span><span class="vars">$size</span><span>&nbsp;=&nbsp;</span><span class="func">filesize</span><span>(</span><span class="vars">$zip_name</span><span>);&nbsp;&nbsp;&nbsp;</span></span></li>
<li class="alt"><span><span class="keyword">if</span><span>&nbsp;(</span><span class="vars">$size</span><span>&nbsp;&lt;&nbsp;277)&nbsp;</span><span class="vars">$maximum_size</span><span>&nbsp;=&nbsp;</span><span class="vars">$size</span><span>;&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span><span class="keyword">else</span><span>&nbsp;</span><span class="vars">$maximum_size</span><span>=277;&nbsp;&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;</span></li>
<li><span>@<span class="func">fseek</span><span>(</span><span class="vars">$zip</span><span>,&nbsp;</span><span class="vars">$size</span><span>-</span><span class="vars">$maximum_size</span><span>);&nbsp;&nbsp;&nbsp;</span></span></li>
<li class="alt"><span><span class="vars">$pos</span><span>&nbsp;=&nbsp;</span><span class="func">ftell</span><span>(</span><span class="vars">$zip</span><span>);&nbsp;</span><span class="vars">$bytes</span><span>&nbsp;=&nbsp;0&#215;00000000;&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span><span class="keyword">while</span><span>&nbsp;(</span><span class="vars">$pos</span><span>&nbsp;&lt;&nbsp;</span><span class="vars">$size</span><span>)&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>{&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;<span class="vars">$byte</span><span>&nbsp;=&nbsp;@</span><span class="func">fread</span><span>(</span><span class="vars">$zip</span><span>,&nbsp;1);&nbsp;</span><span class="vars">$bytes</span><span>=(</span><span class="vars">$bytes</span><span>&nbsp;&lt;&lt;&nbsp;8)&nbsp;|&nbsp;Ord(</span><span class="vars">$byte</span><span>);&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;<span class="keyword">if</span><span>&nbsp;(</span><span class="vars">$bytes</span><span>&nbsp;==&nbsp;0&#215;504b0506){&nbsp;</span><span class="vars">$pos</span><span>++;&nbsp;</span><span class="keyword">break</span><span>;&nbsp;}&nbsp;</span><span class="vars">$pos</span><span>++;&nbsp;&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>}&nbsp;&nbsp;&nbsp;</span></li>
<li><span>&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span><span class="vars">$data</span><span>=unpack(</span><span class="string">&#8216;vdisk/vdisk_start/vdisk_entries/ventries/Vsize/Voffset/vcomment_size&#8217;</span><span>,</span></span></li>
<li class="alt"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span class="func">fread</span><span>(</span><span class="vars">$zip</span><span>,18));&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;</span></li>
<li><span><span class="keyword">if</span><span>&nbsp;(</span><span class="vars">$data</span><span>[</span><span class="string">'comment_size'</span><span>]&nbsp;!=&nbsp;0)&nbsp;&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;<span class="vars">$centd</span><span>[</span><span class="string">'comment'</span><span>]&nbsp;=&nbsp;</span><span class="func">fread</span><span>(</span><span class="vars">$zip</span><span>,&nbsp;</span><span class="vars">$data</span><span>[</span><span class="string">'comment_size'</span><span>]);&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;<span class="keyword">else</span><span>&nbsp;</span><span class="vars">$centd</span><span>[</span><span class="string">'comment'</span><span>]&nbsp;=&nbsp;</span><span class="string">&#8221;</span><span>;&nbsp;</span><span class="vars">$centd</span><span>[</span><span class="string">'entries'</span><span>]&nbsp;=&nbsp;</span><span class="vars">$data</span><span>[</span><span class="string">'entries'</span><span>];&nbsp;&nbsp;&nbsp;</span></span></li>
<li class="alt"><span><span class="vars">$centd</span><span>[</span><span class="string">'disk_entries'</span><span>]&nbsp;=&nbsp;</span><span class="vars">$data</span><span>[</span><span class="string">'disk_entries'</span><span>];&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span><span class="vars">$centd</span><span>[</span><span class="string">'offset'</span><span>]&nbsp;=&nbsp;</span><span class="vars">$data</span><span>[</span><span class="string">'offset'</span><span>];</span><span class="vars">$centd</span><span>[</span><span class="string">'disk_start'</span><span>]&nbsp;=&nbsp;</span><span class="vars">$data</span><span>[</span><span class="string">'disk_start'</span><span>];&nbsp;&nbsp;&nbsp;</span></span></li>
<li class="alt"><span><span class="vars">$centd</span><span>[</span><span class="string">'size'</span><span>]&nbsp;=&nbsp;</span><span class="vars">$data</span><span>[</span><span class="string">'size'</span><span>];&nbsp;&nbsp;</span><span class="vars">$centd</span><span>[</span><span class="string">'disk'</span><span>]&nbsp;=&nbsp;</span><span class="vars">$data</span><span>[</span><span class="string">'disk'</span><span>];&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span><span class="keyword">return</span><span>&nbsp;</span><span class="vars">$centd</span><span>;&nbsp;&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>}&nbsp;&nbsp;&nbsp;</span></li>
<li><span>&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span><span class="keyword">function</span><span>&nbsp;ExtractFile(</span><span class="vars">$header</span><span>,</span><span class="vars">$to</span><span>,</span><span class="vars">$zip</span><span>)&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>{&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;<span class="vars">$header</span><span>&nbsp;=&nbsp;</span><span class="vars">$this</span><span>-&gt;readfileheader(</span><span class="vars">$zip</span><span>);&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;<span class="keyword">if</span><span>(</span><span class="func">substr</span><span>(</span><span class="vars">$to</span><span>,-1)!=</span><span class="string">&quot;/&quot;</span><span>)&nbsp;</span><span class="vars">$to</span><span>.=</span><span class="string">&quot;/&quot;</span><span>;&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;<span class="keyword">if</span><span>(!@</span><span class="func">is_dir</span><span>(</span><span class="vars">$to</span><span>))&nbsp;@</span><span class="func">mkdir</span><span>(</span><span class="vars">$to</span><span>,0777);&nbsp;&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;</span></li>
<li><span>&nbsp;&nbsp;<span class="vars">$pth</span><span>&nbsp;=&nbsp;</span><span class="func">explode</span><span>(</span><span class="string">&quot;/&quot;</span><span>,dirname(</span><span class="vars">$header</span><span>[</span><span class="string">'filename'</span><span>]));&nbsp;&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>&nbsp;&nbsp;<span class="keyword">for</span><span>(</span><span class="vars">$i</span><span>=0;isset(</span><span class="vars">$pth</span><span>[</span><span class="vars">$i</span><span>]);</span><span class="vars">$i</span><span>++){&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">if</span><span>(!</span><span class="vars">$pth</span><span>[</span><span class="vars">$i</span><span>])&nbsp;</span><span class="keyword">continue</span><span>;</span><span class="vars">$pthss</span><span>.=</span><span class="vars">$pth</span><span>[</span><span class="vars">$i</span><span>].</span><span class="string">&quot;/&quot;</span><span>;&nbsp;&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">if</span><span>(!</span><span class="func">is_dir</span><span>(</span><span class="vars">$to</span><span>.</span><span class="vars">$pthss</span><span>))&nbsp;@</span><span class="func">mkdir</span><span>(</span><span class="vars">$to</span><span>.</span><span class="vars">$pthss</span><span>,0777);&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;}&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span><span class="keyword">if</span><span>&nbsp;(!(</span><span class="vars">$header</span><span>[</span><span class="string">'external'</span><span>]==0&#215;41FF0010)&amp;&amp;!(</span><span class="vars">$header</span><span>[</span><span class="string">'external'</span><span>]==16))&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>{&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;<span class="keyword">if</span><span>&nbsp;(</span><span class="vars">$header</span><span>[</span><span class="string">'compression'</span><span>]==0)&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;{&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;<span class="vars">$fp</span><span>&nbsp;=&nbsp;@</span><span class="func">fopen</span><span>(</span><span class="vars">$to</span><span>.</span><span class="vars">$header</span><span>[</span><span class="string">'filename'</span><span>],&nbsp;</span><span class="string">&#8216;wb&#8217;</span><span>);&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;<span class="keyword">if</span><span>(!</span><span class="vars">$fp</span><span>)&nbsp;</span><span class="keyword">return</span><span>(-1);&nbsp;&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;<span class="vars">$size</span><span>&nbsp;=&nbsp;</span><span class="vars">$header</span><span>[</span><span class="string">'compressed_size'</span><span>];&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;<span class="keyword">while</span><span>&nbsp;(</span><span class="vars">$size</span><span>&nbsp;!=&nbsp;0)&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;{&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="vars">$read_size</span><span>&nbsp;=&nbsp;(</span><span class="vars">$size</span><span>&nbsp;&lt;&nbsp;2048&nbsp;?&nbsp;</span><span class="vars">$size</span><span>&nbsp;:&nbsp;2048);&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="vars">$buffer</span><span>&nbsp;=&nbsp;</span><span class="func">fread</span><span>(</span><span class="vars">$zip</span><span>,&nbsp;</span><span class="vars">$read_size</span><span>);&nbsp;&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="vars">$binary_data</span><span>&nbsp;=&nbsp;pack(</span><span class="string">&#8216;a&#8217;</span><span>.</span><span class="vars">$read_size</span><span>,&nbsp;</span><span class="vars">$buffer</span><span>);&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@fwrite(<span class="vars">$fp</span><span>,&nbsp;</span><span class="vars">$binary_data</span><span>,&nbsp;</span><span class="vars">$read_size</span><span>);&nbsp;&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="vars">$size</span><span>&nbsp;-=&nbsp;</span><span class="vars">$read_size</span><span>;&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;fclose(<span class="vars">$fp</span><span>);&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;touch(<span class="vars">$to</span><span>.</span><span class="vars">$header</span><span>[</span><span class="string">'filename'</span><span>],&nbsp;</span><span class="vars">$header</span><span>[</span><span class="string">'mtime'</span><span>]);&nbsp;&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;</span></li>
<li><span>}<span class="keyword">else</span><span>{&nbsp;&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>&nbsp;&nbsp;<span class="vars">$fp</span><span>&nbsp;=&nbsp;@</span><span class="func">fopen</span><span>(</span><span class="vars">$to</span><span>.</span><span class="vars">$header</span><span>[</span><span class="string">'filename'</span><span>].</span><span class="string">&#8216;.gz&#8217;</span><span>,</span><span class="string">&#8216;wb&#8217;</span><span>);&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;<span class="keyword">if</span><span>(!</span><span class="vars">$fp</span><span>)&nbsp;</span><span class="keyword">return</span><span>(-1);&nbsp;&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>&nbsp;&nbsp;<span class="vars">$binary_data</span><span>&nbsp;=&nbsp;pack(</span><span class="string">&#8216;va1a1Va1a1&#8242;</span><span>,&nbsp;0&#215;8b1f,&nbsp;</span><span class="func">Chr</span><span>(</span><span class="vars">$header</span><span>[</span><span class="string">'compression'</span><span>]),&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;&nbsp;<span class="func">Chr</span><span>(0&#215;00),&nbsp;time(),&nbsp;</span><span class="func">Chr</span><span>(0&#215;00),&nbsp;</span><span class="func">Chr</span><span>(3));&nbsp;&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;</span></li>
<li><span>&nbsp;&nbsp;fwrite(<span class="vars">$fp</span><span>,&nbsp;</span><span class="vars">$binary_data</span><span>,&nbsp;10);&nbsp;&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>&nbsp;&nbsp;<span class="vars">$size</span><span>&nbsp;=&nbsp;</span><span class="vars">$header</span><span>[</span><span class="string">'compressed_size'</span><span>];&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;<span class="keyword">while</span><span>&nbsp;(</span><span class="vars">$size</span><span>&nbsp;!=&nbsp;0)&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;{&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;<span class="vars">$read_size</span><span>&nbsp;=&nbsp;(</span><span class="vars">$size</span><span>&nbsp;&lt;&nbsp;1024&nbsp;?&nbsp;</span><span class="vars">$size</span><span>&nbsp;:&nbsp;1024);&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;&nbsp;<span class="vars">$buffer</span><span>&nbsp;=&nbsp;</span><span class="func">fread</span><span>(</span><span class="vars">$zip</span><span>,&nbsp;</span><span class="vars">$read_size</span><span>);&nbsp;&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;<span class="vars">$binary_data</span><span>&nbsp;=&nbsp;pack(</span><span class="string">&#8216;a&#8217;</span><span>.</span><span class="vars">$read_size</span><span>,&nbsp;</span><span class="vars">$buffer</span><span>);&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;&nbsp;@fwrite(<span class="vars">$fp</span><span>,&nbsp;</span><span class="vars">$binary_data</span><span>,&nbsp;</span><span class="vars">$read_size</span><span>);&nbsp;&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;<span class="vars">$size</span><span>&nbsp;-=&nbsp;</span><span class="vars">$read_size</span><span>;&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;}&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;</span></li>
<li><span>&nbsp;&nbsp;<span class="vars">$binary_data</span><span>&nbsp;=&nbsp;pack(</span><span class="string">&#8216;VV&#8217;</span><span>,&nbsp;</span><span class="vars">$header</span><span>[</span><span class="string">'crc'</span><span>],&nbsp;</span><span class="vars">$header</span><span>[</span><span class="string">'size'</span><span>]);&nbsp;&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>&nbsp;&nbsp;fwrite(<span class="vars">$fp</span><span>,&nbsp;</span><span class="vars">$binary_data</span><span>,8);&nbsp;fclose(</span><span class="vars">$fp</span><span>);&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;<span class="vars">$gzp</span><span>&nbsp;=&nbsp;@gzopen(</span><span class="vars">$to</span><span>.</span><span class="vars">$header</span><span>[</span><span class="string">'filename'</span><span>].</span><span class="string">&#8216;.gz&#8217;</span><span>,</span><span class="string">&#8216;rb&#8217;</span><span>)&nbsp;</span><span class="keyword">or</span><span>&nbsp;</span><span class="keyword">die</span><span>(</span><span class="string">&quot;Cette&nbsp;archive&nbsp;est&nbsp;</span></span></li>
<li class="alt"><span><span class="string">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; compress&quot;</span><span>);&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;<span class="keyword">if</span><span>(!</span><span class="vars">$gzp</span><span>)&nbsp;</span><span class="keyword">return</span><span>(-2);&nbsp;&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>&nbsp;&nbsp;<span class="vars">$fp</span><span>&nbsp;=&nbsp;@</span><span class="func">fopen</span><span>(</span><span class="vars">$to</span><span>.</span><span class="vars">$header</span><span>[</span><span class="string">'filename'</span><span>],</span><span class="string">&#8216;wb&#8217;</span><span>);&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;<span class="keyword">if</span><span>(!</span><span class="vars">$fp</span><span>)&nbsp;</span><span class="keyword">return</span><span>(-1);&nbsp;&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>&nbsp;&nbsp;<span class="vars">$size</span><span>&nbsp;=&nbsp;</span><span class="vars">$header</span><span>[</span><span class="string">'size'</span><span>];&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;<span class="keyword">while</span><span>&nbsp;(</span><span class="vars">$size</span><span>&nbsp;!=&nbsp;0)&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;{&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;<span class="vars">$read_size</span><span>&nbsp;=&nbsp;(</span><span class="vars">$size</span><span>&nbsp;&lt;&nbsp;2048&nbsp;?&nbsp;</span><span class="vars">$size</span><span>&nbsp;:&nbsp;2048);&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;&nbsp;<span class="vars">$buffer</span><span>&nbsp;=&nbsp;gzread(</span><span class="vars">$gzp</span><span>,&nbsp;</span><span class="vars">$read_size</span><span>);&nbsp;&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;<span class="vars">$binary_data</span><span>&nbsp;=&nbsp;pack(</span><span class="string">&#8216;a&#8217;</span><span>.</span><span class="vars">$read_size</span><span>,&nbsp;</span><span class="vars">$buffer</span><span>);&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;&nbsp;@fwrite(<span class="vars">$fp</span><span>,&nbsp;</span><span class="vars">$binary_data</span><span>,&nbsp;</span><span class="vars">$read_size</span><span>);&nbsp;&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;<span class="vars">$size</span><span>&nbsp;-=&nbsp;</span><span class="vars">$read_size</span><span>;&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;}&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;fclose(<span class="vars">$fp</span><span>);&nbsp;gzclose(</span><span class="vars">$gzp</span><span>);&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;touch(<span class="vars">$to</span><span>.</span><span class="vars">$header</span><span>[</span><span class="string">'filename'</span><span>],&nbsp;</span><span class="vars">$header</span><span>[</span><span class="string">'mtime'</span><span>]);&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;@unlink(<span class="vars">$to</span><span>.</span><span class="vars">$header</span><span>[</span><span class="string">'filename'</span><span>].</span><span class="string">&#8216;.gz&#8217;</span><span>);&nbsp;&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;</span></li>
<li><span>}}&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span><span class="keyword">return</span><span>&nbsp;true;&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>}&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span>}&nbsp;&nbsp;&nbsp;</span></li>
<li><span>?&gt;&nbsp;&nbsp;&nbsp;&nbsp;</span></li>
</ol>
</div>
<div style="display: none;" class="php">&lt;?  class zip   {    var $datasec, $ctrl_dir = array();  var $eof_ctrl_dir = &quot;\x50\x4b\x05\x06\x00\x00\x00\x00&quot;;  var $old_offset = 0; var $dirs = Array(&quot;.&quot;);    function get_List($zip_name)  {    $zip = @fopen($zip_name, &#8216;rb&#8217;);    if(!$zip) return(0);    $centd = $this-&gt;ReadCentralDir($zip,$zip_name);       @rewind($zip);     @fseek($zip, $centd['offset']);      for ($i=0; $i&lt;$centd['entries']; $i++)    {     $header = $this-&gt;ReadCentralFileHeaders($zip);     $header['index'] = $i;$info['filename'] = $header['filename'];     $info['stored_filename'] = $header['stored_filename'];     $info['size'] = $header['size'];$info['compressed_size']=$header['compressed_size'];     $info['crc'] = strtoupper(dechex( $header['crc'] ));     $info['mtime'] = $header['mtime']; $info['comment'] = $header['comment'];     $info['folder'] = ($header['external']==0&#215;41FF0010||$header['external']==16)?1:0;     $info['index'] = $header['index'];$info['status'] = $header['status'];     $ret[]=$info; unset($header);    }  return $ret;  }  function Add($files,$compact)  {  if(!is_array($files[0])) $files=Array($files);    for($i=0;$files[$i];$i++){     $fn = $files[$i];     if(!in_Array(dirname($fn[0]),$this-&gt;dirs))      $this-&gt;add_Dir(dirname($fn[0]));     if(basename($fn[0]))      $ret[basename($fn[0])]=$this-&gt;add_File($fn[1],$fn[0],$compact);  }  return $ret;  }    function get_file()  {    $data = implode(&#8221;, $this -&gt; datasec);    $ctrldir = implode(&#8221;, $this -&gt; ctrl_dir);      return $data . $ctrldir . $this -&gt; eof_ctrl_dir .     pack(&#8217;v', sizeof($this -&gt; ctrl_dir)).pack(&#8217;v', sizeof($this -&gt; ctrl_dir)).     pack(&#8217;V', strlen($ctrldir)) . pack(&#8217;V', strlen($data)) . &quot;\x00\x00&quot;;  }    function add_dir($name)   {     $name = str_replace(&quot;\\&quot;, &quot;/&quot;, $name);     $fr = &quot;\x50\x4b\x03\x04\x0a\x00\x00\x00\x00\x00\x00\x00\x00\x00&quot;;       $fr .= pack(&quot;V&quot;,0).pack(&quot;V&quot;,0).pack(&quot;V&quot;,0).pack(&quot;v&quot;, strlen($name) );     $fr .= pack(&quot;v&quot;, 0 ).$name.pack(&quot;V&quot;, 0).pack(&quot;V&quot;, 0).pack(&quot;V&quot;, 0);     $this -&gt; datasec[] = $fr;      $new_offset = strlen(implode(&quot;&quot;, $this-&gt;datasec));       $cdrec = &quot;\x50\x4b\x01\x02\x00\x00\x0a\x00\x00\x00\x00\x00\x00\x00\x00\x00&quot;;     $cdrec .= pack(&quot;V&quot;,0).pack(&quot;V&quot;,0).pack(&quot;V&quot;,0).pack(&quot;v&quot;, strlen($name) );     $cdrec .= pack(&quot;v&quot;, 0 ).pack(&quot;v&quot;, 0 ).pack(&quot;v&quot;, 0 ).pack(&quot;v&quot;, 0 );     $ext = &quot;\xff\xff\xff\xff&quot;;     $cdrec .= pack(&quot;V&quot;, 16 ).pack(&quot;V&quot;, $this -&gt; old_offset ).$name;       $this -&gt; ctrl_dir[] = $cdrec;     $this -&gt; old_offset = $new_offset;     $this -&gt; dirs[] = $name;  }    function add_File($data, $name, $compact = 1)  {    $name     = str_replace(&#8217;\\&#8217;, &#8216;/&#8217;, $name);    $dtime    = dechex($this-&gt;DosTime());      $hexdtime = &#8216;\x&#8217; . $dtime[6] . $dtime[7].&#8217;\x&#8217;.$dtime[4] . $dtime[5]      . &#8216;\x&#8217; . $dtime[2] . $dtime[3].&#8217;\x&#8217;.$dtime[0].$dtime[1];    eval(&#8217;$hexdtime = &quot;&#8217; . $hexdtime . &#8216;&quot;;&#8217;);      if($compact)    $fr = &quot;\x50\x4b\x03\x04\x14\x00\x00\x00\x08\x00&quot;.$hexdtime;    else $fr = &quot;\x50\x4b\x03\x04\x0a\x00\x00\x00\x00\x00&quot;.$hexdtime;    $unc_len = strlen($data); $crc = crc32($data);      if($compact){      $zdata = gzcompress($data); $c_len = strlen($zdata);      $zdata = substr(substr($zdata, 0, strlen($zdata) - 4), 2);    }else{      $zdata = $data;    }    $c_len=strlen($zdata);    $fr .= pack(&#8217;V', $crc).pack(&#8217;V', $c_len).pack(&#8217;V', $unc_len);    $fr .= pack(&#8217;v', strlen($name)).pack(&#8217;v', 0).$name.$zdata;      $fr .= pack(&#8217;V', $crc).pack(&#8217;V', $c_len).pack(&#8217;V', $unc_len);      $this -&gt; datasec[] = $fr;    $new_offset        = strlen(implode(&#8221;, $this-&gt;datasec));    if($compact)         $cdrec = &quot;\x50\x4b\x01\x02\x00\x00\x14\x00\x00\x00\x08\x00&quot;;    else $cdrec = &quot;\x50\x4b\x01\x02\x14\x00\x0a\x00\x00\x00\x00\x00&quot;;    $cdrec .= $hexdtime.pack(&#8217;V', $crc).pack(&#8217;V', $c_len).pack(&#8217;V', $unc_len);    $cdrec .= pack(&#8217;v', strlen($name) ).pack(&#8217;v', 0 ).pack(&#8217;v', 0 );    $cdrec .= pack(&#8217;v', 0 ).pack(&#8217;v', 0 ).pack(&#8217;V', 32 );    $cdrec .= pack(&#8217;V', $this -&gt; old_offset );      $this -&gt; old_offset = $new_offset;    $cdrec .= $name;    $this -&gt; ctrl_dir[] = $cdrec;    return true;  }    function DosTime() {    $timearray = getdate();    if ($timearray['year'] &lt; 1980) {      $timearray['year'] = 1980; $timearray['mon'] = 1;      $timearray['mday'] = 1; $timearray['hours'] = 0;      $timearray['minutes'] = 0; $timearray['seconds'] = 0;    }    return (($timearray['year'] - 1980) &lt;&lt; 25) | ($timearray['mon'] &lt;&lt; 21) |     ($timearray['mday'] &lt;&lt; 16) | ($timearray['hours'] &lt;&lt; 11) |      ($timearray['minutes'] &lt;&lt; 5) | ($timearray['seconds'] &gt;&gt; 1);  }    function Extract ( $zn, $to, $index = Array(-1) )  {    $ok = 0; $zip = @fopen($zn,&#8217;rb&#8217;);    if(!$zip) return(-1);    $cdir = $this-&gt;ReadCentralDir($zip,$zn);    $pos_entry = $cdir['offset'];      if(!is_array($index)){ $index = array($index);  }    for($i=0; $index[$i];$i++){      if(intval($index[$i])!=$index[$i]||$index[$i]&gt;$cdir['entries'])       return(-1);    }      for ($i=0; $i&lt;$cdir['entries']; $i++)    {      @fseek($zip, $pos_entry);      $header = $this-&gt;ReadCentralFileHeaders($zip);      $header['index'] = $i; $pos_entry = ftell($zip);      @rewind($zip); fseek($zip, $header['offset']);      if(in_array(&quot;-1&quot;,$index)||in_array($i,$index))       $stat[$header['filename']]=$this-&gt;ExtractFile($header, $to, $zip);           }    fclose($zip);    return $stat;  }    function ReadFileHeader($zip)  {      $binary_data = fread($zip, 30);     $data = unpack(&#8217;vchk/vid/vversion/vflag/vcompression/vmtime/vmdate/Vcrc/Vcompressed_size/Vsize/vfilename_len/vextra_len&#8217;, $binary_data);       $header['filename'] = fread($zip, $data['filename_len']);     if ($data['extra_len'] != 0) {       $header['extra'] = fread($zip, $data['extra_len']);     } else { $header['extra'] = &#8221;; }       $header['compression'] = $data['compression'];$header['size'] = $data['size'];     $header['compressed_size'] = $data['compressed_size'];     $header['crc'] = $data['crc']; $header['flag'] = $data['flag'];     $header['mdate'] = $data['mdate'];$header['mtime'] = $data['mtime'];       if ($header['mdate'] &amp;&amp; $header['mtime']){      $hour=($header['mtime']&amp;0xF800)&gt;&gt;11;$minute=($header['mtime']&amp;0&#215;07E0)&gt;&gt;5;      $seconde=($header['mtime']&amp;0&#215;001F)*2;$year=(($header['mdate']&amp;0xFE00)&gt;&gt;9)+1980;      $month=($header['mdate']&amp;0&#215;01E0)&gt;&gt;5;$day=$header['mdate']&amp;0&#215;001F;      $header['mtime'] = mktime($hour, $minute, $seconde, $month, $day, $year);     }else{$header['mtime'] = time();}       $header['stored_filename'] = $header['filename'];     $header['status'] = &quot;ok&quot;;     return $header;  }    function ReadCentralFileHeaders($zip){     $binary_data = fread($zip, 46);     $header = unpack(&#8217;vchkid/vid/vversion/vversion_extracted/vflag/vcompression/vmtime/vmdate/Vcrc/Vcompressed_size/Vsize/vfilename_len/vextra_len/vcomment_len/vdisk/vinternal/Vexternal/Voffset&#8217;, $binary_data);       if ($header['filename_len'] != 0)       $header['filename'] = fread($zip,$header['filename_len']);     else $header['filename'] = &#8221;;       if ($header['extra_len'] != 0)       $header['extra'] = fread($zip, $header['extra_len']);     else $header['extra'] = &#8221;;       if ($header['comment_len'] != 0)       $header['comment'] = fread($zip, $header['comment_len']);     else $header['comment'] = &#8221;;       if ($header['mdate'] &amp;&amp; $header['mtime'])     {       $hour = ($header['mtime'] &amp; 0xF800) &gt;&gt; 11;       $minute = ($header['mtime'] &amp; 0&#215;07E0) &gt;&gt; 5;       $seconde = ($header['mtime'] &amp; 0&#215;001F)*2;       $year = (($header['mdate'] &amp; 0xFE00) &gt;&gt; 9) + 1980;       $month = ($header['mdate'] &amp; 0&#215;01E0) &gt;&gt; 5;       $day = $header['mdate'] &amp; 0&#215;001F;       $header['mtime'] = mktime($hour, $minute, $seconde, $month, $day, $year);     } else {       $header['mtime'] = time();     }     $header['stored_filename'] = $header['filename'];     $header['status'] = &#8216;ok&#8217;;     if (substr($header['filename'], -1) == &#8216;/&#8217;)       $header['external'] = 0&#215;41FF0010;     return $header;  }    function ReadCentralDir($zip,$zip_name)  {  $size = filesize($zip_name);  if ($size &lt; 277) $maximum_size = $size;  else $maximum_size=277;    @fseek($zip, $size-$maximum_size);  $pos = ftell($zip); $bytes = 0&#215;00000000;    while ($pos &lt; $size)  {     $byte = @fread($zip, 1); $bytes=($bytes &lt;&lt; <img src='http://www.oursit.com/wp-includes/images/smilies/icon_cool.gif' alt='8)' class='wp-smiley' /> | Ord($byte);     if ($bytes == 0&#215;504b0506){ $pos++; break; } $pos++;  }    $data=unpack(&#8217;vdisk/vdisk_start/vdisk_entries/ventries/Vsize/Voffset/vcomment_size&#8217;,fread($zip,18));      if ($data['comment_size'] != 0)     $centd['comment'] = fread($zip, $data['comment_size']);     else $centd['comment'] = &#8221;; $centd['entries'] = $data['entries'];  $centd['disk_entries'] = $data['disk_entries'];  $centd['offset'] = $data['offset'];$centd['disk_start'] = $data['disk_start'];  $centd['size'] = $data['size'];  $centd['disk'] = $data['disk'];  return $centd;  }    function ExtractFile($header,$to,$zip)  {    $header = $this-&gt;readfileheader($zip);      if(substr($to,-1)!=&quot;/&quot;) $to.=&quot;/&quot;;    if(!@is_dir($to)) @mkdir($to,0777);      $pth = explode(&quot;/&quot;,dirname($header['filename']));    for($i=0;isset($pth[$i]);$i++){      if(!$pth[$i]) continue;$pthss.=$pth[$i].&quot;/&quot;;      if(!is_dir($to.$pthss)) @mkdir($to.$pthss,0777);    }  if (!($header['external']==0&#215;41FF0010)&amp;&amp;!($header['external']==16))  {    if ($header['compression']==0)    {     $fp = @fopen($to.$header['filename'], &#8216;wb&#8217;);     if(!$fp) return(-1);     $size = $header['compressed_size'];       while ($size != 0)     {       $read_size = ($size &lt; 2048 ? $size : 2048);       $buffer = fread($zip, $read_size);       $binary_data = pack(&#8217;a&#8217;.$read_size, $buffer);       @fwrite($fp, $binary_data, $read_size);       $size -= $read_size;     }     fclose($fp);     touch($to.$header['filename'], $header['mtime']);    }else{    $fp = @fopen($to.$header['filename'].&#8217;.gz&#8217;,'wb&#8217;);    if(!$fp) return(-1);    $binary_data = pack(&#8217;va1a1Va1a1&#8242;, 0&#215;8b1f, Chr($header['compression']),      Chr(0&#215;00), time(), Chr(0&#215;00), Chr(3));      fwrite($fp, $binary_data, 10);    $size = $header['compressed_size'];      while ($size != 0)    {      $read_size = ($size &lt; 1024 ? $size : 1024);      $buffer = fread($zip, $read_size);      $binary_data = pack(&#8217;a&#8217;.$read_size, $buffer);      @fwrite($fp, $binary_data, $read_size);      $size -= $read_size;    }      $binary_data = pack(&#8217;VV&#8217;, $header['crc'], $header['size']);    fwrite($fp, $binary_data,8); fclose($fp);      $gzp = @gzopen($to.$header['filename'].&#8217;.gz&#8217;,'rb&#8217;) or die(&quot;Cette archive est compress&quot;);     if(!$gzp) return(-2);    $fp = @fopen($to.$header['filename'],&#8217;wb&#8217;);    if(!$fp) return(-1);    $size = $header['size'];      while ($size != 0)    {      $read_size = ($size &lt; 2048 ? $size : 2048);      $buffer = gzread($gzp, $read_size);      $binary_data = pack(&#8217;a&#8217;.$read_size, $buffer);      @fwrite($fp, $binary_data, $read_size);      $size -= $read_size;    }    fclose($fp); gzclose($gzp);      touch($to.$header['filename'], $header['mtime']);    @unlink($to.$header['filename'].&#8217;.gz&#8217;);    }}  return true;  }  }  ?&gt;</div>
<link rel="stylesheet" type="text/css" href="/wp-content/plugins/fckeditor_for_wordpress/fckeditor/editor/plugins/highlighter/dp.SyntaxHighlighter/Styles/SyntaxHighlighter.css" /></div>
<p><font size="2" face="Times New Roman"> 文件解压 <br />
</font></p>
<p>&nbsp;</p>
<div class="dp-highlighter">
<div class="bar">&nbsp;</div>
<ol start="1" class="dp-c">
<li class="alt"><span><span>&lt;?&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span><span class="vars">$zipfile</span><span>=</span><span class="string">&quot;a.zip&quot;</span><span>;&nbsp;</span><span class="comment">//zip&nbsp;文件名&nbsp;</span><span>&nbsp;&nbsp;</span></span></li>
<li class="alt"><span><span class="vars">$i</span><span>=1;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//这个是zip-&gt;get_list的时候文件对应的&nbsp;[index]&nbsp;号(必须是文件，也就是说&nbsp;[folder]=0&nbsp;的才可以)&nbsp;</span><span>&nbsp;&nbsp;</span></span></li>
<li><span><span class="vars">$path</span><span>=</span><span class="string">&quot;filesinzip&quot;</span><span>;&nbsp;&nbsp;</span><span class="comment">//zip文件解压到的目录&nbsp;</span><span>&nbsp;&nbsp;</span></span></li>
<li class="alt"><span><span class="keyword">include</span><span>(</span><span class="string">&quot;zip.class.php&quot;</span><span>);&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span><span class="vars">$zip</span><span>&nbsp;=&nbsp;</span><span class="keyword">new</span><span>&nbsp;Zip;&nbsp;&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;</span></li>
<li><span><span class="keyword">if</span><span>&nbsp;(</span><span class="vars">$zip</span><span>-&gt;Extract(</span><span class="vars">$zipfile</span><span>,</span><span class="vars">$path</span><span>,</span><span class="vars">$i</span><span>))&nbsp;</span><span class="func">echo</span><span>&nbsp;</span><span class="string">&quot;ok&quot;</span><span>;&nbsp;</span><span class="keyword">else</span><span>&nbsp;</span><span class="func">echo</span><span>&nbsp;</span><span class="string">&quot;error&quot;</span><span>;&nbsp;&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;</span></li>
<li><span>?&gt;&nbsp;&nbsp;&nbsp;&nbsp;</span></li>
</ol>
</div>
<div style="display: none;" class="php">&lt;?  $zipfile=&quot;a.zip&quot;; //zip 文件名  $i=1;             //这个是zip-&gt;get_list的时候文件对应的 [index] 号(必须是文件，也就是说 [folder]=0 的才可以)  $path=&quot;filesinzip&quot;;  //zip文件解压到的目录  include(&quot;zip.class.php&quot;);  $zip = new Zip;    if ($zip-&gt;Extract($zipfile,$path,$i)) echo &quot;ok&quot;; else echo &quot;error&quot;;    ?&gt;</div>
<p>&nbsp;</p>
<p><font size="2" face="宋体"> 压缩文件 <br />
</font></p>
<p>&nbsp;</p>
<div class="dp-highlighter">
<div class="bar">&nbsp;</div>
<ol start="1" class="dp-c">
<li class="alt"><span><span>&lt;?&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span><span class="keyword">include</span><span>(</span><span class="string">&quot;zip.class.php&quot;</span><span>);&nbsp;&nbsp;&nbsp;</span></span></li>
<li class="alt"><span><span class="vars">$zip</span><span>&nbsp;=&nbsp;</span><span class="keyword">new</span><span>&nbsp;Zip;&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span><span class="vars">$zipfile</span><span>=</span><span class="string">&quot;zip.php&quot;</span><span>;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//要压缩的文件名&nbsp;</span><span>&nbsp;&nbsp;</span></span></li>
<li class="alt"><span><span class="vars">$key</span><span>=</span><span class="string">&quot;a.zip&quot;</span><span>;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//生成的zip&nbsp;文件名&nbsp;</span><span>&nbsp;&nbsp;</span></span></li>
<li><span><span class="vars">$filename</span><span>=</span><span class="string">&quot;me/me.php&quot;</span><span>;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//zip文件中的文件名,可以和$zipfile不同&nbsp;</span><span>&nbsp;&nbsp;</span></span></li>
<li class="alt"><span><span class="vars">$filesize</span><span>=@</span><span class="func">filesize</span><span>(</span><span class="vars">$zipfile</span><span>);&nbsp;&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span><span class="vars">$fp</span><span>=@</span><span class="func">fopen</span><span>(</span><span class="vars">$zipfile</span><span>,rb);&nbsp;&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span><span class="vars">$zipfilecontent</span><span>=Array(</span><span class="vars">$filename</span><span>,@</span><span class="func">fread</span><span>(</span><span class="vars">$fp</span><span>,</span><span class="vars">$filesize</span><span>));&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>@fclose(<span class="vars">$fp</span><span>);&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span><span class="vars">$zip</span><span>-&gt;Add(</span><span class="vars">$zipfilecontent</span><span>,1);&nbsp;&nbsp;</span><span class="comment">//可以多次执行&nbsp;$zip-&gt;Add&nbsp;来添加多个文件&nbsp;</span><span>&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;</span></li>
<li><span><span class="keyword">if</span><span>(@</span><span class="func">fputs</span><span>(@</span><span class="func">fopen</span><span>(</span><span class="vars">$key</span><span>,</span><span class="string">&quot;wb&quot;</span><span>),</span><span class="vars">$zip</span><span>-&gt;get_file()))&nbsp;</span><span class="comment">//写入文件&nbsp;</span><span>&nbsp;&nbsp;</span></span></li>
<li class="alt"><span><span class="func">echo</span><span>&nbsp;</span><span class="string">&quot;文件压缩成功!!&quot;</span><span>;&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span><span class="keyword">else</span><span>&nbsp;&nbsp;&nbsp;</span></span></li>
<li class="alt"><span><span class="func">echo</span><span>&nbsp;</span><span class="string">&quot;文件压缩失败!!&quot;</span><span>;&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>?&gt;&nbsp;&nbsp;&nbsp;&nbsp;</span></li>
</ol>
</div>
<div style="display: none;" class="php">&lt;?  include(&quot;zip.class.php&quot;);  $zip = new Zip;  $zipfile=&quot;zip.php&quot;;       //要压缩的文件名  $key=&quot;a.zip&quot;;             //生成的zip 文件名  $filename=&quot;me/me.php&quot;;    //zip文件中的文件名,可以和$zipfile不同  $filesize=@filesize($zipfile);     $fp=@fopen($zipfile,rb);   $zipfilecontent=Array($filename,@fread($fp,$filesize));    @fclose($fp);  $zip-&gt;Add($zipfilecontent,1);  //可以多次执行 $zip-&gt;Add 来添加多个文件    if(@fputs(@fopen($key,&quot;wb&quot;),$zip-&gt;get_file())) //写入文件  echo &quot;文件压缩成功!!&quot;;  else  echo &quot;文件压缩失败!!&quot;;  ?&gt;</div>
<p>&nbsp;</p>
<p><font size="2" face="宋体"> 浏览zip文件 <br />
</font></p>
<p>&nbsp;</p>
<div class="dp-highlighter">
<div class="bar">&nbsp;</div>
<ol start="1" class="dp-c">
<li class="alt"><span><span>&lt;?&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span><span class="vars">$zipfile</span><span>=</span><span class="string">&quot;a.zip&quot;</span><span>;&nbsp;&nbsp;</span><span class="comment">//要浏览的zip文件名&nbsp;</span><span>&nbsp;&nbsp;</span></span></li>
<li class="alt"><span><span class="keyword">include</span><span>(</span><span class="string">&quot;zip.class.php&quot;</span><span>);&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span><span class="vars">$zip</span><span>&nbsp;=&nbsp;</span><span class="keyword">new</span><span>&nbsp;Zip;&nbsp;&nbsp;&nbsp;</span></span></li>
<li class="alt"><span><span class="vars">$l</span><span>=</span><span class="vars">$zip</span><span>-&gt;get_list(</span><span class="vars">$zipfile</span><span>);&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>print_r(<span class="vars">$l</span><span>);&nbsp;&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>?&gt;&nbsp;&nbsp;</span></li>
</ol>
</div>
<div style="display: none;" class="php">&lt;?  $zipfile=&quot;a.zip&quot;;  //要浏览的zip文件名  include(&quot;zip.class.php&quot;);  $zip = new Zip;  $l=$zip-&gt;get_list($zipfile);  print_r($l);  ?&gt;</div>
<p>&nbsp;</p>
<p>&nbsp;</p>
]]></content:encoded>
			<wfw:commentRss>http://www.oursit.com/archives/127.html/feed</wfw:commentRss>
		</item>
		<item>
		<title>PHP+GTK入门</title>
		<link>http://www.oursit.com/archives/125.html</link>
		<comments>http://www.oursit.com/archives/125.html#comments</comments>
		<pubDate>Sun, 31 Aug 2008 03:22:35 +0000</pubDate>
		<dc:creator>Skylin</dc:creator>
		
		<category><![CDATA[PHP]]></category>

		<category><![CDATA[gtk]]></category>

		<guid isPermaLink="false">http://www.oursit.com/?p=125</guid>
		<description><![CDATA[ 以前PHP被认为只能用来编写服务器端的CGI程序，如果说PHP能够开发Windows下的GUI（图形用户界面）程序，你相信吗？最近，PHP的开发小组成功开发出了捆绑GTK+的PHP，那么就可以开发Windows下的GUI程序了。&#160;
&#160;
一、建立PHP/GTK运行环境：&#160;
其实GUI程序和普通的PHPCGI程序没有什么区别，不过是PHP/GTK程序由GTK的类来生成GUI界面而已，他们同样是开放源代码，靠PHP来解析建立窗口。如果你已经建立好了PHP的调试环境，那么安装PHP/GTK环境比较简单：&#160;
1、下载php_gtk.dll（这个dll文件用于解析PHP源程序里面的GTK代码），下载后将其解压到PHP的扩展（extension）目录中；&#160;
2、下载其他PHP/GTK的dll文件（一共6个），将他们解压缩到Windows的system32目录里面；&#160;
3、打开php.ini，在扩展设置部分&#8220;Windows Extensions&#8221;最下面加入&#8220;extension=php_gtk.dll&#8221;的语句，建议先备份php.ini，避免修改失败使得建立好的PHP运行环境作废；&#160;
现在就建立好了PHP/GTK的运行环境了。当然，你也可以不作第二步，而改为在每个PHP/GTK程序源代码的第一行加入&#8220;dl(&#8217;php_gtk.dll&#8217;)&#8221;来动态加载GTK的支持。&#160;
如果你还没有建立PHP运行环境，那么安装要更加简单：&#160;
1、下载整个PHP/GTK的捆绑支持包，然后将他们解压缩到c盘的PHP4目录下面；&#160;
2、将winnt目录下面的dll文件拷贝到Windows的system32目录中，将php.ini文件拷贝到Windows的目录中；&#160;
建 立好了PHP/GTK的运行后，可以用命令行模式的PHP来运行一个PHP/GTK程序：在运行中输入&#8220;c:\php4\php  -q gtkprogrampath&#8221;，其中&#8220;c:\php4\php&#8221;改为PHP.EXE的路径，&#8220;gtkprogrampath&#8221;就是PHP/GTK程序的  路径。比如：&#8220;c:\php4\php -q c:\php4\samples\hello.php&#8221;将会运行PHP/GTK运行包中附带的例子&#8220;hello  world&#8221;程序。&#160;
&#160;
二、编译PHP/GTK程序：&#160;
如果你作出一个PHP/GTK的应用程序，还需要对方的电脑建立PHP的运行环境并且使用PHP命令行模式来解析才可以执行的话，那就过于复杂了。那么怎么样才可以编译一个PHP/GTK的程序呢？经过一番搜索，笔者发现了PHPCompiler这个软件。&#160;
PHPCompiler由www.deskcode.com开发（http://www.deskcode.com/phpcompiler），可以将PHP编译成为EXE可执行文件，内置了PHP的支持，如果你要编译一个PHP/GTK程序，必须建立PHP/GTK的运行环境（参照前面的步骤）。要编译一个PHP/GTK程序的步骤如下：&#160;
1、打开PHPCompiler，在&#8220;Script to&#8221;选择希望编译的PHP程序源代码，在&#8220;Destination&#8221;处选择编译成功后的EXE文件的路径；&#160;
2、点击&#8220;Compile&#8221;按钮，会弹出一个对话框询问使用的编译模式（如果是PHP/GTK程序就选择no，是单纯的PHPCGI程序就选择yes）；&#160;
3、然后又会弹出一个对话框询问是否拷贝php4ts.dll文件到编译后的EXE文件的目录，选择yes。&#160;
经过上面的步骤，一个PHP/GTK程序就成功编译了，但是对于编译PHP/GTK程序还有几个需要注意的地方：&#160;
1、编译完成后的可执行文件如果需要执行，PC机上面必须具有GTK运行环境所需的几个dll文件（就是前面下载的那几个），如果需要作成应用程序，可以在安装的时候将几个dll文件拷贝到system32目录中（不过这样子程序也就不是&#8220;绿色软件&#8221;了^_^）。&#160;
2、 PHPCompiler本身对于PHP的支持非常好，但是有些人试过用一些需要扩展支持的函数，比如&#8220;gzopen&#8221;等等，在编译之前还好好的，编译完毕  后就不能用了。其实编译完成后的可执行文件，相当于了只有默认的PHP支持（连GTK支持都没有了），所以如果在程序中应用了任何需要扩展支持的函数，都  必须动态的加载支持函数的dll文件，比如&#8220;dl(&#8217;php_gtk.dll&#8217;)&#8221;，这样子编译完成后才不会出错。&#160;
3、运行一个编译后的可执行文件，都会先弹出一个DOS窗口，然后自动关闭，因为每个GUI窗口都是通过GTK来&#8220;绘制&#8221;出来的，所以必须会有那个窗口。&#160;
4、或许以前PHP还不能说是真正的OOP（面向对象程序）语言，但是到了PHP/GTK，任何一个窗口都由GTK对象来&#8220;绘制&#8221;，如果没有过硬的OOP功底，是很难写出GUI程序的。&#160;
&#160;
三、PHP/GTK资源：&#160;
1、http://gtk.php.net：PHP/GTK的官方网站；虽然说是官方网站，但是确简陋的很，出了一个FAQ和邮件列表，几乎找不到任何有用的东西了，&#160;
2、http://www.phpgtk.com：一个界面比较好的PHP/GTK网站，有最新的版本信息。&#160;
3、http://developer.gnome.org/doc/API/gtk/gtkobjects.html：PHP/GTK函数和类的大全/手册网站，里面有十分丰富的PHP/GTK资料。&#160;
4、http://www.phpuk.org/gtk/：非官方版本的GTK手册网站，简单易懂。&#160;
&#160;
如果大家认为E文比较难看，也可以来zphp.com[url]http://dl.itbulo.com/&#8217;[/url]&#62;下载最新的PHP/GTK运行环境和支持包。&#160;
&#160;
PHP-GTK开发入门全集(1)&#160;
&#160;
1. PHP-GTK介绍&#160;
1.1 PHP-GTK&#160;
PHP-GTK是PHP的延伸模组，它可以让程序设计师写出在客户端执行的、且独立的GUI的程序。这个模组不允许在浏览器上显视GTK+的程序，它一开始就是开发来写独立的GUI程序的。&#160;
&#160;
1.2 GTK&#160;
GTK原本是为GIMP，一个GUI的影像处理软体而开发的。GTK+是GIMP的套装工具。GTK+从这里开始发展，直到现在已经成为Gnome的中心  (Gnome是一个桌面环境)。后来GTK+也已经被推广到BeOS和Win32，使得它成为PHP延伸模组的最佳选择，维持PHP可以跨平台并可以用  PHP为Linux,BeOS,Windows等平台开发视窗接口的程序。&#160;
&#160;
2. PHP-GTK概念&#160;
2.1 前言&#160;
接下来就要教各位一点点比较观念性的东西罗┅因为这章的概念都是非常重要的，所以就算不懂，也还是要慢慢的看懂它，不然┅以后就┅。还有，接下来的内容不 建议没有程序设计经验的读者阅读，因为有很多的观念很容易会搞不清楚。还有，接下来该用英文的部分我都会用英文，这样大家在看国外文件的时候才不会不知所 措，加油吧!!如果对本章有任何不懂之处，请自行查阅&#160;
PHP-GTK Manual：http://gtk.php.net/manual/en/&#160;
&#160;
2.2 Widget(s)&#160;
Widget是一个GUI程序中基本的functions和forms。最常用的几个Widget是：label、button、window、  frame和text box。所有的widget都是来自于一个抽象的基本class─GtkWidget。每个widget都是一个class&#160;
&#160;
一个Widget一生大概都有五个时期：&#160;
1. 建立(Creation)：宣告一个对象(declaring an object)&#160;
2. 放置(Placement)：将它加入一个容器中(adding it to a container)&#160;
3. 信号连接(Signal Connection)：接收信号以及进行动作(the  action it will perform)&#160;
4. 显示(Display)：它是否是可见的(whether it is viewable or [...]]]></description>
			<content:encoded><![CDATA[<p><font size="3" face="宋体"> 以前PHP被认为只能用来编写服务器端的CGI程序，<wbr></wbr>如果说PHP能够开发Windows下的GUI（图形用户界面）<wbr></wbr>程序，你相信吗？最近，<wbr></wbr>PHP的开发小组成功开发出了捆绑GTK+的PHP，<wbr></wbr>那么就可以开发Windows下的GUI程序了。&nbsp;<br />
&nbsp;<br />
一、建立PHP/GTK运行环境：&nbsp;<br />
其实GUI程序和普通的PHPCGI程序没有什么区别，<wbr></wbr>不过是PHP/GTK程序由GTK的类来生成GUI界面而已，<wbr></wbr>他们同样是开放源代码，靠PHP来解析建立窗口。<wbr></wbr>如果你已经建立好了PHP的调试环境，那么安装PHP/<wbr></wbr>GTK环境比较简单：&nbsp;<br />
1、下载php_gtk.dll（<wbr></wbr>这个dll文件用于解析PHP源程序里面的GTK代码），<wbr></wbr>下载后将其解压到PHP的扩展（extension）目录中；&nbsp;<br />
2、下载其他PHP/GTK的dll文件（一共6个），<wbr></wbr>将他们解压缩到Windows的system32目录里面；&nbsp;<br />
3、打开php.ini，在扩展设置部分&ldquo;Windows Extensions&rdquo;最下面加入&ldquo;extension=<wbr></wbr>php_gtk.dll&rdquo;的语句，建议先备份php.ini，<wbr></wbr>避免修改失败使得建立好的PHP运行环境作废；&nbsp;<br />
现在就建立好了PHP/GTK的运行环境了。当然，<wbr></wbr>你也可以不作第二步，而改为在每个PHP/<wbr></wbr>GTK程序源代码的第一行加入&ldquo;dl(&#8217;php_gtk.<wbr></wbr>dll&#8217;)&rdquo;来动态加载GTK的支持。&nbsp;<br />
如果你还没有建立PHP运行环境，那么安装要更加简单：&nbsp;<br />
1、下载整个PHP/GTK的捆绑支持包，<wbr></wbr>然后将他们解压缩到c盘的PHP4目录下面；&nbsp;<br />
2、<wbr></wbr>将winnt目录下面的dll文件拷贝到Windows的sys<wbr></wbr>tem32目录中，将php.<wbr></wbr>ini文件拷贝到Windows的目录中；&nbsp;<br />
建 立好了PHP/GTK的运行后，<wbr></wbr>可以用命令行模式的PHP来运行一个PHP/GTK程序：<wbr></wbr>在运行中输入&ldquo;c:\php4\php  -q gtkprogrampath&rdquo;，其中&ldquo;c:\php4\<wbr></wbr>php&rdquo;改为PHP.EXE的路径，&ldquo;<wbr></wbr>gtkprogrampath&rdquo;就是PHP/GTK程序的  路径。比如：&ldquo;c:\php4\php -q c:\php4\samples\hello.php&rdquo;<wbr></wbr>将会运行PHP/GTK运行包中附带的例子&ldquo;hello  world&rdquo;程序。&nbsp;<br />
&nbsp;<br />
二、编译PHP/GTK程序：&nbsp;<br />
如果你作出一个PHP/GTK的应用程序，<wbr></wbr>还需要对方的电脑建立PHP的运行环境并且使用PHP命令行模式<wbr></wbr>来解析才可以执行的话，那就过于复杂了。<wbr></wbr>那么怎么样才可以编译一个PHP/GTK的程序呢？<wbr></wbr>经过一番搜索，笔者发现了PHPCompiler这个软件。&nbsp;<br />
PHPCompiler由</font><a target="_blank" href="http://www.deskcode.com/"><font size="3" face="宋体" color="#0000ff"><u>www.deskcode.com</u></font></a><font size="3" face="宋体">开发<wbr></wbr>（</font><a target="_blank" href="http://www.deskcode.com/phpcompiler"><font size="3" face="宋体" color="#0000ff"><u>http://www.deskcode.com/<wbr></wbr>phpcompiler</u></font></a><font size="3" face="宋体">），<wbr></wbr>可以将PHP编译成为EXE可执行文件，内置了PHP的支持，<wbr></wbr>如果你要编译一个PHP/GTK程序，必须建立PHP/<wbr></wbr>GTK的运行环境（参照前面的步骤）。要编译一个PHP/<wbr></wbr>GTK程序的步骤如下：&nbsp;<br />
1、打开PHPCompiler，在&ldquo;Script to&rdquo;选择希望编译的PHP程序源代码，在&ldquo;<wbr></wbr>Destination&rdquo;处选择编译成功后的EXE文件的路径；<wbr></wbr>&nbsp;<br />
2、点击&ldquo;Compile&rdquo;按钮，<wbr></wbr>会弹出一个对话框询问使用的编译模式（如果是PHP/<wbr></wbr>GTK程序就选择no，是单纯的PHPCGI程序就选择yes）<wbr></wbr>；&nbsp;<br />
3、然后又会弹出一个对话框询问是否拷贝php4ts.<wbr></wbr>dll文件到编译后的EXE文件的目录，选择yes。&nbsp;<br />
经过上面的步骤，一个PHP/GTK程序就成功编译了，<wbr></wbr>但是对于编译PHP/GTK程序还有几个需要注意的地方：&nbsp;<br />
1、编译完成后的可执行文件如果需要执行，<wbr></wbr>PC机上面必须具有GTK运行环境所需的几个dll文件（<wbr></wbr>就是前面下载的那几个），如果需要作成应用程序，<wbr></wbr>可以在安装的时候将几个dll文件拷贝到system32目录中<wbr></wbr>（不过这样子程序也就不是&ldquo;绿色软件&rdquo;了^_^）。&nbsp;<br />
2、 PHPCompiler本身对于PHP的支持非常好，<wbr></wbr>但是有些人试过用一些需要扩展支持的函数，比如&ldquo;gzopen&rdquo;<wbr></wbr>等等，在编译之前还好好的，编译完毕  后就不能用了。其实编译完成后的可执行文件，<wbr></wbr>相当于了只有默认的PHP支持（连GTK支持都没有了），<wbr></wbr>所以如果在程序中应用了任何需要扩展支持的函数，都  必须动态的加载支持函数的dll文件，比如&ldquo;dl(&#8217;php_<wbr></wbr>gtk.dll&#8217;)&rdquo;，这样子编译完成后才不会出错。&nbsp;<br />
3、运行一个编译后的可执行文件，都会先弹出一个DOS窗口，<wbr></wbr>然后自动关闭，因为每个GUI窗口都是通过GTK来&ldquo;绘制&rdquo;<wbr></wbr>出来的，所以必须会有那个窗口。&nbsp;<br />
4、或许以前PHP还不能说是真正的OOP（面向对象程序）<wbr></wbr>语言，但是到了PHP/GTK，任何一个窗口都由GTK对象来&ldquo;<wbr></wbr>绘制&rdquo;，如果没有过硬的OOP功底，是很难写出GUI程序的。&nbsp;<br />
&nbsp;<br />
三、PHP/GTK资源：&nbsp;<br />
1、</font><a target="_blank" href="http://gtk.php.net/"><font size="3" face="宋体" color="#0000ff"><u>http://gtk.php.net</u></font></a><font size="3" face="宋体">：PHP/<wbr></wbr>GTK的官方网站；虽然说是官方网站，但是确简陋的很，<wbr></wbr>出了一个FAQ和邮件列表，几乎找不到任何有用的东西了，&nbsp;<br />
2、</font><a target="_blank" href="http://www.phpgtk.com/"><font size="3" face="宋体" color="#0000ff"><u>http://www.phpgtk.com</u></font></a><font size="3" face="宋体">：<wbr></wbr>一个界面比较好的PHP/GTK网站，有最新的版本信息。&nbsp;<br />
3、</font><a target="_blank" href="http://developer.gnome.org/doc/API/gtk/gtkobjects.html"><font size="3" face="宋体" color="#0000ff"><u>http://developer.gnome.org/<wbr></wbr>doc/API/gtk/gtkobjects.html</u></font></a><font size="3" face="宋体">：<wbr></wbr>PHP/GTK函数和类的大全/手册网站，<wbr></wbr>里面有十分丰富的PHP/GTK资料。&nbsp;<br />
4、</font><a target="_blank" href="http://www.phpuk.org/gtk/"><font size="3" face="宋体" color="#0000ff"><u>http://www.phpuk.org/gtk/</u></font></a><font size="3" face="宋体">：<wbr></wbr>非官方版本的GTK手册网站，简单易懂。&nbsp;<br />
&nbsp;<br />
如果大家认为E文比较难看，也可以来<a target="_blank" href="http://zphp.com/">zphp.com</a>[url]<a target="_blank" href="http://dl.itbulo.com/%27%5B/url%5D"><wbr></wbr>http://dl.itbulo.com/&#8217;[/url]</a>&gt;<wbr></wbr>下载最新的PHP/GTK运行环境和支持包。</font>&nbsp;<br />
&nbsp;</p>
<p align="justify"><font size="2" face="Times New Roman">PHP-GTK</font><font size="2" face="宋体">开发入门全集</font><font size="2" face="Times New Roman">(1)&nbsp;<br />
&nbsp;<br />
1. PHP-GTK介绍&nbsp;<br />
1.1 PHP-GTK&nbsp;<br />
PHP-GTK是PHP的延伸模组，<wbr></wbr>它可以让程序设计师写出在客户端执行的、且独立的GUI的程序。<wbr></wbr>这个模</font><font size="2" face="宋体">组不允许在浏览器上显视</font><font size="2" face="Times New Roman">GTK+</font><font size="2" face="宋体">的程序，<wbr></wbr>它一开始就是开发来写独立的</font><font size="2" face="Times New Roman">GUI</font><font size="2" face="宋体">程序的。&nbsp;<br />
&nbsp;<br />
1.2 GTK&nbsp;<br />
GTK原本是为GIMP，一个GUI的影像处理软体而开发的。<wbr></wbr>GTK+是GIMP的套装工具。GTK+从这里开始发展，<wbr></wbr>直到现在已经成为Gnome的中心  (Gnome是一个桌面环境)。后来GTK+<wbr></wbr>也已经被推广到BeOS和Win32，<wbr></wbr>使得它成为PHP延伸模组的最佳选择，<wbr></wbr>维持PHP可以跨平台并可以用  PHP为Linux,BeOS,<wbr></wbr>Windows等平台开发视窗接口的程序。&nbsp;<br />
&nbsp;<br />
2. PHP-GTK概念&nbsp;<br />
2.1 前言&nbsp;<br />
接下来就要教各位一点点比较观念性的东西罗┅<wbr></wbr>因为这章的概念都是非常重要的，所以就算不懂，<wbr></wbr>也还是要慢慢的看懂它，不然┅以后就┅。还有，接下来的内容不</font><font size="2" face="Times New Roman"> </font><font size="2" face="宋体">建议没有程序设计经验的读者阅读，<wbr></wbr>因为有很多的观念很容易会搞不清楚。还有，<wbr></wbr>接下来该用英文的部分我都会用英文，<wbr></wbr>这样大家在看国外文件的时候才不会不知所</font><font size="2" face="Times New Roman"> </font><font size="2" face="宋体">措，加油吧</font><font size="2" face="Times New Roman">!!</font><font size="2" face="宋体">如果对本章有任何不懂之处，请自行查阅&nbsp;<br />
PHP-GTK Manual：</font><a target="_blank" href="http://gtk.php.net/manual/en/"><font size="2" face="Times New Roman"><u>http://gtk.php.net/<wbr></wbr>manual/en/</u></font></a><font size="2" face="Times New Roman">&nbsp;<br />
&nbsp;<br />
2.2 Widget(s)&nbsp;<br />
Widget是一个GUI程序中基本的functions和fo<wbr></wbr>rms。最常用的几个Widget是：label、<wbr></wbr>button、window、  frame和text box。<wbr></wbr>所有的widget都是来自于一个抽象的基本class─<wbr></wbr>GtkWidget。每个widget都是一个class&nbsp;<br />
&nbsp;<br />
一个Widget一生大概都有五个时期：&nbsp;<br />
1. 建立(Creation)：宣告一个对象(declaring an object)&nbsp;<br />
2. 放置(Placement)：将它加入一个</font><font size="2" face="宋体">容器中</font><font size="2" face="Times New Roman">(adding it to a container)&nbsp;<br />
3. 信号连接(Signal Connection)：接收信号以及进行动作(the  action it will perform)&nbsp;<br />
4. 显示(Display)：它是否是可见的(whether it is viewable or  not)&nbsp;<br />
5. 删除(Destruction)：关闭程序(closing of a program)&nbsp;<br />
&nbsp;<br />
2.3 Container(s)&nbsp;<br />
Container是一个可以包含其它widget的widge<wbr></wbr>t。大部分的widget</font><font size="2" face="宋体">都是</font><font size="2" face="Times New Roman">container</font><font size="2" face="宋体">，例如：</font><font size="2" face="Times New Roman">Gtk<wbr></wbr>Window</font><font size="2" face="宋体">、</font><font size="2" face="Times New Roman">  GtkTable</font><font size="2" face="宋体">和</font><font size="2" face="Times New Roman">GtkBox</font><font size="2" face="宋体">。除了这点之外，</font><font size="2" face="Times New Roman">contain<wbr></wbr>er</font><font size="2" face="宋体">跟其它的</font><font size="2" face="Times New Roman">widget</font><font size="2" face="宋体">没两样，也可以被放到其它</font><font size="2" face="Times New Roman">contai<wbr></wbr>ner</font><font size="2" face="宋体">去。而所有的</font><font size="2" face="Times New Roman"> container</font><font size="2" face="宋体">都是来自于一个</font><font size="2" face="Times New Roman">class─<wbr></wbr>GtkContainer</font><font size="2" face="宋体">，本身来自于</font><font size="2" face="Times New Roman">GtkWidget</font><font size="2" face="宋体">的</font><font size="2" face="Times New Roman">cl<wbr></wbr>ass</font><font size="2" face="宋体">。所以</font><font size="2" face="Times New Roman">container</font><font size="2" face="宋体">也是</font><font size="2" face="Times New Roman"> widget</font><font size="2" face="宋体">的一种。&nbsp;<br />
&nbsp;<br />
2.4 Signal(s)&nbsp;<br />
当程序设计师在程序中做了一个动作时，<wbr></wbr>程序需要有一个动作来回应使用者的动作。<wbr></wbr>Signals使程序可以知道使用者做了动作并可以触发适合的回<wbr></wbr>应。&nbsp;<br />
&nbsp;<br />
例如，当使用者按了一个可以开新视窗的按钮(<wbr></wbr>GtkButton)，程序认出这个请求，<wbr></wbr>于是就开了一个新的视窗。这件事可以经由signal来做到。<wbr></wbr>当按  钮按下去之后，会使widget发出一个signal，<wbr></wbr>接着再由该signal触发callbacks，<wbr></wbr>产生一个新的视窗(GtkWindow)。&nbsp;<br />
&nbsp;<br />
2.5 Callback(s)&nbsp;<br />
Callback就是当signal送出之后，<wbr></wbr>被signal唤起的function。<wbr></wbr>Callback会执行function传回一个值或是做一个动  作。Callback就是signa</font><font size="2" face="Times New Roman">l</font><font size="2" face="宋体">的</font><font size="2" face="Times New Roman">handler  funciton</font><font size="2" face="宋体">。它可以是该</font><font size="2" face="Times New Roman">signal</font><font size="2" face="宋体">的预设</font><font size="2" face="Times New Roman">handler</font><font size="2" face="宋体"><wbr></wbr>或着是程序设计师定义的</font><font size="2" face="Times New Roman">function</font><font size="2" face="宋体">。要建立一个</font><font size="2" face="Times New Roman">callb<wbr></wbr>ack</font><font size="2" face="宋体">，就必须把</font><font size="2" face="Times New Roman"> function connect </font><font size="2" face="宋体">到</font><font size="2" face="Times New Roman"> signal</font><font size="2" face="宋体">。&nbsp;<br />
&nbsp;<br />
2.6 Signal Inheritance(继承)&nbsp;<br />
和methods一样，signals可以被对象继承。<wbr></wbr>一个widget可以送出任何它的parent  widget可以送出的还有它自己特有的signal。&nbsp;<br />
&nbsp;<br />
2.7 Connecting Signals&nbsp;<br />
你必须为PHP-GTK指定一个callbac</font><font size="2" face="Times New Roman">k  function</font><font size="2" face="宋体">当</font><font size="2" face="Times New Roman">signal</font><font size="2" face="宋体">送出时来对</font><font size="2" face="Times New Roman">signal</font><font size="2" face="宋体">做回应。<wbr></wbr>把一个</font><font size="2" face="Times New Roman">signal</font><font size="2" face="宋体">连接到一个</font><font size="2" face="Times New Roman">function</font><font size="2" face="宋体">可以用</font><font size="2" face="Times New Roman">conne<wbr></wbr>ct() </font><font size="2" face="宋体">这个</font><font size="2" face="Times New Roman">object </font><font size="2" face="宋体">方法达成。&nbsp;<br />
&nbsp;<br />
如下： <br />
</font></p>
<p align="justify">&nbsp;</p>
<div>
<div class="dp-highlighter">
<div class="bar">&nbsp;</div>
<ol start="1" class="dp-c">
<li class="alt"><span><span class="comment">//建立一个GtkWindow&nbsp;</span><span>&nbsp;&nbsp;</span></span></li>
<li><span><span class="vars">$window</span><span>&nbsp;=&nbsp;&amp;</span><span class="keyword">new</span><span>&nbsp;GtkWindow();&nbsp;&nbsp;&nbsp;</span></span></li>
<li class="alt"><span><span class="comment">//将&quot;destroy&quot;&nbsp;signal用connect()&nbsp;方法连接到shutdown函式&nbsp;</span><span>&nbsp;&nbsp;</span></span></li>
<li><span><span class="vars">$window</span><span>-&gt;connect(</span><span class="string">&quot;destroy&quot;</span><span>,&nbsp;</span><span class="string">&quot;shutdown&quot;</span><span>);&nbsp;&nbsp;&nbsp;</span></span></li>
<li class="alt"><span><span class="comment">//建立一个GtkButton，按钮文字为&quot;按我&quot;&nbsp;</span><span>&nbsp;&nbsp;</span></span></li>
<li><span><span class="vars">$button</span><span>&nbsp;=&nbsp;&amp;</span><span class="keyword">new</span><span>&nbsp;GtkButton(</span><span class="string">&quot;按我&quot;</span><span>);&nbsp;&nbsp;&nbsp;</span></span></li>
<li class="alt"><span><span class="vars">$button</span><span>-&gt;connect(</span><span class="string">&quot;clicked&quot;</span><span>,&nbsp;</span><span class="string">&quot;you_clicked&quot;</span><span>);&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span><span class="comment">//把GtkButton放到是container的GtkWindow中&nbsp;</span><span>&nbsp;&nbsp;</span></span></li>
<li class="alt"><span><span class="vars">$window</span><span>-&gt;add(</span><span class="vars">$button</span><span>);&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span><span class="comment">//显示$window以及它的所有child&nbsp;widget&nbsp;</span><span>&nbsp;&nbsp;</span></span></li>
<li class="alt"><span><span class="vars">$window</span><span>-&gt;show_all();&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span><span class="comment">//进入程序主回圈(即程序启动之意)&nbsp;</span><span>&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>gtk::main();&nbsp;&nbsp;&nbsp;</span></li>
<li><span>?&gt;&nbsp;&nbsp;&nbsp;</span></li>
</ol>
</div>
<div style="display: none;" class="php">//建立一个GtkWindow  $window = &amp;new GtkWindow();  //将&quot;destroy&quot; signal用connect() 方法连接到shutdown函式  $window-&gt;connect(&quot;destroy&quot;, &quot;shutdown&quot;);  //建立一个GtkButton，按钮文字为&quot;按我&quot;  $button = &amp;new GtkButton(&quot;按我&quot;);  $button-&gt;connect(&quot;clicked&quot;, &quot;you_clicked&quot;);  //把GtkButton放到是container的GtkWindow中  $window-&gt;add($button);  //显示$window以及它的所有child widget  $window-&gt;show_all();  //进入程序主回圈(即程序启动之意)  gtk::main();  ?&gt;</div>
<link rel="stylesheet" type="text/css" href="/wp-content/plugins/fckeditor_for_wordpress/fckeditor/editor/plugins/highlighter/dp.SyntaxHighlighter/Styles/SyntaxHighlighter.css" /></div>
<p><font size="2" face="Times New Roman"> 执行它的话，就会出现一个视窗，里面有一个写着&quot;按我&quot;的按钮，<wbr></wbr>按下按钮程序就会执行you_clicked</font><font size="2" face="宋体">函式。<wbr></wbr>在这个程序中，</font><font size="2" face="Times New Roman">$window</font><font size="2" face="宋体">对象的</font><font size="2" face="Times New Roman">  &quot;destroy&quot; signal</font><font size="2" face="宋体">是在使用者按下视窗右上角的</font><font size="2" face="Times New Roman">&quot;X&quot;</font><font size="2" face="宋体">时会送出的；而</font><font size="2" face="Times New Roman">$<wbr></wbr>button</font><font size="2" face="宋体">对象的</font><font size="2" face="Times New Roman">&quot;clicked&quot; signal</font><font size="2" face="宋体">是在使用者按下该按钮的时候会送出的。最后那一行的</font><font size="2" face="Times New Roman"><wbr></wbr>gtk::main() </font><font size="2" face="宋体">是一定要执行的，这样才能告诉电脑要开始执行程序，<wbr></wbr>既然有开始执行，那就一定有停止吧</font><font size="2" face="Times New Roman">? </font><font size="2" face="宋体">没错，用</font><font size="2" face="Times New Roman">gtk::main_quit() </font><font size="2" face="宋体">就可以停止程序了。&nbsp;<br />
&nbsp;<br />
看完了以上的范例，有些读者可能会有疑问「<wbr></wbr>如果我想执行送出signal的widget之外的widget<wbr></wbr>的meth</font><font size="2" face="Times New Roman">od</font><font size="2" face="宋体">怎么办</font><font size="2" face="Times New Roman">?</font><font size="2" face="宋体">」，这时候，就要用另一</font><font size="2" face="Times New Roman"> </font><font size="2" face="宋体">个</font><font size="2" face="Times New Roman">method</font><font size="2" face="宋体">了</font><font size="2" face="Times New Roman"> a connect_object()</font><font size="2" face="宋体">，<wbr></wbr>它可以跨对象呼叫方法或是传递其它对象做为</font><font size="2" face="Times New Roman">function</font><font size="2" face="宋体">的叁<wbr></wbr>数。跨对象呼叫方法如下：&nbsp;<br />
&nbsp;<br />
$window-&gt;connect_object(&quot;<wbr></wbr>destroy&quot;, array(&quot;gtk&quot;,&quot;main_quit&quot;))&nbsp;<br />
&nbsp;<br />
如此，在$window对象的&quot;destroy&quot; signal送出的时候就会唤起gtk::main_quit(<wbr></wbr>)这个方法，程序就会终指执行。&nbsp;<br />
&nbsp;<br />
在介绍连接方法的最后，再提一下connect() 和 connec</font><font size="2" face="Times New Roman">t_object() </font><font size="2" face="宋体">的自订增加要传给</font><font size="2" face="Times New Roman">callback function</font><font size="2" face="宋体">的叁数的办法。见例子： <br />
</font></p>
<p>&nbsp;</p>
<div>
<div class="dp-highlighter">
<div class="bar">&nbsp;</div>
<ol start="1" class="dp-c">
<li class="alt"><span><span class="vars">$parameter</span><span>=</span><span class="string">&quot;新超人&quot;</span><span>;&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span><span class="vars">$button1</span><span>&nbsp;=&nbsp;&amp;</span><span class="keyword">new</span><span>&nbsp;GtkButton(</span><span class="string">&quot;测试&quot;</span><span>);&nbsp;&nbsp;&nbsp;</span></span></li>
<li class="alt"><span><span class="comment">//将&quot;clicked&quot;&nbsp;signal连接到who_are_you函式，附加叁数$parameter&nbsp;</span><span>&nbsp;&nbsp;</span></span></li>
<li><span><span class="vars">$button1</span><span>-&gt;connect(</span><span class="string">&quot;clicked&quot;</span><span>,</span><span class="string">&quot;who_are_you&quot;</span><span>,</span><span class="vars">$parameter</span><span>);&nbsp;&nbsp;&nbsp;</span></span></li>
<li class="alt"><span><span class="vars">$button2</span><span>&nbsp;=&nbsp;&amp;</span><span class="keyword">new</span><span>&nbsp;GtkButton(</span><span class="string">&quot;测试二&quot;</span><span>);&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span><span class="comment">//将&quot;clicked&quot;&nbsp;signal连接到kill_the_button1函式，附加叁数$button1&nbsp;</span><span>&nbsp;&nbsp;</span></span></li>
<li class="alt"><span><span class="vars">$button2</span><span>-&gt;connect_object(</span><span class="string">&quot;clicked&quot;</span><span>,</span><span class="string">&quot;kill_the_button1&quot;</span><span>,</span><span class="vars">$button1</span><span>);&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span><span class="keyword">function</span><span>&nbsp;who_are_you(</span><span class="vars">$widget</span><span>,</span><span class="vars">$parameter</span><span>){&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span><span class="func">echo</span><span>&nbsp;</span><span class="vars">$parameter</span><span>;&nbsp;&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>}&nbsp;&nbsp;&nbsp;</span></li>
<li><span>&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span><span class="keyword">function</span><span>&nbsp;kill_the_button(</span><span class="vars">$button</span><span>){&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span><span class="vars">$button</span><span>-&gt;destroy();&nbsp;&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>}&nbsp;&nbsp;&nbsp;</span></li>
<li><span>?&gt;&nbsp;&nbsp;&nbsp;</span></li>
</ol>
</div>
<div style="display: none;" class="php">$parameter=&quot;新超人&quot;;  $button1 = &amp;new GtkButton(&quot;测试&quot;);  //将&quot;clicked&quot; signal连接到who_are_you函式，附加叁数$parameter  $button1-&gt;connect(&quot;clicked&quot;,&quot;who_are_you&quot;,$parameter);  $button2 = &amp;new GtkButton(&quot;测试二&quot;);  //将&quot;clicked&quot; signal连接到kill_the_button1函式，附加叁数$button1  $button2-&gt;connect_object(&quot;clicked&quot;,&quot;kill_the_button1&quot;,$button1);    function who_are_you($widget,$parameter){  echo $parameter;  }    function kill_the_button($button){  $button-&gt;destroy();  }  ?&gt;</div>
</div>
<p><font size="2" face="Times New Roman"> 注意那两个function，who_are_<wbr></wbr>you有两个叁数对</font><font size="2" face="宋体">吧</font><font size="2" face="Times New Roman">? </font><font size="2" face="宋体">第一个是做什么用的呢</font><font size="2" face="Times New Roman">?</font><font size="2" face="宋体">为什么它会自动出现</font><font size="2" face="Times New Roman">?? </font><font size="2" face="宋体">因为，每个</font><font size="2" face="Times New Roman">signal</font><font size="2" face="宋体">的</font><font size="2" face="Times New Roman">callback function</font><font size="2" face="宋体">都会因为</font><font size="2" face="Times New Roman">signal</font><font size="2" face="宋体">的不同而加上一些内定一定<wbr></wbr>会传入</font><font size="2" face="Times New Roman">callback function</font><font size="2" face="宋体">的叁数，而基本上所有的</font><font size="2" face="Times New Roman">signal</font><font size="2" face="宋体">都至少会传<wbr></wbr>给</font><font size="2" face="Times New Roman">callback function</font><font size="2" face="宋体">一个叁数</font><font size="2" face="Times New Roman">a</font><font size="2" face="宋体">产生该</font><font size="2" face="Times New Roman">signal</font><font size="2" face="宋体">的物件。所以</font><font size="2" face="Times New Roman">wh<wbr></wbr>o_are_you</font><font size="2" face="宋体">的第一个叁数就是</font><font size="2" face="Times New Roman">$button1</font><font size="2" face="宋体">，<wbr></wbr>而第二个就是</font><font size="2" face="Times New Roman">$ parameter</font><font size="2" face="宋体">，也就是新超人。那</font><font size="2" face="Times New Roman">kill_the_<wbr></wbr>button</font><font size="2" face="宋体">函式就不一样罗</font><font size="2" face="Times New Roman">~ </font><font size="2" face="宋体">因为</font><font size="2" face="Times New Roman">connect_object()</font><font size="2" face="宋体">函式会呼略原本</font><font size="2" face="Times New Roman">signa<wbr></wbr>l</font><font size="2" face="宋体">的</font><font size="2" face="Times New Roman">callback function</font><font size="2" face="宋体">的预设叁数，所以</font><font size="2" face="Times New Roman">kill_the_<wbr></wbr>button</font><font size="2" face="宋体">就只有附加在</font><font size="2" face="Times New Roman">connect_object</font><font size="2" face="宋体">最后的</font><font size="2" face="Times New Roman">$<wbr></wbr>button1</font><font size="2" face="宋体">叁数了，如此，</font><font size="2" face="Times New Roman"> kill_the_button</font><font size="2" face="宋体">就可以呼叫</font><font size="2" face="Times New Roman">$button1</font><font size="2" face="宋体">的方<wbr></wbr>法或是取得它的属性，这里呼叫了</font><font size="2" face="Times New Roman">$button1</font><font size="2" face="宋体">的</font><font size="2" face="Times New Roman">destro<wbr></wbr>y</font><font size="2" face="宋体">方法，于是</font><font size="2" face="Times New Roman">$ button1</font><font size="2" face="宋体">就会被消灭。&nbsp;<br />
&nbsp;<br />
2.8 Event(s)&nbsp;<br />
Event是signal的一种，<wbr></wbr>但是它的用途还有功能都非常强大。就signal来说，<wbr></wbr>signal这种东西都是内建在widget上的，所以，例如</font><font size="2" face="Times New Roman"> GtkWindow</font><font size="2" face="宋体">没有</font><font size="2" face="Times New Roman">&quot;clicked&quot;signal</font><font size="2" face="宋体">，<wbr></wbr>那么在不用</font><font size="2" face="Times New Roman">event  signal</font><font size="2" face="宋体">的情况下，</font><font size="2" face="Times New Roman">GtkWindow</font><font size="2" face="宋体">是决对不可能送出</font><font size="2" face="Times New Roman">cl<wbr></wbr>icked</font><font size="2" face="宋体">之类的</font><font size="2" face="Times New Roman">signal</font><font size="2" face="宋体">的。那如果用了</font><font size="2" face="Times New Roman">event signal</font><font size="2" face="宋体">呢</font><font size="2" face="Times New Roman">? Event signal</font><font size="2" face="宋体">是可以允许被加到任何的</font><font size="2" face="Times New Roman">widget</font><font size="2" face="宋体">上的，<wbr></wbr>所以就算这个</font><font size="2" face="Times New Roman">widget</font><font size="2" face="宋体">本来没有发出</font><font size="2" face="Times New Roman">&quot;clicked&quot;<wbr></wbr>signal</font><font size="2" face="宋体">的功能，你也可以用</font><font size="2" face="Times New Roman">  add_events() </font><font size="2" face="宋体">来为它加上按了它之后</font><font size="2" face="Times New Roman">event signal</font><font size="2" face="宋体">会做什么样的反应。而</font><font size="2" face="Times New Roman">event signal</font><font size="2" face="宋体">中包含的资讯比较多，比如说当你在使用</font><font size="2" face="Times New Roman">&quot;key-<wbr></wbr>press-event&quot;</font><font size="2" face="宋体">这个</font><font size="2" face="Times New Roman">event  signal</font><font size="2" face="宋体">的时候，同时也会记录到你按下的是什么按键，<wbr></wbr>于是通常</font><font size="2" face="Times New Roman">event signal</font><font size="2" face="宋体">的</font><font size="2" face="Times New Roman">callback function</font><font size="2" face="宋体">格式内定会有两个叁数，第一个依然是送出</font><font size="2" face="Times New Roman">sig<wbr></wbr>nal</font><font size="2" face="宋体">的</font><font size="2" face="Times New Roman">widget</font><font size="2" face="宋体">，而第二个就是</font><font size="2" face="Times New Roman">$event</font><font size="2" face="宋体">，这个</font><font size="2" face="Times New Roman">$<wbr></wbr>event</font><font size="2" face="宋体">是一个</font><font size="2" face="Times New Roman">class</font><font size="2" face="宋体">，里</font><font size="2" face="Times New Roman"> </font><font size="2" face="宋体">面的属性和方法会因为送过来的</font><font size="2" face="Times New Roman">event signal</font><font size="2" face="宋体">种类而不同。就</font><font size="2" face="Times New Roman">&quot;key-press-event&quot;</font><font size="2" face="宋体"><wbr></wbr>传回的</font><font size="2" face="Times New Roman">$event  class</font><font size="2" face="宋体">来说，里面有一个属性是</font><font size="2" face="Times New Roman">keyval</font><font size="2" face="宋体">，<wbr></wbr>内容就是使用者按的是哪一个键。<wbr></wbr>这些对于一个程序设计师来说常常是很有用的资讯。所以</font><font size="2" face="Times New Roman">event</font><font size="2" face="宋体"><wbr></wbr>的重要性</font><font size="2" face="Times New Roman"> </font><font size="2" face="宋体">是不可忽视的，就算刚开始会有点不懂，也要慢慢的融入才行。<wbr></wbr>这一节也非常重要。</font>&nbsp;<br />
&nbsp;</p>
<p align="justify"><font size="2" face="Times New Roman">PHP-GTK</font><font size="2" face="宋体">开发入门全集</font><font size="2" face="Times New Roman">(2)&nbsp;<br />
&nbsp;<br />
3. 安装PHP-GTK&nbsp;<br />
3.1 在Windows系统下安装&nbsp;<br />
首先要从</font><a target="_blank" href="http://gtk.php.net/download.php"><font size="2" face="Times New Roman"><u>http://gtk.php.net/<wbr></wbr>download.php</u></font></a><font size="2" face="宋体">下载</font><font size="2" face="Times New Roman">&#8230;HP-GTK</font><font size="2" face="宋体">的</font><font size="2" face="Times New Roman">window<wbr></wbr>s  binary</font><font size="2" face="宋体">档案</font><font size="2" face="Times New Roman">(</font><font size="2" face="宋体">本文撰写时为</font><font size="2" face="Times New Roman">0.5.1</font><font size="2" face="宋体">版</font><font size="2" face="Times New Roman">)</font><font size="2" face="宋体">。&nbsp;<br />
&nbsp;<br />
接着来看看PHP-GTK 0.5.1 binary档的内容：&nbsp;<br />
\php4 &rarr; php 和 php-gtk binary 档案&nbsp;<br />
\w</font><font size="2" face="Times New Roman">innt &rarr; </font><font size="2" face="宋体">预设的</font><font size="2" face="Times New Roman">php.ini</font><font size="2" face="宋体">档案&nbsp;<br />
\winnt\system32 &rarr; gtk binaries used by extension&nbsp;<br />
\test &rarr; 几个测试用的档案&nbsp;<br />
\README.txt &rarr; 安装说明档&nbsp;<br />
&nbsp;<br />
开始安装：&nbsp;<br />
1. 复制 \php4 的内容到你的php安装目录下(例C:\php)。&nbsp;<br />
2. 复制 \winnt 的内容到你的winnt资料夹。在Windows NT或Windows2000上是C:\winnt，<wbr></wbr>在Window95、98、xp上是C:\windows。<wbr></wbr>如果该资料夹里已经有  php.i</font><font size="2" face="Times New Roman">ni</font><font size="2" face="宋体">，那就不用做这个动作。&nbsp;<br />
3. 复制 \winnt\system32 的内容到你的winnt\system32资料夹。<wbr></wbr>在Windows  NT或Windows2000上是C:\winnt\<wbr></wbr>system32，在Window95、98、xp上是C:\<wbr></wbr>windows\system32。&nbsp;<br />
4. 复制 \test 的内容到你想要执行你的script的地方(此步骤非必要)。&nbsp;<br />
&nbsp;<br />
如何执行PHP-GTK程序：&nbsp;<br />
PHP-GTK程序可以在「开始」-「执行」下输入指令(<wbr></wbr>或是建立捷径)来启动，如：C:\php\php  -q c:\</font><font size="2" face="Times New Roman">php\test\gtk.php  ## </font><font size="2" face="宋体">表示不送印出</font><font size="2" face="Times New Roman"> HTTP Header</font><font size="2" face="宋体">，但一直使用这个视窗，直到关闭程序。&nbsp;<br />
C:\php\php -q -c php.ini c:\gtk.php ## 同上，但执行指定的php.ini设定。&nbsp;<br />
C:\php\php C:\php\test\gtk.php ## 表示会送印出 HTTP Header，但一直使&nbsp;<br />
用这个视窗，直到关闭程序&nbsp;<br />
C:\php\php_win C:\php\test\gtk.php ## 表示不使用视窗，执行后独立一个执行程序，他是使用  php -q模式，但是只要</font><font size="2" face="Times New Roman">output</font><font size="2" face="宋体">出任何字符，例如错误讯息，<wbr></wbr>就会停止执行。&nbsp;<br />
&nbsp;<br />
3.2 在UNIX系统下安装&nbsp;<br />
Debian的使用者可以在 </font><a target="_blank" href="http://www.debian.org/"><font size="2" face="Times New Roman"><u>http://www.debian.org</u></font></a><font size="2" face="Times New Roman"> </font><font size="2" face="宋体">下载</font><font size="2" face="Times New Roman">PHP-GTK</font><font size="2" face="宋体">的</font><font size="2" face="Times New Roman">binary</font><font size="2" face="宋体">档。系统需求须已安装下列</font><font size="2" face="Times New Roman">pa<wbr></wbr>ckage</font><font size="2" face="宋体">：&nbsp;<br />
&nbsp;<br />
PHP 4.1.0 或之后的版本，必须是编为CGI binary(command-line)  版本，包含所有的header files和devlement scri</font><font size="2" face="Times New Roman">pts</font><font size="2" face="宋体">。&nbsp;<br />
&nbsp;<br />
PHP-GTK支持GTK+ v1.2而需要安装1.2.6以上版本的GTK+。GTK+  v2.0还未被支持，<wbr></wbr>必须等到它开发完成并且普及了之后才会被支持。<wbr></wbr>你可以从下面的网址取得GTK+  v1.2.X的最新版本：</font><a target="_blank" href="ftp://ftp.gtk.org/pub/gtk/v1.2/"><font size="2" face="Times New Roman"><u>ftp://ftp.gtk.org/<wbr></wbr>pub/gtk/v1.2/</u></font></a><font size="2" face="Times New Roman">&nbsp;<br />
&nbsp;<br />
</font><font size="2" face="宋体">在将取得的档案解压缩或是由</font><font size="2" face="Times New Roman">CVS</font><font size="2" face="宋体">中</font><font size="2" face="Times New Roman">check out</font><font size="2" face="宋体">出来之后，切换到该目录下，开始进行安装</font><font size="2" face="Times New Roman">(</font><font size="2" face="宋体">打指令罗</font><font size="2" face="Times New Roman">~)</font><font size="2" face="宋体">：<wbr></wbr>&nbsp;<br />
</font><font size="2" face="Times New Roman">&nbsp;<br />
</font><font size="2" face="宋体">取得</font><font size="2" face="Times New Roman">CVS</font><font size="2" face="宋体">版本，执行&nbsp;<br />
cvs -d server:cvsread@cvs.php.net:/<wbr></wbr>repository co php-gtk&nbsp;<br />
或下载最新版本&nbsp;<br />
</font><a target="_blank" href="http://gtk.php.net/download.php"><font size="2" face="Times New Roman"><u>http://gtk.php.net/download.<wbr></wbr>php</u></font></a><font size="2" face="Times New Roman">&nbsp;<br />
&nbsp;<br />
1. ./buildconf&nbsp;<br />
2. ./configure (想要加装extensions的话请输任./<wbr></wbr>configure &#8211;help看说明)&nbsp;<br />
3. make(如果看到&quot;Could not write</font><font size="2" face="宋体">┅</font><font size="2" face="Times New Roman">&quot;</font><font size="2" face="宋体">，只是代表该</font><font size="2" face="Times New Roman">GTK+ object</font><font size="2" face="宋体">还没被支持，不算是什么错误讯息</font><font size="2" face="Times New Roman">)&nbsp;<br />
4. make install&nbsp;<br />
&nbsp;<br />
执行看看test/资料夹中的范例scripts来测试，<wbr></wbr>特别是gtk.php，这些都是展示如何使用的好例子。&nbsp;<br />
&nbsp;<br />
4. 第一支程序&nbsp;<br />
4.1 前言&nbsp;<br />
本章会教导各位一些常用的GtkClass(widget)，<wbr></wbr>还有运用这些来做出你的第一支PHP-GTK程序，<wbr></wbr>如果概念那章不是很熟的话，这章可以给你一个练习的机会喔!  如果对本章的内容有不懂或是想要深入了解其它的widget，<wbr></wbr>可以到</font><a target="_blank" href="http://gtk.php.net/manual/en/"><font size="2" face="Times New Roman"><u>http://gtk.php.net/manual/<wbr></wbr>en/</u></font></a><font size="2" face="Times New Roman"> </font><font size="2" face="宋体">看手册，手册里面有不少范例程序。&nbsp;<br />
&nbsp;<br />
4.2 会用到的widgets&nbsp;<br />
在开始写程序之前，先来对等一下会用到的widget class们做一个overview。&nbsp;<br />
&nbsp;<br />
GtkWindow()&nbsp;<br />
GtkWindow()建立一个视窗，里面有很多方法可以使用，<wbr></wbr>如：set_title,set_name,&nbsp;<br />
connect,set_border_width等┅。</font><font size="2" face="Times New Roman">&nbsp;<br />
&nbsp;<br />
GtkFrame()&nbsp;<br />
GtkFrame()纯粹建立一个好Border，<wbr></wbr>你可以设定它的label name,alignment,&nbsp;<br />
shadow(用英文，读Manual的时候会比较方便)。&nbsp;<br />
GtkVBox()&nbsp;<br />
GtkVBox()<wbr></wbr>建立一个直立的container来放入widgets。&nbsp;<br />
&nbsp;<br />
GtkLabel()&nbsp;<br />
GtkLabel()可以建立一个label，<wbr></wbr>内容文字可以建立时设定也可以建立后用方法来设定，<wbr></wbr>如果没有设定内容文字，将会建立一个空的label(这是废话吗</font><font size="2" face="宋体"><wbr></wbr>┅</font><font size="2" face="Times New Roman">?)</font><font size="2" face="宋体">。&nbsp;<br />
&nbsp;<br />
GtkHSeparator()&nbsp;<br />
GtkH</font><font size="2" face="Times New Roman">separator()</font><font size="2" face="宋体">建立一个水平线。&nbsp;<br />
&nbsp;<br />
GtkEntry()&nbsp;<br />
GtkEntry()建立一个textbox供使用者输入资讯。<wbr></wbr>&nbsp;<br />
&nbsp;<br />
GtkHButtonBox()&nbsp;<br />
GtkHButtonBox()<wbr></wbr>建立一个以水平方式排列Button的container。&nbsp;<br />
&nbsp;<br />
GktBtton()&nbsp;<br />
GtkButton()<wbr></wbr>或许可以说是GUI程序中最常用的widget了，<wbr></wbr>它建立一个可以让使用者按的按钮。 <br />
</font></p>
<p align="justify"><font size="2" face="宋体"> 4.3 开始 <br />
</font></p>
<p align="justify">&nbsp;</p>
<div class="dp-highlighter">
<div class="bar">&nbsp;</div>
<ol start="1" class="dp-c">
<li class="alt"><span><span>If(!class_exist(</span><span class="string">&quot;gtk&quot;</span><span>))&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>{&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span>dl(<span class="string">&quot;php_gtk.&quot;</span><span>.(</span><span class="func">strstr</span><span>(PHP_OS,</span><span class="string">&quot;WIN&quot;</span><span>)&nbsp;?&nbsp;</span><span class="string">&quot;dll&quot;</span><span>&nbsp;:&nbsp;</span><span class="string">&quot;so&quot;</span><span>));&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>}&nbsp;&nbsp;&nbsp;</span></li>
</ol>
</div>
<div style="display: none;" class="php">If(!class_exist(&quot;gtk&quot;))  {  dl(&quot;php_gtk.&quot;.(strstr(PHP_OS,&quot;WIN&quot;) ? &quot;dll&quot; : &quot;so&quot;));  }</div>
<p>&nbsp;</p>
<p><font size="2" face="Times New Roman"> 这段程序码会判断PHP-GTK延伸模组是否已启动，如果没有，<wbr></wbr>它就会读取适当的档案。在上面的范例中，<wbr></wbr>是靠判断执行的作业系统是Windows还是其它来判断要载入<a target="_blank" href="http://php_gtk.xn--dllphp_gtk-j07uf299a.so/">p<wbr></wbr>hp_gtk.dll还是php_gtk.so</a>。 <br />
</font></p>
<p>&nbsp;</p>
<div class="dp-highlighter">
<div class="bar">&nbsp;</div>
<ol start="1" class="dp-c">
<li class="alt"><span><span>Function&nbsp;delete_event()&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>{&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span><span class="keyword">return</span><span>&nbsp;false;&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>}&nbsp;&nbsp;&nbsp;</span></li>
</ol>
</div>
<div style="display: none;" class="php">Function delete_event()  {  return false;  }</div>
<p>&nbsp;</p>
<p><font size="2" face="Times New Roman"> 这里建立了一个名为delete_<wbr></wbr>event的function，<wbr></wbr>这个function是等会儿delete-event  signal发出时的callback function。内</font><font size="2" face="宋体">容传回</font><font size="2" face="Times New Roman">false</font><font size="2" face="宋体">会告诉</font><font size="2" face="Times New Roman">PHP-GTK</font><font size="2" face="宋体">用预<wbr></wbr>设的</font><font size="2" face="Times New Roman">signal handler</font><font size="2" face="宋体">来处理，而预设的</font><font size="2" face="Times New Roman">handler</font><font size="2" face="宋体">会关闭视窗</font><font size="2" face="Times New Roman">(</font><font size="2" face="宋体">同时<wbr></wbr>会呼叫该视窗的</font><font size="2" face="Times New Roman">destroy() </font><font size="2" face="宋体">函式</font><font size="2" face="Times New Roman">)</font><font size="2" face="宋体">，在这里，它会关闭程序</font><font size="2" face="Times New Roman">(</font><font size="2" face="宋体">因为这个范例程序只有一个主视窗<wbr></wbr>，一旦关闭就会关闭程序</font><font size="2" face="Times New Roman">)</font></p>
<p>&nbsp;</p>
<div class="dp-highlighter">
<div class="bar">&nbsp;</div>
<ol start="1" class="dp-c">
<li class="alt"><span><span>Function&nbsp;destroy()&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>{&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span>Gtk::main_quit();&nbsp;&nbsp;&nbsp;</span></li>
<li><span>}&nbsp;&nbsp;&nbsp;</span></li>
</ol>
</div>
<div style="display: none;" class="php">Function destroy()  {  Gtk::main_quit();  }</div>
<p>&nbsp;</p>
<p><font size="2" face="宋体"> 这里建立了一个函式，destroy()。在这个程序中，<wbr></wbr>这个函式是很重要的，因为我们在关闭程序的时候会连接到它。<wbr></wbr>之前说过，Gtk::  main_quit()会关闭程序，<wbr></wbr>如果我们在这个程序中没有定义这个</font><font size="2" face="Times New Roman">function</font><font size="2" face="宋体">或是这个</font><font size="2" face="Times New Roman">fu<wbr></wbr>nction</font><font size="2" face="宋体">里面没有</font><font size="2" face="Times New Roman">Gtk::main_quit ()</font><font size="2" face="宋体">这行，那么这个程序就不会关闭了。<wbr></wbr>以上一段程序码说明里提到的</font><font size="2" face="Times New Roman">delete-event</font><font size="2" face="宋体">来说，</font><font size="2" face="Times New Roman">re<wbr></wbr>turn false</font><font size="2" face="宋体">之后预设会执行关闭视窗的动作，还会呼叫</font><font size="2" face="Times New Roman">destro<wbr></wbr>y()</font><font size="2" face="宋体">函式，如果这里没有定义或是没有</font><font size="2" face="Times New Roman">Gtk::main_<wbr></wbr>quit()</font><font size="2" face="宋体">这段的话，主视窗</font><font size="2" face="Times New Roman"> </font><font size="2" face="宋体">的确会关闭，可是程序并不会结束，因为主程序回圈</font><font size="2" face="Times New Roman">aGtk::<wbr></wbr>main()</font><font size="2" face="宋体">还在跑。 <br />
</font></p>
<div class="dp-highlighter">
<div class="bar">&nbsp;</div>
<ol start="1" class="dp-c">
<li class="alt"><span><span class="vars">$window</span><span>&nbsp;=&nbsp;&amp;</span><span class="keyword">new</span><span>&nbsp;GtkWindow();&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span><span class="comment">//设定名字以辨别各个视窗&nbsp;</span><span>&nbsp;&nbsp;</span></span></li>
<li class="alt"><span><span class="vars">$window</span><span>-&gt;set_name(</span><span class="string">&#8216;main&nbsp;window&#8217;</span><span>);&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span><span class="comment">//设定视窗的标题&nbsp;</span><span>&nbsp;&nbsp;</span></span></li>
<li class="alt"><span><span class="vars">$window</span><span>-&gt;set_title(</span><span class="string">&#8216;对PHP-GTK的介绍&#8217;</span><span>);&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span><span class="comment">//设定视窗的大小&nbsp;</span><span>&nbsp;&nbsp;</span></span></li>
<li class="alt"><span><span class="vars">$window</span><span>-&gt;set_usize(160,&nbsp;120);&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span><span class="comment">//呼叫destroy()函式来结束程序&nbsp;</span><span>&nbsp;&nbsp;</span></span></li>
<li class="alt"><span><span class="vars">$window</span><span>-&gt;connect(</span><span class="string">&#8216;destroy&#8217;</span><span>,&nbsp;</span><span class="string">&#8216;destroy&#8217;</span><span>);&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span><span class="comment">//呼叫delete_event()函式来关闭视窗&nbsp;</span><span>&nbsp;&nbsp;</span></span></li>
<li class="alt"><span><span class="vars">$window</span><span>-&gt;connect(</span><span class="string">&#8216;delete-event&#8217;</span><span>,&nbsp;</span><span class="string">&#8216;delete_event&#8217;</span><span>);&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span><span class="comment">//设定视窗的边框宽度&nbsp;</span><span>&nbsp;&nbsp;</span></span></li>
<li class="alt"><span><span class="vars">$window</span><span>-&gt;set_border_width(10);&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span><span class="comment">//设定视窗的位置&nbsp;</span><span>&nbsp;&nbsp;</span></span></li>
<li class="alt"><span><span class="vars">$window</span><span>-&gt;set_position(GTK_WIN_POS_CENTER);&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span><span class="comment">//显示视窗和所有child&nbsp;widget&nbsp;(不显示就看不到)&nbsp;</span><span>&nbsp;&nbsp;</span></span></li>
<li class="alt"><span><span class="comment">//最后这两行一定要放在程序码的最后，否则什么都看不到&nbsp;</span><span>&nbsp;&nbsp;</span></span></li>
<li><span><span class="vars">$window</span><span>-&gt;show_all();&nbsp;&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>Gtk::main();&nbsp;&nbsp;&nbsp;</span></li>
<li><span>?&gt;&nbsp;&nbsp;&nbsp;</span></li>
</ol>
</div>
<div style="display: none;" class="php">$window = &amp;new GtkWindow();  //设定名字以辨别各个视窗  $window-&gt;set_name(&#8217;main window&#8217;);  //设定视窗的标题  $window-&gt;set_title(&#8217;对PHP-GTK的介绍&#8217;);  //设定视窗的大小  $window-&gt;set_usize(160, 120);  //呼叫destroy()函式来结束程序  $window-&gt;connect(&#8217;destroy&#8217;, &#8216;destroy&#8217;);  //呼叫delete_event()函式来关闭视窗  $window-&gt;connect(&#8217;delete-event&#8217;, &#8216;delete_event&#8217;);  //设定视窗的边框宽度  $window-&gt;set_border_width(10);  //设定视窗的位置  $window-&gt;set_position(GTK_WIN_POS_CENTER);  //显示视窗和所有child widget (不显示就看不到)  //最后这两行一定要放在程序码的最后，否则什么都看不到  $window-&gt;show_all();  Gtk::main();  ?&gt;</div>
</p>
<p><font size="2" face="宋体"> 执行程序可以看到如下的图： <br />
</font></p>
<p><font size="2" face="宋体"><img width="376" height="301" src="http://www.oursit.com/wp-content/uploads/1.jpg" alt="" /></font></p>
<div class="dp-highlighter">
<div class="bar">&nbsp;</div>
<ol start="1" class="dp-c">
<li class="alt"><span><span class="comment">//建立一个GtkFrame&nbsp;</span><span>&nbsp;&nbsp;</span></span></li>
<li><span><span class="vars">$frame</span><span>&quot;&nbsp;=&nbsp;&amp;</span><span class="keyword">new</span><span>&nbsp;GtkFrame(</span><span class="string">&#8216;经过简易修改的程序&#8217;</span><span>);&nbsp;&nbsp;&nbsp;</span></span></li>
<li class="alt"><span><span class="comment">//把GtkFrame放到GtkWindow里&nbsp;</span><span>&nbsp;&nbsp;</span></span></li>
<li><span><span class="vars">$window</span><span>-&gt;add(</span><span class="vars">$frame</span><span>);&nbsp;&nbsp;&nbsp;</span></span></li>
<li class="alt"><span><span class="comment">//最下面两行不要动&nbsp;</span><span>&nbsp;&nbsp;</span></span></li>
</ol>
</div>
<div style="display: none;" class="php">//建立一个GtkFrame  $frame&quot; = &amp;new GtkFrame(&#8217;经过简易修改的程序&#8217;);  //把GtkFrame放到GtkWindow里  $window-&gt;add($frame);  //最下面两行不要动</div>
</p>
<p><font size="2" face="Times New Roman"> 结果如下图：</font></p>
<p><font size="2" face="Times New Roman"><img width="380" height="311" src="http://www.oursit.com/wp-content/uploads/2.jpg" alt="" /></font></p>
<p><font size="2" face="宋体">下面这段建立一个</font><font size="2" face="Times New Roman">GtkVBox</font><font size="2" face="宋体">作为</font><font size="2" face="Times New Roman">container</font><font size="2" face="宋体">，并把</font><font size="2" face="Times New Roman">G<wbr></wbr>tkEntry</font><font size="2" face="宋体">、</font><font size="2" face="Times New Roman">GtkHSeperator</font><font size="2" face="宋体">、</font><font size="2" face="Times New Roman">GtkLabel</font><font size="2" face="宋体"><wbr></wbr>和</font><font size="2" face="Times New Roman"> GtkButtonBox</font><font size="2" face="宋体">都</font><font size="2" face="Times New Roman">pack</font><font size="2" face="宋体">进去，所谓</font><font size="2" face="Times New Roman">pack</font><font size="2" face="宋体">，是</font><font size="2" face="Times New Roman">Gt<wbr></wbr>kBox</font><font size="2" face="宋体">底下的</font><font size="2" face="Times New Roman">container</font><font size="2" face="宋体">们特别加入的放入</font><font size="2" face="Times New Roman">widget</font><font size="2" face="宋体"><wbr></wbr>的方法，就类似于</font><font size="2" face="Times New Roman">add ()</font><font size="2" face="宋体">，而</font><font size="2" face="Times New Roman">pack</font><font size="2" face="宋体">用的方法一般是</font><font size="2" face="Times New Roman">pack_start()</font><font size="2" face="宋体">和</font><font size="2" face="Times New Roman">pa<wbr></wbr>ck_end()</font><font size="2" face="宋体">，比</font><font size="2" face="Times New Roman">add()</font><font size="2" face="宋体">好的地方是可以控制将</font><font size="2" face="Times New Roman">widge<wbr></wbr>t</font><font size="2" face="宋体">增加进去之后</font><font size="2" face="Times New Roman"> widget</font><font size="2" face="宋体">的位置</font><font size="2" face="Times New Roman">(</font><font size="2" face="宋体">不过只要是</font><font size="2" face="Times New Roman">container</font><font size="2" face="宋体">就会有</font><font size="2" face="Times New Roman">add<wbr></wbr>()</font><font size="2" face="宋体">方法</font><font size="2" face="Times New Roman">)</font><font size="2" face="宋体">，欲查询详细资料请至&nbsp;<br />
</font><a target="_blank" href="http://gtk.php.net/manual/en"><font size="2" face="Times New Roman"><u>http://gtk.php.net/manual/en</u></font></a><font size="2" face="宋体">。 <br />
</font></p>
<div class="dp-highlighter">
<div class="bar">&nbsp;</div>
<ol start="1" class="dp-c">
<li class="alt"><span><span class="comment">//建立一个GtkVBox，为常用的container&nbsp;</span><span>&nbsp;&nbsp;</span></span></li>
<li><span><span class="vars">$box1</span><span>&quot;&nbsp;=&nbsp;&amp;</span><span class="keyword">new</span><span>&nbsp;GtkVBox();&nbsp;&nbsp;&nbsp;</span></span></li>
<li class="alt"><span><span class="comment">//把GtkVBox放到GtkFrame里面&nbsp;</span><span>&nbsp;&nbsp;</span></span></li>
<li><span><span class="vars">$frame</span><span>-&gt;add(</span><span class="vars">$box1</span><span>);&nbsp;&nbsp;&nbsp;</span></span></li>
<li class="alt"><span><span class="comment">//建立一个GtkLabel并将它pack到GtkVBox里&nbsp;</span><span>&nbsp;&nbsp;</span></span></li>
<li><span><span class="vars">$label</span><span>&nbsp;=&nbsp;&amp;</span><span class="keyword">new</span><span>&nbsp;GtkLabel();&nbsp;&nbsp;&nbsp;</span></span></li>
<li class="alt"><span><span class="vars">$box1</span><span>-&gt;pack_start(</span><span class="vars">$label</span><span>);&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span><span class="comment">//建立一个GtkHSeparator并将它pack到GtkVBox里&nbsp;</span><span>&nbsp;&nbsp;</span></span></li>
<li class="alt"><span><span class="vars">$separator</span><span>&nbsp;=&nbsp;&amp;</span><span class="keyword">new</span><span>&nbsp;GtkHSeparator();&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span><span class="vars">$box1</span><span>-&gt;pack_start(</span><span class="vars">$separator</span><span>);&nbsp;&nbsp;&nbsp;</span></span></li>
<li class="alt"><span><span class="comment">//建立一个GtkEntry并将它pack到GtkVBox里&nbsp;</span><span>&nbsp;&nbsp;</span></span></li>
<li><span><span class="vars">$entry</span><span>&nbsp;=&nbsp;&amp;</span><span class="keyword">new</span><span>&nbsp;GtkEntry();&nbsp;&nbsp;&nbsp;</span></span></li>
<li class="alt"><span><span class="vars">$box1</span><span>-&gt;pack_start(</span><span class="vars">$entry</span><span>);&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span><span class="comment">//建立一个GtkButtonBox并将它add到GtkVBox里&nbsp;</span><span>&nbsp;&nbsp;</span></span></li>
<li class="alt"><span><span class="comment">//因为GtkButtonBox也是一个无形的container，位置不重要，所以用add()&nbsp;</span><span>&nbsp;&nbsp;</span></span></li>
<li><span><span class="vars">$box2</span><span>&nbsp;=&nbsp;&amp;</span><span class="keyword">new</span><span>&nbsp;GtkHButtonBox();&nbsp;&nbsp;&nbsp;</span></span></li>
<li class="alt"><span><span class="vars">$box1</span><span>-&gt;add(</span><span class="vars">$box2</span><span>);&nbsp;&nbsp;&nbsp;</span></span></li>
</ol>
</div>
<div style="display: none;" class="php">//建立一个GtkVBox，为常用的container  $box1&quot; = &amp;new GtkVBox();  //把GtkVBox放到GtkFrame里面  $frame-&gt;add($box1);  //建立一个GtkLabel并将它pack到GtkVBox里  $label = &amp;new GtkLabel();  $box1-&gt;pack_start($label);  //建立一个GtkHSeparator并将它pack到GtkVBox里  $separator = &amp;new GtkHSeparator();  $box1-&gt;pack_start($separator);  //建立一个GtkEntry并将它pack到GtkVBox里  $entry = &amp;new GtkEntry();  $box1-&gt;pack_start($entry);  //建立一个GtkButtonBox并将它add到GtkVBox里  //因为GtkButtonBox也是一个无形的container，位置不重要，所以用add()  $box2 = &amp;new GtkHButtonBox();  $box1-&gt;add($box2);</div>
</p>
<p><font size="2" face="Times New Roman"> 执行如下图： <br />
</font></p>
<p><font size="2" face="Times New Roman"><img width="374" height="300" src="http://www.oursit.com/wp-content/uploads/3.jpg" alt="" /></font></p>
<p><font size="2" face="宋体">最后这段程序码会建立两个</font><font size="2" face="Times New Roman">GtkButton</font><font size="2" face="宋体">并</font><font size="2" face="Times New Roman">pack</font><font size="2" face="宋体">到</font><font size="2" face="Times New Roman">Gtk<wbr></wbr>ButtonBox</font><font size="2" face="宋体">里去，还有为两个按钮加上连接，<wbr></wbr>使它们起作用，并建立一个函式，只要按下</font><font size="2" face="Times New Roman">GtkButton</font><font size="2" face="宋体">就会<wbr></wbr>将</font><font size="2" face="Times New Roman">GtkLabel</font><font size="2" face="宋体">的内容换成</font><font size="2" face="Times New Roman">GtkEntry</font><font size="2" face="宋体">中的文字。 <br />
</font></p>
<div class="dp-highlighter">
<div class="bar">&nbsp;</div>
<ol start="1" class="dp-c">
<li class="alt"><span><span class="vars">$button</span><span>&quot;&nbsp;=&nbsp;&amp;</span><span class="keyword">new</span><span>&nbsp;GtkButton(</span><span class="string">&#8216;显示输入的字&#8217;</span><span>);&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span><span class="comment">//连接&quot;clicked&quot;&nbsp;signal到set_name()函式，附加$label和$entry两个widget&nbsp;</span><span>&nbsp;&nbsp;</span></span></li>
<li class="alt"><span><span class="vars">$button</span><span>-&gt;connect_object(</span><span class="string">&#8216;clicked&#8217;</span><span>,</span><span class="string">&#8217;set_name&#8217;</span><span>,</span><span class="vars">$label</span><span>,</span><span class="vars">$entry</span><span>);&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span><span class="vars">$box2</span><span>-&gt;pack_start(</span><span class="vars">$button</span><span>);&nbsp;&nbsp;&nbsp;</span></span></li>
<li class="alt"><span><span class="vars">$button</span><span>&nbsp;=&nbsp;&amp;</span><span class="keyword">new</span><span>&nbsp;GtkButton(</span><span class="string">&#8216;离开程序&#8217;</span><span>);&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span><span class="comment">//连接&quot;clicked&quot;&nbsp;signal到destroy()函式，将会关闭程序&nbsp;</span><span>&nbsp;&nbsp;</span></span></li>
<li class="alt"><span><span class="vars">$button</span><span>-&gt;connect(</span><span class="string">&#8216;clicked&#8217;</span><span>,</span><span class="string">&#8216;destroy&#8217;</span><span>);&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span><span class="vars">$box2</span><span>-&gt;pack_start(</span><span class="vars">$button</span><span>);&nbsp;&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;</span></li>
<li><span><span class="keyword">function</span><span>&nbsp;set_name(</span><span class="vars">$label</span><span>,</span><span class="vars">$entry</span><span>)&nbsp;&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>{&nbsp;&nbsp;&nbsp;</span></li>
<li><span><span class="comment">//用GtkEntry的get_text()方法从取得文字方块内容&nbsp;</span><span>&nbsp;&nbsp;</span></span></li>
<li class="alt"><span><span class="vars">$gettext</span><span>=</span><span class="vars">$entry</span><span>-&gt;get_text();&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span><span class="comment">//用GtkLabel的set_text()方法设定新的文字&nbsp;</span><span>&nbsp;&nbsp;</span></span></li>
<li class="alt"><span><span class="vars">$label</span><span>-&gt;set_text(</span><span class="vars">$gettext</span><span>);&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>}&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span><span class="comment">//最后再提一下那两行┅.&nbsp;</span><span>&nbsp;&nbsp;</span></span></li>
<li><span><span class="vars">$window</span><span>-&gt;show_all();&nbsp;&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>Gtk::main();&nbsp;&nbsp;&nbsp;</span></li>
</ol>
</div>
<div style="display: none;" class="php">$button&quot; = &amp;new GtkButton(&#8217;显示输入的字&#8217;);  //连接&quot;clicked&quot; signal到set_name()函式，附加$label和$entry两个widget  $button-&gt;connect_object(&#8217;clicked&#8217;,&#8217;set_name&#8217;,$label,$entry);  $box2-&gt;pack_start($button);  $button = &amp;new GtkButton(&#8217;离开程序&#8217;);  //连接&quot;clicked&quot; signal到destroy()函式，将会关闭程序  $button-&gt;connect(&#8217;clicked&#8217;,'destroy&#8217;);  $box2-&gt;pack_start($button);    function set_name($label,$entry)  {  //用GtkEntry的get_text()方法从取得文字方块内容  $gettext=$entry-&gt;get_text();  //用GtkLabel的set_text()方法设定新的文字  $label-&gt;set_text($gettext);  }  //最后再提一下那两行┅.  $window-&gt;show_all();  Gtk::main();</div>
</p>
<p><font size="2" face="Times New Roman"> 写到这里，整个程序就算是完成了，来看看执行的结果吧~ <br />
</font></p>
<p><font size="2" face="Times New Roman"><img width="326" height="261" src="http://www.oursit.com/wp-content/uploads/4.jpg" alt="" /></font></p>
<p><font size="2" face="Times New Roman"><img width="326" height="262" src="http://www.oursit.com/wp-content/uploads/5.jpg" alt="" /></font></p>
]]></content:encoded>
			<wfw:commentRss>http://www.oursit.com/archives/125.html/feed</wfw:commentRss>
		</item>
		<item>
		<title>Linux音频编程指南</title>
		<link>http://www.oursit.com/archives/123.html</link>
		<comments>http://www.oursit.com/archives/123.html#comments</comments>
		<pubDate>Sun, 31 Aug 2008 03:08:23 +0000</pubDate>
		<dc:creator>Skylin</dc:creator>
		
		<category><![CDATA[C/C++]]></category>

		<category><![CDATA[音频编程]]></category>

		<category><![CDATA[linux]]></category>

		<guid isPermaLink="false">http://www.oursit.com/?p=123</guid>
		<description><![CDATA[&#160;
2004-10-28&#160; &#160; 肖文鹏&#160; &#160; IBM DW &#160;
&#160;
虽然目前Linux的优势主要体现在网络服务方面，但事实上同样也有着非常丰富的媒体功能，本文就是以多媒体应用中最基本的声音为对象，介绍如何在Linux平台下开发实际的音频应用程序，同时还给出了一些常用的音频编程框架。&#160;
&#160;
一、数字音频&#160;
&#160;
音频信号是一种连续变化的模拟信号，但计算机只能处理和记录二进制的数字信号，由自然音源得到的音频信号必须经过一定的变换，成为数字音频信号之后，才能送到计算机中作进一步的处理。&#160;
&#160;
数字音频系统通过将声波的波型转换成一系列二进制数据，来实现对原始声音的重现，实现这一步骤的设备常被称为模/数转换器（A/D）。A/D转换器以每秒  钟上万次的速率对声波进行采样，每个采样点都记录下了原始模拟声波在某一时刻的状态，通常称之为样本（sample），而每一秒钟所采样的数目则称为采样  频率，通过将一串连续的样本连接起来，就可以在计算机中描述一段声音了。对于采样过程中的每一个样本来说，数字音频系统会分配一定存储位来记录声波的振  幅，一般称之为采样分辩率或者采样精度，采样精度越高，声音还原时就会越细腻。&#160;
&#160;
数字音频涉及到的概念非常多，对于在Linux下进行音频编程的程序员来说，最重要的是理解声音数字化的两个关键步骤：采样和量化。采样就是每隔一定时间  就读一次声音信号的幅度，而量化则是将采样得到的声音信号幅度转换为数字值，从本质上讲，采样是时间上的数字化，而量化则是幅度上的数字化。下面介绍几个  在进行音频编程时经常需要用到的技术指标：&#160;
&#160;
采样频率&#160;
采样频率是指将模拟声音波形进行数字化时，每秒钟抽取声波幅度样本的次数。采样频率的选择应该遵循奈奎斯特（Harry  Nyquist）采样理论：如果对某一模拟信号进行采样，则采样后可还原的最高信号频率只有采样频率的一半，或者说只要采样频率高于输入信号最高频率的两  倍，就能从采样信号系列重构原始信号。正常人听觉的频率范围大约在20Hz~20kHz之间，根据奈奎斯特采样理论，为了保证声音不失真，采样频率应该在  40kHz左右。常用的音频采样频率有8kHz、11.025kHz、22.05kHz、16kHz、37.8kHz、44.1kHz、48kHz等，如  果采用更高的采样频率，还可以达到DVD的音质。 &#160;
量化位数&#160;
量化位数是对模拟音频信号的幅度进行数字化，它决定了模拟信号数字化以后的动态范围，常用的有8位、12位和16位。量化位越高，信号的动态范围越大，数字化后的音频信号就越可能接近原始信号，但所需要的存贮空间也越大。 &#160;
声道数&#160;
声道数是反映音频数字化质量的另一个重要因素，它有单声道和双声道之分。双声道又称为立体声，在硬件中有两条线路，音质和音色都要优于单声道，但数字化后占据的存储空间的大小要比单声道多一倍。 &#160;
二、声卡驱动&#160;
&#160;
出于对安全性方面的考虑，Linux下的应用程序无法直接对声卡这类硬件设备进行操作，而是必须通过内核提供的驱动程序才能完成。在Linux上进行音频编程的本质就是要借助于驱动程序，来完成对声卡的各种操作。&#160;
&#160;
对硬件的控制涉及到寄存器中各个比特位的操作，通常这是与设备直接相关并且对时序的要求非常严格，如果这些工作都交由应用程序员来负责，那么对声卡的编程  将变得异常复杂而困难起来，驱动程序的作用正是要屏蔽硬件的这些底层细节，从而简化应用程序的编写。目前Linux下常用的声卡驱动程序主要有两种：  OSS和ALSA。&#160;
&#160;
最早出现在Linux上的音频编程接口是OSS（Open Sound System），它由一套完整的内核驱动程序模块组成，可以为绝大多数声卡提供统一的编程接口。OSS出现的历史相对较长，这些内核模块中的一部分  （OSS/Free）是与Linux内核源码共同免费发布的，另外一些则以二进制的形式由4Front  Technologies公司提供。由于得到了商业公司的鼎力支持，OSS已经成为在Linux下进行音频编程的事实标准，支持OSS的应用程序能够在绝  大多数声卡上工作良好。&#160;
&#160;
虽然OSS已经非常成熟，但它毕竟是一个没有完全开放源代码的商业产品，ALSA（Advanced  Linux Sound Architecture）恰好弥补了这一空白，它是在Linux下进行音频编程时另一个可供选择的声卡驱动程序。ALSA除了像OSS那样提供了一组内  核驱动程序模块之外，还专门为简化应用程序的编写提供了相应的函数库，与OSS提供的基于ioctl的原始编程接口相比，ALSA函数库使用起来要更加方  便一些。ALSA的主要特点有：&#160;
&#160;
支持多种声卡设备 &#160;
模块化的内核驱动程序 &#160;
支持SMP和多线程 &#160;
提供应用开发函数库 &#160;
兼容OSS应用程序 &#160;
ALSA和OSS最大的不同之处在于ALSA是由志愿者维护的自由项目，而OSS则是由公司提供的商业产品，因此在对硬件的适应程度上OSS要优于  ALSA，它能够支持的声卡种类更多。ALSA虽然不及OSS运用得广泛，但却具有更加友好的编程接口，并且完全兼容于OSS，对应用程序员来讲无疑是一 [...]]]></description>
			<content:encoded><![CDATA[<p>&nbsp;</p>
<p><span style="font-size: small;"><font face="宋体">2004-10-28&nbsp; &nbsp; 肖文鹏&nbsp; &nbsp; IBM DW &nbsp;<br />
&nbsp;<br />
虽然目前Linux的优势主要体现在网络服务方面，</font></span><font size="3" face="宋体"><wbr></wbr><span style="font-size: small;">但事实上同样也有着非常丰富的媒体功能，</span><wbr></wbr><span style="font-size: small;">本文就是以多媒体应用中最基本的声音为对象，</span><wbr></wbr><span style="font-size: small;">介绍如何在Linux平台下开发实际的音频应用程序，</span><wbr></wbr><span style="font-size: small;">同时还给出了一些常用的音频编程框架。&nbsp;<br />
&nbsp;<br />
一、数字音频&nbsp;<br />
&nbsp;<br />
音频信号是一种连续变化的模拟信号，</span><wbr></wbr><span style="font-size: small;">但计算机只能处理和记录二进制的数字信号，</span><wbr></wbr><span style="font-size: small;">由自然音源得到的音频信号必须经过一定的变换，</span><wbr></wbr><span style="font-size: small;">成为数字音频信号之后，才能送到计算机中作进一步的处理。&nbsp;<br />
&nbsp;<br />
数字音频系统通过将声波的波型转换成一系列二进制数据，</span><wbr></wbr><span style="font-size: small;">来实现对原始声音的重现，实现这一步骤的设备常被称为模/</span><wbr></wbr><span style="font-size: small;">数转换器（A/D）。A/D转换器以每秒  钟上万次的速率对声波进行采样，</span><wbr></wbr><span style="font-size: small;">每个采样点都记录下了原始模拟声波在某一时刻的状态，</span><wbr></wbr><span style="font-size: small;">通常称之为样本（sample），</span><wbr></wbr><span style="font-size: small;">而每一秒钟所采样的数目则称为采样  频率，通过将一串连续的样本连接起来，</span><wbr></wbr><span style="font-size: small;">就可以在计算机中描述一段声音了。</span><wbr></wbr><span style="font-size: small;">对于采样过程中的每一个样本来说，</span><wbr></wbr><span style="font-size: small;">数字音频系统会分配一定存储位来记录声波的振  幅，一般称之为采样分辩率或者采样精度，采样精度越高，</span><wbr></wbr><span style="font-size: small;">声音还原时就会越细腻。&nbsp;<br />
&nbsp;<br />
数字音频涉及到的概念非常多，</span><wbr></wbr><span style="font-size: small;">对于在Linux下进行音频编程的程序员来说，</span><wbr></wbr><span style="font-size: small;">最重要的是理解声音数字化的两个关键步骤：采样和量化。</span><wbr></wbr><span style="font-size: small;">采样就是每隔一定时间  就读一次声音信号的幅度，</span><wbr></wbr><span style="font-size: small;">而量化则是将采样得到的声音信号幅度转换为数字值，从本质上讲，</span><wbr></wbr><span style="font-size: small;">采样是时间上的数字化，而量化则是幅度上的数字化。下面介绍几个  在进行音频编程时经常需要用到的技术指标：&nbsp;<br />
&nbsp;<br />
采样频率&nbsp;<br />
采样频率是指将模拟声音波形进行数字化时，</span><wbr></wbr><span style="font-size: small;">每秒钟抽取声波幅度样本的次数。</span><wbr></wbr><span style="font-size: small;">采样频率的选择应该遵循奈奎斯特（Harry  Nyquist）采样理论：如果对某一模拟信号进行采样，</span><wbr></wbr><span style="font-size: small;">则采样后可还原的最高信号频率只有采样频率的一半，</span><wbr></wbr><span style="font-size: small;">或者说只要采样频率高于输入信号最高频率的两  倍，就能从采样信号系列重构原始信号。</span><wbr></wbr><span style="font-size: small;">正常人听觉的频率范围大约在20Hz~20kHz之间，</span><wbr></wbr><span style="font-size: small;">根据奈奎斯特采样理论，为了保证声音不失真，采样频率应该在  40kHz左右。常用的音频采样频率有8kHz、11.</span><wbr></wbr><span style="font-size: small;">025kHz、22.05kHz、16kHz、37.8kHz、</span><wbr></wbr><span style="font-size: small;">44.1kHz、48kHz等，如  果采用更高的采样频率，还可以达到DVD的音质。 &nbsp;<br />
量化位数&nbsp;<br />
量化位数是对模拟音频信号的幅度进行数字化，</span><wbr></wbr><span style="font-size: small;">它决定了模拟信号数字化以后的动态范围，常用的有8位、</span><wbr></wbr><span style="font-size: small;">12位和16位。量化位越高，信号的动态范围越大，</span><wbr></wbr><span style="font-size: small;">数字化后的音频信号就越可能接近原始信号，</span><wbr></wbr><span style="font-size: small;">但所需要的存贮空间也越大。 &nbsp;<br />
声道数&nbsp;<br />
声道数是反映音频数字化质量的另一个重要因素，</span><wbr></wbr><span style="font-size: small;">它有单声道和双声道之分。双声道又称为立体声，</span><wbr></wbr><span style="font-size: small;">在硬件中有两条线路，音质和音色都要优于单声道，</span><wbr></wbr><span style="font-size: small;">但数字化后占据的存储空间的大小要比单声道多一倍。 &nbsp;<br />
二、声卡驱动&nbsp;<br />
&nbsp;<br />
出于对安全性方面的考虑，</span><wbr></wbr><span style="font-size: small;">Linux下的应用程序无法直接对声卡这类硬件设备进行操作，</span><wbr></wbr><span style="font-size: small;">而是必须通过内核提供的驱动程序才能完成。</span><wbr></wbr><span style="font-size: small;">在Linux上进行音频编程的本质就是要借助于驱动程序，</span><wbr></wbr><span style="font-size: small;">来完成对声卡的各种操作。&nbsp;<br />
&nbsp;<br />
对硬件的控制涉及到寄存器中各个比特位的操作，</span><wbr></wbr><span style="font-size: small;">通常这是与设备直接相关并且对时序的要求非常严格，</span><wbr></wbr><span style="font-size: small;">如果这些工作都交由应用程序员来负责，那么对声卡的编程  将变得异常复杂而困难起来，</span><wbr></wbr><span style="font-size: small;">驱动程序的作用正是要屏蔽硬件的这些底层细节，</span><wbr></wbr><span style="font-size: small;">从而简化应用程序的编写。</span><wbr></wbr><span style="font-size: small;">目前Linux下常用的声卡驱动程序主要有两种：  OSS和ALSA。&nbsp;<br />
&nbsp;<br />
最早出现在Linux上的音频编程接口是OSS（Open Sound System），它由一套完整的内核驱动程序模块组成，</span><wbr></wbr><span style="font-size: small;">可以为绝大多数声卡提供统一的编程接口。</span><wbr></wbr><span style="font-size: small;">OSS出现的历史相对较长，这些内核模块中的一部分  （OSS/Free）是与Linux内核源码共同免费发布的，</span><wbr></wbr><span style="font-size: small;">另外一些则以二进制的形式由4Front  Technologies公司提供。</span><wbr></wbr><span style="font-size: small;">由于得到了商业公司的鼎力支持，</span><wbr></wbr><span style="font-size: small;">OSS已经成为在Linux下进行音频编程的事实标准，</span><wbr></wbr><span style="font-size: small;">支持OSS的应用程序能够在绝  大多数声卡上工作良好。&nbsp;<br />
&nbsp;<br />
虽然OSS已经非常成熟，</span><wbr></wbr><span style="font-size: small;">但它毕竟是一个没有完全开放源代码的商业产品，ALSA（</span><wbr></wbr><span style="font-size: small;">Advanced  Linux Sound Architecture）恰好弥补了这一空白，</span><wbr></wbr><span style="font-size: small;">它是在Linux下进行音频编程时另一个可供选择的声卡驱动程序</span><wbr></wbr><span style="font-size: small;">。ALSA除了像OSS那样提供了一组内  核驱动程序模块之外，</span><wbr></wbr><span style="font-size: small;">还专门为简化应用程序的编写提供了相应的函数库，</span><wbr></wbr><span style="font-size: small;">与OSS提供的基于ioctl的原始编程接口相比，</span><wbr></wbr><span style="font-size: small;">ALSA函数库使用起来要更加方  便一些。ALSA的主要特点有：&nbsp;<br />
&nbsp;<br />
支持多种声卡设备 &nbsp;<br />
模块化的内核驱动程序 &nbsp;<br />
支持SMP和多线程 &nbsp;<br />
提供应用开发函数库 &nbsp;<br />
兼容OSS应用程序 &nbsp;<br />
ALSA和OSS最大的不同之处在于ALSA是由志愿者维护的自</span><wbr></wbr><span style="font-size: small;">由项目，而OSS则是由公司提供的商业产品，</span><wbr></wbr><span style="font-size: small;">因此在对硬件的适应程度上OSS要优于  ALSA，它能够支持的声卡种类更多。</span><wbr></wbr><span style="font-size: small;">ALSA虽然不及OSS运用得广泛，</span><wbr></wbr><span style="font-size: small;">但却具有更加友好的编程接口，并且完全兼容于OSS，</span><wbr></wbr><span style="font-size: small;">对应用程序员来讲无疑是一  个更佳的选择。&nbsp;<br />
&nbsp;<br />
三、编程接口&nbsp;<br />
&nbsp;<br />
如何对各种音频设备进行操作是在Linux上进行音频编程的关键</span><wbr></wbr><span style="font-size: small;">，通过内核提供的一组系统调用，</span><wbr></wbr><span style="font-size: small;">应用程序能够访问声卡驱动程序提供的各种音频设备接口，</span><wbr></wbr><span style="font-size: small;">这是在Linux下进行音频编程最简单也是最直接的方法。&nbsp;<br />
&nbsp;<br />
3.1 访问音频设备&nbsp;<br />
&nbsp;<br />
无论是OSS还是ALSA，</span><wbr></wbr><span style="font-size: small;">都是以内核驱动程序的形式运行在Linux内核空间中的，</span><wbr></wbr><span style="font-size: small;">应用程序要想访问声卡这一硬件设备，</span><wbr></wbr><span style="font-size: small;">必须借助于Linux内核所提供  的系统调用（system call）。从程序员的角度来说，</span><wbr></wbr><span style="font-size: small;">对声卡的操作在很大程度上等同于对磁盘文件的操作：</span><wbr></wbr><span style="font-size: small;">首先使用open系统调用建立起与硬件间的联系，</span><wbr></wbr><span style="font-size: small;">此时返回的文件描述  符将作为随后操作的标识；</span><wbr></wbr><span style="font-size: small;">接着使用read系统调用从设备接收数据，</span><wbr></wbr><span style="font-size: small;">或者使用write系统调用向设备写入数据，</span><wbr></wbr><span style="font-size: small;">而其它所有不符合读/写这一基本模式的操  作都可以由ioctl系统调用来完成；最后，</span><wbr></wbr><span style="font-size: small;">使用close系统调用告诉Linux内核不会再对该设备做进一</span><wbr></wbr><span style="font-size: small;">步的处理。&nbsp;<br />
&nbsp;<br />
open系统调用&nbsp;<br />
系统调用open可以获得对声卡的访问权，</span><wbr></wbr></font><span style="font-size: small;"><font face="宋体">同时还能为随后的系统调用做好准备，其函数原型如下所示：</font></span></p>
<p><span style="font-size: small;"><font face="宋体">int open(const char *pathname, int flags,  int mode);</font></span></p>
<p><span style="font-size: small;"><font face="宋体"> 参 数pathname是将要被打开的设备文件的名称，</font></span><font size="3" face="宋体"><wbr></wbr><span style="font-size: small;">对于声卡来讲一般是/dev/dsp。</span><wbr></wbr><span style="font-size: small;">参数flags用来指明应该以什么方式打开设备文件，它可以是  O_RDONLY、O_WRONLY或者O_RDWR，</span><wbr></wbr><span style="font-size: small;">分别表示以只读、只写或者读写的方式打开设备文件；</span><wbr></wbr><span style="font-size: small;">参数mode通常是可选的，它只有在指定的设备  文件不存在时才会用到，指明新创建的文件应该具有怎样的权限。&nbsp;<br />
如果open系统调用能够成功完成，</span><wbr></wbr><span style="font-size: small;">它将返回一个正整数作为文件标识符，</span><wbr></wbr><span style="font-size: small;">在随后的系统调用中需要用到该标识符。</span><wbr></wbr><span style="font-size: small;">如果open系统调用失败，它将返回-1，</span><wbr></wbr><span style="font-size: small;">同时还会设置全局变量errno，</span><wbr></wbr></font><span style="font-size: small;"><font face="宋体">指明是什么原因导致了错误的发生。 &nbsp;<br />
read系统调用&nbsp;<br />
系统调用read用来从声卡读取数据，其函数原型如下所示：</font></span></p>
<p><span style="font-size: small;"><font face="宋体">int read(int fd, char *buf, size_t count);</font></span></p>
<p><span style="font-size: small;"><font face="宋体"> 参 数fd是设备文件的标识符，</font></span><font size="3" face="宋体"><wbr></wbr><span style="font-size: small;">它是通过之前的open系统调用获得的；</span><wbr></wbr><span style="font-size: small;">参数buf是指向缓冲区的字符指针，</span><wbr></wbr><span style="font-size: small;">它用来保存从声卡获得的数据；参数count则用  来限定从声卡获得的最大字节数。如果read系统调用成功完成，</span><wbr></wbr><span style="font-size: small;">它将返回从声卡实际读取的字节数，</span><wbr></wbr><span style="font-size: small;">通常情况会比count的值要小一些；如果read系统  调用失败，它将返回-1，同时还会设置全局变量errno，</span><wbr></wbr></font><span style="font-size: small;"><font face="宋体">来指明是什么原因导致了错误的发生。 &nbsp;<br />
write系统调用&nbsp;<br />
系统调用write用来向声卡写入数据，其函数原型如下所示：</font></span></p>
<p><span style="font-size: small;"><font face="宋体">size_t write(int fd, const char *buf,  size_t count);</font></span></p>
<p><span style="font-size: small;"><font face="宋体"> 系 统调用write和系统调用read在很大程度是类似的，</font></span><font size="3" face="宋体"><wbr></wbr><span style="font-size: small;">差别只在于write是向声卡写入数据，</span><wbr></wbr><span style="font-size: small;">而read则是从声卡读入数据。参数fd同样是设备文件  的标识符，它也是通过之前的open系统调用获得的；</span><wbr></wbr><span style="font-size: small;">参数buf是指向缓冲区的字符指针，</span><wbr></wbr><span style="font-size: small;">它保存着即将向声卡写入的数据；参数count则用来限定向声卡  写入的最大字节数。&nbsp;<br />
如果write系统调用成功完成，</span><wbr></wbr><span style="font-size: small;">它将返回向声卡实际写入的字节数；如果read系统调用失败，</span><wbr></wbr><span style="font-size: small;">它将返回-1，同时还会设置全局变量errno，来指明是  什么原因导致了错误的发生。无论是read还是write，</span><wbr></wbr><span style="font-size: small;">一旦调用之后Linux内核就会阻塞当前应用程序，</span><wbr></wbr><span style="font-size: small;">直到数据成功地从声卡读出或者写入为止。 &nbsp;<br />
ioctl系统调用&nbsp;<br />
系统调用ioctl可以对声卡进行控制，</span><wbr></wbr><span style="font-size: small;">凡是对设备文件的操作不符合读/写基本模式的，</span><wbr></wbr><span style="font-size: small;">都是通过ioctl来完成的，它可以影响设备的行为，</span><wbr></wbr></font><span style="font-size: small;"><font face="宋体">或者返回设备的状态，其函数原型如下所示：</font></span></p>
<p><span style="font-size: small;"><font face="宋体">int ioctl(int fd, int request, &#8230;);</font></span></p>
<p><span style="font-size: small;"><font face="宋体"> 参 数fd是设备文件的标识符，它是在设备打开时获得的；</font></span><font size="3" face="宋体"><wbr></wbr><span style="font-size: small;">如果设备比较复杂，那么对它的控制请求相应地也会有很多种，</span><wbr></wbr><span style="font-size: small;">参数request的目的就是用来区分不  同的控制请求；通常说来，在对设备进行控制时还需要有其它参数，</span><wbr></wbr><span style="font-size: small;">这要根据不同的控制请求才能确定，</span><wbr></wbr><span style="font-size: small;">并且可能是与硬件设备直接相关的。 &nbsp;<br />
close系统调用&nbsp;<br />
当应用程序使用完声卡之后，需要用close系统调用将其关闭，</span><wbr></wbr></font><span style="font-size: small;"><font face="宋体">以便及时释放占用的硬件资源，其函数原型如下所示：</font></span></p>
<p><span style="font-size: small;"><font face="宋体">int close(int fd);</font></span></p>
<p><span style="font-size: small;"><font face="宋体"> 参数fd是设备文件的标识符，它是在设备打开时获得的。</font></span><font size="3" face="宋体"><wbr></wbr><span style="font-size: small;">一旦应用程序调用了close系统调用，</span><wbr></wbr><span style="font-size: small;">Linux内核就会释放与之相关的各种资源，</span><wbr></wbr><span style="font-size: small;">因此建议在不需要的时候尽量及时关闭已经打开的设备。 &nbsp;<br />
3.2 音频设备文件&nbsp;<br />
&nbsp;<br />
对于Linux应用程序员来讲，</span><wbr></wbr><span style="font-size: small;">音频编程接口实际上就是一组音频设备文件，</span><wbr></wbr><span style="font-size: small;">通过它们可以从声卡读取数据，或者向声卡写入数据，</span><wbr></wbr><span style="font-size: small;">并且能够对声卡进行控制，设置采样频率和声道数目等等。&nbsp;<br />
&nbsp;<br />
/dev/sndstat&nbsp;<br />
设备文件/dev/</span><wbr></wbr><span style="font-size: small;">sndstat是声卡驱动程序提供的最简单的接口，</span><wbr></wbr><span style="font-size: small;">通常它是一个只读文件，作用也仅仅只限于汇报声卡的当前状态。</span><wbr></wbr><span style="font-size: small;">一般说来，  /dev/sndstat是提供给最终用户来检测声卡的，</span><wbr></wbr><span style="font-size: small;">不宜用于程序当中，</span><wbr></wbr><span style="font-size: small;">因为所有的信息都可以通过ioctl系统调用来获得。  Linux提供的cat命令可以很方便地从/dev/</span><wbr></wbr><span style="font-size: small;">sndstat获得声卡的当前状态：  [xiaowp@linuxgam sound]$ cat /dev/sndstat &nbsp;<br />
/dev/dsp&nbsp;<br />
&nbsp;<br />
声卡驱动程序提供的/dev/dsp是用于数字采样（</span><wbr></wbr><span style="font-size: small;">sampling）和数字录音（recording）</span><wbr></wbr><span style="font-size: small;">的设备文件，它对于Linux下的音频编程来讲  非常重要：向该设备写数据即意味着激活声卡上的D/</span><wbr></wbr><span style="font-size: small;">A转换器进行放音，而向该设备读数据则意味着激活声卡上的A/</span><wbr></wbr><span style="font-size: small;">D转换器进行录音。目前许多声卡都提供有  多个数字采样设备，它们在Linux下可以通过/dev/</span><wbr></wbr><span style="font-size: small;">dsp1等设备文件进行访问。&nbsp;<br />
&nbsp;<br />
DSP是数字信号处理器（Digital Signal Processor）的简称，</span><wbr></wbr><span style="font-size: small;">它是用来进行数字信号处理的特殊芯片，</span><wbr></wbr><span style="font-size: small;">声卡使用它来实现模拟信号和数字信号的转换。</span><wbr></wbr><span style="font-size: small;">声卡中的DSP设备实际上包含两个组成部  分：在以只读方式打开时，能够使用A/D转换器进行声音的输入；</span><wbr></wbr><span style="font-size: small;">而在以只写方式打开时，则能够使用D/A转换器进行声音的输出。</span><wbr></wbr><span style="font-size: small;">严格说来，Linux下的  应用程序要么以只读方式打开/dev/dsp输入声音，</span><wbr></wbr><span style="font-size: small;">要么以只写方式打开/dev/dsp输出声音，</span><wbr></wbr><span style="font-size: small;">但事实上某些声卡驱动程序仍允许以读写的方式打开  /dev/dsp，以便同时进行声音的输入和输出，</span><wbr></wbr><span style="font-size: small;">这对于某些应用场合（如IP电话）来讲是非常关键的。&nbsp;<br />
&nbsp;<br />
在从DSP设备读取数据时，从声卡输入的模拟信号经过A/</span><wbr></wbr><span style="font-size: small;">D转换器变成数字采样后的样本（sample），</span><wbr></wbr><span style="font-size: small;">保存在声卡驱动程序的内核缓冲区中，当应用程序  通过read系统调用从声卡读取数据时，</span><wbr></wbr><span style="font-size: small;">保存在内核缓冲区中的数字采样结果将被复制到应用程序所指定的用</span><wbr></wbr><span style="font-size: small;">户缓冲区中。需要指出的是，声卡采样频率是由内核  中的驱动程序所决定的，</span><wbr></wbr><span style="font-size: small;">而不取决于应用程序从声卡读取数据的速度。</span><wbr></wbr><span style="font-size: small;">如果应用程序读取数据的速度过慢，以致低于声卡的采样频率，</span><wbr></wbr><span style="font-size: small;">那么多余的数据将会被丢弃；  如果读取数据的速度过快，以致高于声卡的采样频率，</span><wbr></wbr><span style="font-size: small;">那么声卡驱动程序将会阻塞那些请求数据的应用程序，</span><wbr></wbr><span style="font-size: small;">直到新的数据到来为止。&nbsp;<br />
&nbsp;<br />
在向DSP设备写入数据时，数字信号会经过D/</span><wbr></wbr><span style="font-size: small;">A转换器变成模拟信号，然后产生出声音。</span><wbr></wbr><span style="font-size: small;">应用程序写入数据的速度同样应该与声卡的采样频率相匹配，</span><wbr></wbr><span style="font-size: small;">否则过慢  的话会产生声音暂停或者停顿的现象，</span><wbr></wbr><span style="font-size: small;">过快的话又会被内核中的声卡驱动程序阻塞，</span><wbr></wbr><span style="font-size: small;">直到硬件有能力处理新的数据为止。与其它设备有所不同，</span><wbr></wbr><span style="font-size: small;">声卡通常不会支持非  阻塞（non-blocking）的I/O操作。&nbsp;<br />
&nbsp;<br />
无论是从声卡读取数据，或是向声卡写入数据，</span><wbr></wbr><span style="font-size: small;">事实上都具有特定的格式（format），</span><wbr></wbr><span style="font-size: small;">默认为8位无符号数据、单声道、8KHz采样率，</span><wbr></wbr><span style="font-size: small;">如果默认值无法达  到要求，可以通过ioctl系统调用来改变它们。通常说来，</span><wbr></wbr><span style="font-size: small;">在应用程序中打开设备文件/dev/dsp之后，</span><wbr></wbr><span style="font-size: small;">接下去就应该为其设置恰当的格式，然后才能从  声卡读取或者写入数据。&nbsp;<br />
&nbsp;<br />
/dev/audio&nbsp;<br />
/dev/audio类似于/dev/dsp，</span><wbr></wbr><span style="font-size: small;">它兼容于Sun工作站上的音频设备，使用的是mu-</span><wbr></wbr><span style="font-size: small;">law编码方式。如果声卡驱动程序提供了对  /dev/audio的支持，</span><wbr></wbr><span style="font-size: small;">那么在Linux上就可以通过cat命令，</span><wbr></wbr><span style="font-size: small;">来播放在Sun工作站上用mu-law进行编码的音频文件： &nbsp;<br />
[xiaowp@linuxgam sound]$ cat audio.au &gt; /dev/audio&nbsp;<br />
&nbsp;<br />
&nbsp;<br />
由于设备文件/dev/audio主要出于对兼容性的考虑，</span><wbr></wbr><span style="font-size: small;">所以在新开发的应用程序中最好不要尝试用它，而应该以/dev/</span><wbr></wbr><span style="font-size: small;">dsp进行替代。对于应用程序来说，同一时刻只能使用/dev/</span><wbr></wbr><span style="font-size: small;">audio或者/dev/dsp其中之一，</span><wbr></wbr><span style="font-size: small;">因为它们是相同硬件的不同软件接口。 &nbsp;<br />
/dev/mixer&nbsp;<br />
在声卡的硬件电路中，混音器（mixer）</span><wbr></wbr><span style="font-size: small;">是一个很重要的组成部分，</span><wbr></wbr><span style="font-size: small;">它的作用是将多个信号组合或者叠加在一起，对于不同的声卡来说，</span><wbr></wbr><span style="font-size: small;">其混音器的作用可能各  不相同。运行在Linux内核中的声卡驱动程序一般都会提供/</span><wbr></wbr><span style="font-size: small;">dev/mixer这一设备文件，</span><wbr></wbr><span style="font-size: small;">它是应用程序对混音器进行操作的软件接口。混音器电路通常  由两个部分组成：输入混音器（input mixer）和输出混音器（output  mixer）。&nbsp;<br />
输入混音器负责从多个不同的信号源接收模拟信号，</span><wbr></wbr><span style="font-size: small;">这些信号源有时也被称为混音通道或者混音设备。</span><wbr></wbr><span style="font-size: small;">模拟信号通过增益控制器和由软件控制的音量调节器后，在不  同的混音通道中进行级别（level）调制，</span><wbr></wbr><span style="font-size: small;">然后被送到输入混音器中进行声音的合成。</span><wbr></wbr><span style="font-size: small;">混音器上的电子开关可以控制哪些通道中有信号与混音器相连，</span><wbr></wbr><span style="font-size: small;">有些声卡  只允许连接一个混音通道作为录音的音源，</span><wbr></wbr><span style="font-size: small;">而有些声卡则允许对混音通道做任意的连接。</span><wbr></wbr><span style="font-size: small;">经过输入混音器处理后的信号仍然为模拟信号，它们将被送到A/</span><wbr></wbr><span style="font-size: small;">D转换器  进行数字化处理。&nbsp;<br />
输出混音器的工作原理与输入混音器类似，</span><wbr></wbr><span style="font-size: small;">同样也有多个信号源与混音器相连，并且事先都经过了增益调节。</span><wbr></wbr><span style="font-size: small;">当输出混音器对所有的模拟信号进行了混合之后，通常  还会有一个总控增益调节器来控制输出声音的大小，</span><wbr></wbr><span style="font-size: small;">此外还有一些音调控制器来调节输出声音的音调。</span><wbr></wbr><span style="font-size: small;">经过输出混音器处理后的信号也是模拟信号，它们最终会被送  给喇叭或者其它的模拟输出设备。</span><wbr></wbr><span style="font-size: small;">对混音器的编程包括如何设置增益控制器的级别，</span><wbr></wbr><span style="font-size: small;">以及怎样在不同的音源间进行切换，这些操作通常来讲是不连续的，</span><wbr></wbr><span style="font-size: small;">而且不会像  录音或者放音那样需要占用大量的计算机资源。</span><wbr></wbr><span style="font-size: small;">由于混音器的操作不符合典型的读/写操作模式，</span><wbr></wbr><span style="font-size: small;">因此除了open和close两个系统调用之外，大部分的操作  都是通过ioctl系统调用来完成的。与/dev/dsp不同，</span><wbr></wbr><span style="font-size: small;">/dev/mixer允许多个应用程序同时访问，</span><wbr></wbr><span style="font-size: small;">并且混音器的设置值会一直保持到对应的设  备文件被关闭为止。&nbsp;<br />
为了简化应用程序的设计，</span><wbr></wbr><span style="font-size: small;">Linux上的声卡驱动程序大多都支持将混音器的ioctl操作</span><wbr></wbr><span style="font-size: small;">直接应用到声音设备上，也就是说如果已经打开了  /dev/dsp，那么就不用再打开/dev/</span><wbr></wbr><span style="font-size: small;">mixer来对混音器进行操作，而是可以直接用打开/dev/</span><wbr></wbr><span style="font-size: small;">dsp时得到的文件标识符来设置混音器。 &nbsp;<br />
/dev/sequencer&nbsp;<br />
目前大多数声卡驱动程序还会提供/dev/</span><wbr></wbr><span style="font-size: small;">sequencer这一设备文件，</span><wbr></wbr><span style="font-size: small;">用来对声卡内建的波表合成器进行操作，</span><wbr></wbr><span style="font-size: small;">或者对MIDI总线上的乐器进行控制，</span><wbr></wbr><span style="font-size: small;">一般只用于计算机音乐软件中。 &nbsp;<br />
四、应用框架&nbsp;<br />
&nbsp;<br />
在Linux下进行音频编程时，</span><wbr></wbr><span style="font-size: small;">重点在于如何正确地操作声卡驱动程序所提供的各种设备文件，</span><wbr></wbr><span style="font-size: small;">由于涉及到的概念和因素比较多，</span><wbr></wbr><span style="font-size: small;">所以遵循一个通用的框架无疑将有助于简化应用程序的设计。&nbsp;<br />
&nbsp;<br />
4.1 DSP编程&nbsp;<br />
&nbsp;<br />
对声卡进行编程时首先要做的是打开与之对应的硬件设备，</span><wbr></wbr><span style="font-size: small;">这是借助于open系统调用来完成的，并且一般情况下使用的是/</span><wbr></wbr><span style="font-size: small;">dev/dsp文件。采用何种模式  对声卡进行操作也必须在打开设备时指定，</span><wbr></wbr><span style="font-size: small;">对于不支持全双工的声卡来说，应该使用只读或者只写的方式打开，</span><wbr></wbr><span style="font-size: small;">只有那些支持全双工的声卡，才能以读写的方式打  开，并且还要依赖于驱动程序的具体实现。</span><wbr></wbr><span style="font-size: small;">Linux允许应用程序多次打开或者关闭与声卡对应的设备文件，</span><wbr></wbr><span style="font-size: small;">从而能够很方便地在放音状态和录音状态之间进行切  换，</span><wbr></wbr><span style="font-size: small;">建议在进行音频编程时只要有可能就尽量使用只读或者只写的方式打</span><wbr></wbr><span style="font-size: small;">开设备文件，因为这样不仅能够充分利用声卡的硬件资源，</span><wbr></wbr><span style="font-size: small;">而且还有利于驱动程序的优化。  下面的代码示范了如何以只写方式打开声卡进行放音（</span><wbr></wbr></font><span style="font-size: small;"><font face="宋体">playback）操作：</font></span></p>
<p>&nbsp;</p>
<div>
<div class="dp-highlighter">
<div class="bar">&nbsp;</div>
<ol start="1" class="dp-cpp">
<li class="alt"><span><span class="datatypes">int</span><span>&nbsp;handle&nbsp;=&nbsp;open(</span><span class="string">&quot;/dev/dsp&quot;</span><span>,&nbsp;O_WRONLY);&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span><span class="keyword">if</span><span>&nbsp;(handle&nbsp;==&nbsp;-1)&nbsp;{&nbsp;&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>perror(<span class="string">&quot;open&nbsp;/dev/dsp&quot;</span><span>);&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span><span class="keyword">return</span><span>&nbsp;-1;&nbsp;&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>}&nbsp;&nbsp;</span></li>
</ol>
</div>
<div style="display: none;" class="cpp">int handle = open(&quot;/dev/dsp&quot;, O_WRONLY);  if (handle == -1) {  perror(&quot;open /dev/dsp&quot;);  return -1;  }</div>
<link rel="stylesheet" type="text/css" href="/wp-content/plugins/fckeditor_for_wordpress/fckeditor/editor/plugins/highlighter/dp.SyntaxHighlighter/Styles/SyntaxHighlighter.css" /></div>
<p><span style="font-size: small;"><font face="宋体"> 运 行在Linux内核中的声卡驱动程序专门维护了一个缓冲区，</font></span><font size="3" face="宋体"><wbr></wbr><span style="font-size: small;">其大小会影响到放音和录音时的效果，</span><wbr></wbr><span style="font-size: small;">使用ioctl系统调用可以对它的尺寸进行恰当的设置。调  节驱动程序中缓冲区大小的操作不是必须的，如果没有特殊的要求，</span><wbr></wbr><span style="font-size: small;">一般采用默认的缓冲区大小也就可以了。但需要注意的是，</span><wbr></wbr><span style="font-size: small;">缓冲区大小的设置通常应紧跟在设备  文件打开之后，</span><wbr></wbr><span style="font-size: small;">这是因为对声卡的其它操作有可能会导致驱动程序无法再修改其缓冲</span><wbr></wbr><span style="font-size: small;">区的大小。</span><wbr></wbr></font><span style="font-size: small;"><font face="宋体">下面的代码示范了怎样设置声卡驱动程序中的内核缓冲区的大小：</font></span></p>
<p>&nbsp;</p>
<div>
<div class="dp-highlighter">
<div class="bar">&nbsp;</div>
<ol start="1" class="dp-cpp">
<li class="alt"><span><span class="datatypes">int</span><span>&nbsp;setting&nbsp;=&nbsp;0xnnnnssss;&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span><span class="datatypes">int</span><span>&nbsp;result&nbsp;=&nbsp;ioctl(handle,&nbsp;SNDCTL_DSP_SETFRAGMENT,&nbsp;&amp;setting);&nbsp;&nbsp;&nbsp;</span></span></li>
<li class="alt"><span><span class="keyword">if</span><span>&nbsp;(result&nbsp;==&nbsp;-1)&nbsp;{&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>perror(<span class="string">&quot;ioctl&nbsp;buffer&nbsp;size&quot;</span><span>);&nbsp;&nbsp;&nbsp;</span></span></li>
<li class="alt"><span><span class="keyword">return</span><span>&nbsp;-1;&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>}&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span><span class="comment">//&nbsp;检查设置值的正确性</span><span>&nbsp;&nbsp;</span></span></li>
</ol>
</div>
<div style="display: none;" class="cpp">int setting = 0xnnnnssss;  int result = ioctl(handle, SNDCTL_DSP_SETFRAGMENT, &amp;setting);  if (result == -1) {  perror(&quot;ioctl buffer size&quot;);  return -1;  }  // 检查设置值的正确性</div>
</div>
<p><span style="font-size: small;"><font face="宋体"> 在 设置缓冲区大小时，参数setting实际上由两部分组成，</font></span><font size="3" face="宋体"><wbr></wbr><span style="font-size: small;">其低16位标明缓冲区的尺寸，相应的计算公式为buffer_</span><wbr></wbr><span style="font-size: small;">size  = 2^ssss，即若参数setting低16位的值为16，</span><wbr></wbr><span style="font-size: small;">那么相应的缓冲区的大小会被设置为65536字节。</span><wbr></wbr><span style="font-size: small;">参数setting的高16位则用来标明分  片（fragment）的最大序号，</span><wbr></wbr><span style="font-size: small;">它的取值范围从2一直到0&#215;7FFF，</span><wbr></wbr><span style="font-size: small;">其中0&#215;7FFF表示没有任何限制。&nbsp;<br />
&nbsp;<br />
接下来要做的是设置声卡工作时的声道（channel）数目，</span><wbr></wbr><span style="font-size: small;">根据硬件设备和驱动程序的具体情况，可以将其设置为0（单声道，</span><wbr></wbr><span style="font-size: small;">mono）或者1（立体声，stereo）。</span><wbr></wbr></font><span style="font-size: small;"><font face="宋体">下面的代码示范了应该怎样设置声道数目：</font></span></p>
<p>&nbsp;</p>
<div>
<div class="dp-highlighter">
<div class="bar">&nbsp;</div>
<ol start="1" class="dp-cpp">
<li class="alt"><span><span class="datatypes">int</span><span>&nbsp;channels&nbsp;=&nbsp;0;&nbsp;</span><span class="comment">//&nbsp;0=mono&nbsp;1=stereo&nbsp;</span><span>&nbsp;&nbsp;</span></span></li>
<li><span><span class="datatypes">int</span><span>&nbsp;result&nbsp;=&nbsp;ioctl(handle,&nbsp;SNDCTL_DSP_STEREO,&nbsp;&amp;channels);&nbsp;&nbsp;&nbsp;</span></span></li>
<li class="alt"><span><span class="keyword">if</span><span>&nbsp;(&nbsp;result&nbsp;==&nbsp;-1&nbsp;)&nbsp;{&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>perror(<span class="string">&quot;ioctl&nbsp;channel&nbsp;number&quot;</span><span>);&nbsp;&nbsp;&nbsp;</span></span></li>
<li class="alt"><span><span class="keyword">return</span><span>&nbsp;-1;&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>}&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span><span class="keyword">if</span><span>&nbsp;(channels&nbsp;!=&nbsp;0)&nbsp;{&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span><span class="comment">//&nbsp;只支持立体声&nbsp;</span><span>&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>}&nbsp;&nbsp;</span></li>
</ol>
</div>
<div style="display: none;" class="cpp">int channels = 0; // 0=mono 1=stereo  int result = ioctl(handle, SNDCTL_DSP_STEREO, &amp;channels);  if ( result == -1 ) {  perror(&quot;ioctl channel number&quot;);  return -1;  }  if (channels != 0) {  // 只支持立体声  }</div>
</div>
<p><span style="font-size: small;"><font face="宋体"> 采样格式和采样频率是在进行音频编程时需要考虑的另一个问题，</font></span><font size="3" face="宋体"><wbr></wbr><span style="font-size: small;">声卡支持的所有采样格式可以在头文件soundcard.</span><wbr></wbr><span style="font-size: small;">h中找到，</span><wbr></wbr><span style="font-size: small;">而通过ioctl系统调用则可以很方便地更改当前所使用的采样格</span><wbr></wbr></font><span style="font-size: small;"><font face="宋体">式。下面的代码示范了如何设置声卡的采样格式：</font></span></p>
<p>&nbsp;</p>
<div>
<div class="dp-highlighter">
<div class="bar">&nbsp;</div>
<ol start="1" class="dp-cpp">
<li class="alt"><span><span class="datatypes">int</span><span>&nbsp;format&nbsp;=&nbsp;AFMT_U8;&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span><span class="datatypes">int</span><span>&nbsp;result&nbsp;=&nbsp;ioctl(handle,&nbsp;SNDCTL_DSP_SETFMT,&nbsp;&amp;format);&nbsp;&nbsp;&nbsp;</span></span></li>
<li class="alt"><span><span class="keyword">if</span><span>&nbsp;(&nbsp;result&nbsp;==&nbsp;-1&nbsp;)&nbsp;{&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>perror(<span class="string">&quot;ioctl&nbsp;sample&nbsp;format&quot;</span><span>);&nbsp;&nbsp;&nbsp;</span></span></li>
<li class="alt"><span><span class="keyword">return</span><span>&nbsp;-1;&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>}&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span><span class="comment">//&nbsp;检查设置值的正确性</span><span>&nbsp;&nbsp;</span></span></li>
</ol>
</div>
<div style="display: none;" class="cpp">int format = AFMT_U8;  int result = ioctl(handle, SNDCTL_DSP_SETFMT, &amp;format);  if ( result == -1 ) {  perror(&quot;ioctl sample format&quot;);  return -1;  }  // 检查设置值的正确性</div>
</div>
<p><span style="font-size: small;"><font face="宋体"> 声 卡采样频率的设置也非常容易，</font></span><font size="3" face="宋体"><wbr></wbr><span style="font-size: small;">只需在调用ioctl时将第二个参数的值设置为SNDCTL_</span><wbr></wbr><span style="font-size: small;">DSP_SPEED，同时在第三个参数中指定采样频率的数值就  行了。对于大多数声卡来说，</span><wbr></wbr><span style="font-size: small;">其支持的采样频率范围一般为5kHz到44.</span><wbr></wbr><span style="font-size: small;">1kHz或者48kHz，</span><wbr></wbr><span style="font-size: small;">但并不意味着该范围内的所有频率都会被硬件支持，在  Linux下进行音频编程时最常用到的几种采样频率是11025</span><wbr></wbr><span style="font-size: small;">Hz、16000Hz、22050Hz、</span><wbr></wbr></font><span style="font-size: small;"><font face="宋体">32000Hz和44100Hz。下面的代码示范  了如何设置声卡的采样频率：</font></span></p>
<p>&nbsp;</p>
<div>
<div class="dp-highlighter">
<div class="bar">&nbsp;</div>
<ol start="1" class="dp-cpp">
<li class="alt"><span><span class="datatypes">int</span><span>&nbsp;rate&nbsp;=&nbsp;22050;&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span><span class="datatypes">int</span><span>&nbsp;result&nbsp;=&nbsp;ioctl(handle,&nbsp;SNDCTL_DSP_SPEED,&nbsp;&amp;rate);&nbsp;&nbsp;&nbsp;</span></span></li>
<li class="alt"><span><span class="keyword">if</span><span>&nbsp;(&nbsp;result&nbsp;==&nbsp;-1&nbsp;)&nbsp;{&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>perror(<span class="string">&quot;ioctl&nbsp;sample&nbsp;format&quot;</span><span>);&nbsp;&nbsp;&nbsp;</span></span></li>
<li class="alt"><span><span class="keyword">return</span><span>&nbsp;-1;&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>}&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span><span class="comment">//&nbsp;检查设置值的正确性</span><span>&nbsp;&nbsp;</span></span></li>
</ol>
</div>
<div style="display: none;" class="cpp">int rate = 22050;  int result = ioctl(handle, SNDCTL_DSP_SPEED, &amp;rate);  if ( result == -1 ) {  perror(&quot;ioctl sample format&quot;);  return -1;  }  // 检查设置值的正确性</div>
</div>
<p><span style="font-size: small;"><font face="宋体"> 4.2 Mixer编程&nbsp;<br />
&nbsp;<br />
声卡上的混音器由多个混音通道组成，</font></span><font size="3" face="宋体"><wbr></wbr><span style="font-size: small;">它们可以通过驱动程序提供的设备文件/dev/</span><wbr></wbr><span style="font-size: small;">mixer进行编程。</span><wbr></wbr><span style="font-size: small;">对混音器的操作是通过ioctl系统调用来完成的，</span><wbr></wbr><span style="font-size: small;">并且所有控制命令都由SOUND_</span><wbr></wbr><span style="font-size: small;">MIXER或者MIXER开头，</span><wbr></wbr><span style="font-size: small;">表1列出了常用的几个混音器控制命令：&nbsp;<br />
&nbsp;<br />
名 称 作 用 &nbsp;<br />
SOUND_MIXER_VOLUME 主音量调节 &nbsp;<br />
SOUND_MIXER_BASS 低音控制 &nbsp;<br />
SOUND_MIXER_TREBLE 高音控制 &nbsp;<br />
SOUND_MIXER_SYNTH FM合成器 &nbsp;<br />
SOUND_MIXER_PCM 主D/A转换器 &nbsp;<br />
SOUND_MIXER_SPEAKER PC喇叭 &nbsp;<br />
SOUND_MIXER_LINE 音频线输入 &nbsp;<br />
SOUND_MIXER_MIC 麦克风输入 &nbsp;<br />
SOUND_MIXER_CD CD输入 &nbsp;<br />
SOUND_MIXER_IMIX 回放音量 &nbsp;<br />
SOUND_MIXER_ALTPCM 从D/A 转换器 &nbsp;<br />
SOUND_MIXER_RECLEV 录音音量 &nbsp;<br />
SOUND_MIXER_IGAIN 输入增益 &nbsp;<br />
SOUND_MIXER_OGAIN 输出增益 &nbsp;<br />
SOUND_MIXER_LINE1 声卡的第1输入 &nbsp;<br />
SOUND_MIXER_LINE2 声卡的第2输入 &nbsp;<br />
SOUND_MIXER_LINE3 声卡的第3输入 &nbsp;<br />
&nbsp;<br />
表1 混音器命令 &nbsp;<br />
对声卡的输入增益和输出增益进行调节是混音器的一个主要作用，</span><wbr></wbr><span style="font-size: small;">目前大部分声卡采用的是8位或者16位的增益控制器，</span><wbr></wbr><span style="font-size: small;">但作为程序员来讲并不需要关心这些，因  为声卡驱动程序会负责将它们变换成百分比的形式，</span><wbr></wbr><span style="font-size: small;">也就是说无论是输入增益还是输出增益，</span><wbr></wbr><span style="font-size: small;">其取值范围都是从0到100。在进行混音器编程时，可以使用  SOUND_MIXER_READ宏来读取混音通道的增益大小，</span><wbr></wbr></font><span style="font-size: small;"><font face="宋体">例如在获取麦克风的输入增益时，可以使用如下的代码：</font></span></p>
<p>&nbsp;</p>
<div>
<div class="dp-highlighter">
<div class="bar">&nbsp;</div>
<ol start="1" class="dp-cpp">
<li class="alt"><span><span class="datatypes">int</span><span>&nbsp;vol;&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>ioctl(fd,&nbsp;SOUND_MIXER_READ(SOUND_MIXER_MIC),&nbsp;&amp;vol);&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span>printf(<span class="string">&quot;Mic&nbsp;gain&nbsp;is&nbsp;at&nbsp;%d&nbsp;%%\n&quot;</span><span>,&nbsp;vol);&nbsp;&nbsp;</span></span></li>
</ol>
</div>
<div style="display: none;" class="cpp">int vol;  ioctl(fd, SOUND_MIXER_READ(SOUND_MIXER_MIC), &amp;vol);  printf(&quot;Mic gain is at %d %%\n&quot;, vol);</div>
</div>
<p><span style="font-size: small;"><font face="宋体"> 对 于只有一个混音通道的单声道设备来说，</font></span><font size="3" face="宋体"><wbr></wbr><span style="font-size: small;">返回的增益大小保存在低位字节中。</span><wbr></wbr><span style="font-size: small;">而对于支持多个混音通道的双声道设备来说，</span><wbr></wbr><span style="font-size: small;">返回的增益大小实际上包括两个部分，分  别代表左、右两个声道的值，其中低位字节保存左声道的音量，</span><wbr></wbr><span style="font-size: small;">而高位字节则保存右声道的音量。</span><wbr></wbr></font><span style="font-size: small;"><font face="宋体">下面的代码可以从返回值中依次提取左右声道的增益大小：</font></span></p>
<p>&nbsp;</p>
<div>
<div class="dp-highlighter">
<div class="bar">&nbsp;</div>
<ol start="1" class="dp-cpp">
<li class="alt"><span><span class="datatypes">int</span><span>&nbsp;left,&nbsp;right;&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>left&nbsp;=&nbsp;vol&nbsp;&amp;&nbsp;0xff;&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span>right&nbsp;=&nbsp;(vol&nbsp;&amp;&nbsp;0xff00)&nbsp;&gt;&gt;&nbsp;8;&nbsp;&nbsp;&nbsp;</span></li>
<li><span>printf(<span class="string">&quot;Left&nbsp;gain&nbsp;is&nbsp;%d&nbsp;%%,&nbsp;Right&nbsp;gain&nbsp;is&nbsp;%d&nbsp;%%\n&quot;</span><span>,&nbsp;left,&nbsp;right);&nbsp;&nbsp;</span></span></li>
</ol>
</div>
<div style="display: none;" class="cpp">int left, right;  left = vol &amp; 0xff;  right = (vol &amp; 0xff00) &gt;&gt; 8;  printf(&quot;Left gain is %d %%, Right gain is %d %%\n&quot;, left, right);</div>
</div>
<p><span style="font-size: small;"><font face="宋体"> 类似地，如果想设置混音通道的增益大小，则可以通过SOUND_</font></span><font size="3" face="宋体"><wbr></wbr><span style="font-size: small;">MIXER_WRITE宏来实现，</span><wbr></wbr><span style="font-size: small;">此时遵循的原则与获取增益值时的原则基本相同，</span><wbr></wbr></font><span style="font-size: small;"><font face="宋体">例如下面的语句可以用来设置麦克风的输入增益：</font></span></p>
<p>&nbsp;</p>
<div>
<div class="dp-highlighter">
<div class="bar">&nbsp;</div>
<ol start="1" class="dp-cpp">
<li class="alt"><span><span>vol&nbsp;=&nbsp;(right&nbsp;&lt;&lt;&nbsp;8)&nbsp;+&nbsp;left;&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>ioctl(fd,&nbsp;SOUND_MIXER_WRITE(SOUND_MIXER_MIC),&nbsp;&amp;vol);&nbsp;&nbsp;</span></li>
</ol>
</div>
<div style="display: none;" class="cpp">vol = (right &lt;&lt; <img src='http://www.oursit.com/wp-includes/images/smilies/icon_cool.gif' alt='8)' class='wp-smiley' /> + left;  ioctl(fd, SOUND_MIXER_WRITE(SOUND_MIXER_MIC), &amp;vol);</div>
</div>
<p><span style="font-size: small;"><font face="宋体"> 在 编写实用的音频程序时，</font></span><font size="3" face="宋体"><wbr></wbr><span style="font-size: small;">混音器是在涉及到兼容性时需要重点考虑的一个对象，</span><wbr></wbr><span style="font-size: small;">这是因为不同的声卡所提供的混音器资源是有所区别的。</span><wbr></wbr><span style="font-size: small;">声卡驱动程序提供了多个  ioctl系统调用来获得混音器的信息，</span><wbr></wbr><span style="font-size: small;">它们通常返回一个整型的位掩码（bitmask），</span><wbr></wbr><span style="font-size: small;">其中每一位分别代表一个特定的混音通道，如果相应的位为1，则  说明与之对应的混音通道是可用的。例如通过SOUND_</span><wbr></wbr><span style="font-size: small;">MIXER_READ_DEVMASK返回的位掩码，</span><wbr></wbr><span style="font-size: small;">可以查询出能够被声卡支持的每一个混音通道，  而通过SOUND_MIXER_READ_</span><wbr></wbr><span style="font-size: small;">RECMAS返回的位掩码，</span><wbr></wbr><span style="font-size: small;">则可以查询出能够被当作录音源的每一个通道。</span><wbr></wbr></font><span style="font-size: small;"><font face="宋体">下面的代码可以用来检查CD输入是否是  一个有效的混音通道：</font></span></p>
<p>&nbsp;</p>
<div>
<div class="dp-highlighter">
<div class="bar">&nbsp;</div>
<ol start="1" class="dp-cpp">
<li class="alt"><span><span>ioctl(fd,&nbsp;SOUND_MIXER_READ_DEVMASK,&nbsp;&amp;devmask);&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span><span class="keyword">if</span><span>&nbsp;(devmask&nbsp;&amp;&nbsp;SOUND_MIXER_CD)&nbsp;&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>&nbsp;&nbsp;printf(<span class="string">&quot;The&nbsp;CD&nbsp;input&nbsp;is&nbsp;supported&quot;</span><span>);&nbsp;&nbsp;</span></span></li>
</ol>
</div>
<div style="display: none;" class="cpp">ioctl(fd, SOUND_MIXER_READ_DEVMASK, &amp;devmask);  if (devmask &amp; SOUND_MIXER_CD)    printf(&quot;The CD input is supported&quot;);</div>
</div>
<p><span style="font-size: small;"><font face="宋体"> 如果进一步还想知道其是否是一个有效的录音源，</font></span><font size="3" face="宋体"><wbr></wbr></font><span style="font-size: small;"><font face="宋体">则可以使用如下语句：</font></span></p>
<p>&nbsp;</p>
<div>
<div class="dp-highlighter">
<div class="bar">&nbsp;</div>
<ol start="1" class="dp-cpp">
<li class="alt"><span><span>ioctl(fd,&nbsp;SOUND_MIXER_READ_RECMASK,&nbsp;&amp;recmask);&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span><span class="keyword">if</span><span>&nbsp;(recmask&nbsp;&amp;&nbsp;SOUND_MIXER_CD)&nbsp;&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>&nbsp;&nbsp;printf(<span class="string">&quot;The&nbsp;CD&nbsp;input&nbsp;can&nbsp;be&nbsp;a&nbsp;recording&nbsp;source&quot;</span><span>);&nbsp;&nbsp;</span></span></li>
</ol>
</div>
<div style="display: none;" class="cpp">ioctl(fd, SOUND_MIXER_READ_RECMASK, &amp;recmask);  if (recmask &amp; SOUND_MIXER_CD)    printf(&quot;The CD input can be a recording source&quot;);</div>
</div>
<p><span style="font-size: small;"><font face="宋体"> 目 前大多数声卡提供多个录音源，通过SOUND_MIXER_</font></span><font size="3" face="宋体"><wbr></wbr><span style="font-size: small;">READ_RECSRC可以查询出当前正在使用的录音源，</span><wbr></wbr><span style="font-size: small;">同一时刻能够使用几个录音源是由声卡  硬件决定的。类似地，使用SOUND_MIXER_WRITE_</span><wbr></wbr><span style="font-size: small;">RECSRC可以设置声卡当前使用的录音源，</span><wbr></wbr></font><span style="font-size: small;"><font face="宋体">例如下面的代码可以将CD输入作为声卡的录音  源使用：</font></span></p>
<p>&nbsp;</p>
<div>
<div class="dp-highlighter">
<div class="bar">&nbsp;</div>
<ol start="1" class="dp-cpp">
<li class="alt"><span><span>devmask&nbsp;=&nbsp;SOUND_MIXER_CD;&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>ioctl(fd,&nbsp;SOUND_MIXER_WRITE_DEVMASK,&nbsp;&amp;devmask);&nbsp;&nbsp;</span></li>
</ol>
</div>
<div style="display: none;" class="cpp">devmask = SOUND_MIXER_CD;  ioctl(fd, SOUND_MIXER_WRITE_DEVMASK, &amp;devmask);</div>
</div>
<p><span style="font-size: small;"><font face="宋体"> 此外，所有的混音通道都有单声道和双声道的区别，</font></span><font size="3" face="宋体"><wbr></wbr><span style="font-size: small;">如果需要知道哪些混音通道提供了对立体声的支持，</span><wbr></wbr><span style="font-size: small;">可以通过SOUND_MIXER_READ_</span><wbr></wbr><span style="font-size: small;">STEREODEVS来获得。&nbsp;<br />
&nbsp;<br />
4.3 音频录放框架&nbsp;<br />
&nbsp;<br />
下面给出一个利用声卡上的DSP设备进行声音录制和回放的基本框</span><wbr></wbr><span style="font-size: small;">架，它的功能是先录制几秒种音频数据，将其存放在内存缓冲区中，</span><wbr></wbr><span style="font-size: small;">然后再进行回放，其所有的功能都是通过读写/dev/</span><wbr></wbr></font><span style="font-size: small;"><font face="宋体">dsp设备文件来完成的：</font></span></p>
<p>&nbsp;</p>
<div>
<div class="dp-highlighter">
<div class="bar">&nbsp;</div>
<ol start="1" class="dp-cpp">
<li class="alt"><span><span class="comment">/*&nbsp;</span>&nbsp;</span></li>
<li><span><span class="comment">*&nbsp;sound.c&nbsp;</span>&nbsp;</span></li>
<li class="alt"><span><span class="comment">*/</span><span>&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span><span class="preprocessor">#include&nbsp;&lt;unistd.h&gt;&nbsp;</span><span>&nbsp;&nbsp;</span></span></li>
<li class="alt"><span><span class="preprocessor">#include&nbsp;&lt;fcntl.h&gt;&nbsp;</span><span>&nbsp;&nbsp;</span></span></li>
<li><span><span class="preprocessor">#include&nbsp;&lt;sys/types.h&gt;&nbsp;</span><span>&nbsp;&nbsp;</span></span></li>
<li class="alt"><span><span class="preprocessor">#include&nbsp;&lt;sys/ioctl.h&gt;&nbsp;</span><span>&nbsp;&nbsp;</span></span></li>
<li><span><span class="preprocessor">#include&nbsp;&lt;stdlib.h&gt;&nbsp;</span><span>&nbsp;&nbsp;</span></span></li>
<li class="alt"><span><span class="preprocessor">#include&nbsp;&lt;stdio.h&gt;&nbsp;</span><span>&nbsp;&nbsp;</span></span></li>
<li><span><span class="preprocessor">#include&nbsp;&lt;linux/soundcard.h&gt;&nbsp;</span><span>&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;</span></li>
<li><span><span class="preprocessor">#define&nbsp;LENGTH&nbsp;3&nbsp;&nbsp;&nbsp;&nbsp;/*&nbsp;存储秒数&nbsp;*/&nbsp;</span><span>&nbsp;&nbsp;</span></span></li>
<li class="alt"><span><span class="preprocessor">#define&nbsp;RATE&nbsp;8000&nbsp;&nbsp;&nbsp;/*&nbsp;采样频率&nbsp;*/&nbsp;</span><span>&nbsp;&nbsp;</span></span></li>
<li><span><span class="preprocessor">#define&nbsp;SIZE&nbsp;8&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/*&nbsp;量化位数&nbsp;*/&nbsp;</span><span>&nbsp;&nbsp;</span></span></li>
<li class="alt"><span><span class="preprocessor">#define&nbsp;CHANNELS&nbsp;1&nbsp;&nbsp;/*&nbsp;声道数目&nbsp;*/&nbsp;</span><span>&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span><span class="comment">/*&nbsp;用于保存数字音频数据的内存缓冲区&nbsp;*/</span><span>&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>unsigned&nbsp;<span class="datatypes">char</span><span>&nbsp;buf[LENGTH*RATE*SIZE*CHANNELS/8];&nbsp;&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;</span></li>
<li><span><span class="datatypes">int</span><span>&nbsp;main()&nbsp;&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>{&nbsp;&nbsp;&nbsp;</span></li>
<li><span>&nbsp;&nbsp;<span class="datatypes">int</span><span>&nbsp;fd;&nbsp;</span><span class="comment">/*&nbsp;声音设备的文件描述符&nbsp;*/</span><span>&nbsp;&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>&nbsp;&nbsp;<span class="datatypes">int</span><span>&nbsp;arg;&nbsp;</span><span class="comment">/*&nbsp;用于ioctl调用的参数&nbsp;*/</span><span>&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;<span class="datatypes">int</span><span>&nbsp;status;&nbsp;&nbsp;&nbsp;</span><span class="comment">/*&nbsp;系统调用的返回值&nbsp;*/</span><span>&nbsp;&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;</span></li>
<li><span>&nbsp;&nbsp;<span class="comment">/*&nbsp;打开声音设备&nbsp;*/</span><span>&nbsp;&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>&nbsp;&nbsp;fd&nbsp;=&nbsp;open(<span class="string">&quot;/dev/dsp&quot;</span><span>,&nbsp;O_RDWR);&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;<span class="keyword">if</span><span>&nbsp;(fd&nbsp;&lt;&nbsp;0)&nbsp;{&nbsp;&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;perror(<span class="string">&quot;open&nbsp;of&nbsp;/dev/dsp&nbsp;failed&quot;</span><span>);&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;&nbsp;exit(1);&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;}&nbsp;&nbsp;&nbsp;</span></li>
<li><span>&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;<span class="comment">/*&nbsp;设置采样时的量化位数&nbsp;*/</span><span>&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;arg&nbsp;=&nbsp;SIZE;&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;status&nbsp;=&nbsp;ioctl(fd,&nbsp;SOUND_PCM_WRITE_BITS,&nbsp;&amp;arg);&nbsp;&nbsp;&nbsp;</span></li>
<li><span>&nbsp;&nbsp;<span class="keyword">if</span><span>&nbsp;(status&nbsp;==&nbsp;-1)&nbsp;&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;perror(<span class="string">&quot;SOUND_PCM_WRITE_BITS&nbsp;ioctl&nbsp;failed&quot;</span><span>);&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;<span class="keyword">if</span><span>&nbsp;(arg&nbsp;!=&nbsp;SIZE)&nbsp;&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;perror(<span class="string">&quot;unable&nbsp;to&nbsp;set&nbsp;sample&nbsp;size&quot;</span><span>);&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;<span class="comment">/*&nbsp;设置采样时的声道数目&nbsp;*/</span><span>&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;arg&nbsp;=&nbsp;CHANNELS;&nbsp;&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;status&nbsp;=&nbsp;ioctl(fd,&nbsp;SOUND_PCM_WRITE_CHANNELS,&nbsp;&amp;arg);&nbsp;&nbsp;&nbsp;</span></li>
<li><span>&nbsp;&nbsp;<span class="keyword">if</span><span>&nbsp;(status&nbsp;==&nbsp;-1)&nbsp;&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;perror(<span class="string">&quot;SOUND_PCM_WRITE_CHANNELS&nbsp;ioctl&nbsp;failed&quot;</span><span>);&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;<span class="keyword">if</span><span>&nbsp;(arg&nbsp;!=&nbsp;CHANNELS)&nbsp;&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;perror(<span class="string">&quot;unable&nbsp;to&nbsp;set&nbsp;number&nbsp;of&nbsp;channels&quot;</span><span>);&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;<span class="comment">/*&nbsp;设置采样时的采样频率&nbsp;*/</span><span>&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;arg&nbsp;=&nbsp;RATE;&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;status&nbsp;=&nbsp;ioctl(fd,&nbsp;SOUND_PCM_WRITE_RATE,&nbsp;&amp;arg);&nbsp;&nbsp;&nbsp;</span></li>
<li><span>&nbsp;&nbsp;<span class="keyword">if</span><span>&nbsp;(status&nbsp;==&nbsp;-1)&nbsp;&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;perror(<span class="string">&quot;SOUND_PCM_WRITE_WRITE&nbsp;ioctl&nbsp;failed&quot;</span><span>);&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;<span class="comment">/*&nbsp;循环，直到按下Control-C&nbsp;*/</span><span>&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;<span class="keyword">while</span><span>&nbsp;(1)&nbsp;{&nbsp;&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;printf(<span class="string">&quot;Say&nbsp;something:\n&quot;</span><span>);&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;&nbsp;status&nbsp;=&nbsp;read(fd,&nbsp;buf,&nbsp;<span class="keyword">sizeof</span><span>(buf));&nbsp;</span><span class="comment">/*&nbsp;录音&nbsp;*/</span><span>&nbsp;&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">if</span><span>&nbsp;(status&nbsp;!=&nbsp;</span><span class="keyword">sizeof</span><span>(buf))&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;perror(<span class="string">&quot;read&nbsp;wrong&nbsp;number&nbsp;of&nbsp;bytes&quot;</span><span>);&nbsp;&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;</span></li>
<li><span>&nbsp;&nbsp;&nbsp;&nbsp;printf(<span class="string">&quot;You&nbsp;said:\n&quot;</span><span>);&nbsp;&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;status&nbsp;=&nbsp;write(fd,&nbsp;buf,&nbsp;<span class="keyword">sizeof</span><span>(buf));&nbsp;</span><span class="comment">/*&nbsp;回放&nbsp;*/</span><span>&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">if</span><span>&nbsp;(status&nbsp;!=&nbsp;</span><span class="keyword">sizeof</span><span>(buf))&nbsp;&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;perror(<span class="string">&quot;wrote&nbsp;wrong&nbsp;number&nbsp;of&nbsp;bytes&quot;</span><span>);&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">/*&nbsp;在继续录音前等待回放结束&nbsp;*/</span><span>&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;&nbsp;status&nbsp;=&nbsp;ioctl(fd,&nbsp;SOUND_PCM_SYNC,&nbsp;0);&nbsp;&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">if</span><span>&nbsp;(status&nbsp;==&nbsp;-1)&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;perror(<span class="string">&quot;SOUND_PCM_SYNC&nbsp;ioctl&nbsp;failed&quot;</span><span>);&nbsp;&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>&nbsp;&nbsp;}&nbsp;&nbsp;&nbsp;</span></li>
<li><span>}&nbsp;&nbsp;</span></li>
</ol>
</div>
<div style="display: none;" class="cpp">/*  * sound.c  */  #include &lt;unistd.h&gt;  #include <fcntl.h>  #include <sys types.h="">  #include <sys ioctl.h="">  #include <stdlib.h>  #include <stdio.h>  #include</p>
<linux soundcard.h="">    #define LENGTH 3    /* 存储秒数 */  #define RATE 8000   /* 采样频率 */  #define SIZE 8      /* 量化位数 */  #define CHANNELS 1  /* 声道数目 */    /* 用于保存数字音频数据的内存缓冲区 */  unsigned char buf[LENGTH*RATE*SIZE*CHANNELS/8];    int main()  {    int fd; /* 声音设备的文件描述符 */    int arg; /* 用于ioctl调用的参数 */    int status;   /* 系统调用的返回值 */      /* 打开声音设备 */    fd = open(&quot;/dev/dsp&quot;, O_RDWR);    if (fd &lt; 0) {      perror(&quot;open of /dev/dsp failed&quot;);      exit(1);    }      /* 设置采样时的量化位数 */    arg = SIZE;    status = ioctl(fd, SOUND_PCM_WRITE_BITS, &amp;arg);    if (status == -1)      perror(&quot;SOUND_PCM_WRITE_BITS ioctl failed&quot;);    if (arg != SIZE)      perror(&quot;unable to set sample size&quot;);      /* 设置采样时的声道数目 */    arg = CHANNELS;     status = ioctl(fd, SOUND_PCM_WRITE_CHANNELS, &amp;arg);    if (status == -1)      perror(&quot;SOUND_PCM_WRITE_CHANNELS ioctl failed&quot;);    if (arg != CHANNELS)      perror(&quot;unable to set number of channels&quot;);      /* 设置采样时的采样频率 */    arg = RATE;    status = ioctl(fd, SOUND_PCM_WRITE_RATE, &amp;arg);    if (status == -1)      perror(&quot;SOUND_PCM_WRITE_WRITE ioctl failed&quot;);      /* 循环，直到按下Control-C */    while (1) {      printf(&quot;Say something:\n&quot;);      status = read(fd, buf, sizeof(buf)); /* 录音 */      if (status != sizeof(buf))        perror(&quot;read wrong number of bytes&quot;);        printf(&quot;You said:\n&quot;);      status = write(fd, buf, sizeof(buf)); /* 回放 */      if (status != sizeof(buf))        perror(&quot;wrote wrong number of bytes&quot;);        /* 在继续录音前等待回放结束 */      status = ioctl(fd, SOUND_PCM_SYNC, 0);       if (status == -1)        perror(&quot;SOUND_PCM_SYNC ioctl failed&quot;);    }  }</linux>
</stdio.h></stdlib.h></sys></sys></fcntl.h></div>
</div>
<p><span style="font-size: small;"><font face="宋体"> 4.4 混音器框架&nbsp;<br />
&nbsp;<br />
下面再给出一个对混音器进行编程的基本框架，</font></span><font size="3" face="宋体"><wbr></wbr><span style="font-size: small;">利用它可以对各种混音通道的增益进行调节，</span><wbr></wbr><span style="font-size: small;">其所有的功能都是通过读写/dev/</span><wbr></wbr></font><span style="font-size: small;"><font face="宋体">mixer设备文件来完成的：</font></span></p>
<p>&nbsp;</p>
<div>
<div class="dp-highlighter">
<div class="bar">&nbsp;</div>
<ol start="1" class="dp-cpp">
<li class="alt"><span><span class="comment">/*&nbsp;</span>&nbsp;</span></li>
<li><span><span class="comment">*&nbsp;mixer.c&nbsp;</span>&nbsp;</span></li>
<li class="alt"><span><span class="comment">*/</span><span>&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span><span class="preprocessor">#include&nbsp;&lt;unistd.h&gt;&nbsp;</span><span>&nbsp;&nbsp;</span></span></li>
<li class="alt"><span><span class="preprocessor">#include&nbsp;&lt;stdlib.h&gt;&nbsp;</span><span>&nbsp;&nbsp;</span></span></li>
<li><span><span class="preprocessor">#include&nbsp;&lt;stdio.h&gt;&nbsp;</span><span>&nbsp;&nbsp;</span></span></li>
<li class="alt"><span><span class="preprocessor">#include&nbsp;&lt;sys/ioctl.h&gt;&nbsp;</span><span>&nbsp;&nbsp;</span></span></li>
<li><span><span class="preprocessor">#include&nbsp;&lt;fcntl.h&gt;&nbsp;</span><span>&nbsp;&nbsp;</span></span></li>
<li class="alt"><span><span class="preprocessor">#include&nbsp;&lt;linux/soundcard.h&gt;&nbsp;</span><span>&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span><span class="comment">/*&nbsp;用来存储所有可用混音设备的名称&nbsp;*/</span><span>&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span><span class="keyword">const</span><span>&nbsp;</span><span class="datatypes">char</span><span>&nbsp;*sound_device_names[]&nbsp;=&nbsp;SOUND_DEVICE_NAMES;&nbsp;&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;</span></li>
<li><span><span class="datatypes">int</span><span>&nbsp;fd;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">/*&nbsp;混音设备所对应的文件描述符&nbsp;*/</span><span>&nbsp;&nbsp;&nbsp;</span></span></li>
<li class="alt"><span><span class="datatypes">int</span><span>&nbsp;devmask,&nbsp;stereodevs;&nbsp;</span><span class="comment">/*&nbsp;混音器信息对应的位图掩码&nbsp;*/</span><span>&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span><span class="datatypes">char</span><span>&nbsp;*name;&nbsp;&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;</span></li>
<li><span><span class="comment">/*&nbsp;显示命令的使用方法及所有可用的混音设备&nbsp;*/</span><span>&nbsp;&nbsp;&nbsp;</span></span></li>
<li class="alt"><span><span class="keyword">void</span><span>&nbsp;usage()&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>{&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;<span class="datatypes">int</span><span>&nbsp;i;&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;fprintf(stderr,&nbsp;<span class="string">&quot;usage:&nbsp;%s&nbsp;&lt;device&gt;&nbsp;&lt;left-gain%%&gt;&nbsp;&lt;right-gain%%&gt;\n&quot;</span><span>&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;<span class="string">&quot;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;%s&nbsp;&lt;device&gt;&nbsp;&lt;gain%%&gt;\n\n&quot;</span><span>&nbsp;&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;<span class="string">&quot;Where&nbsp;&lt;device&gt;&nbsp;is&nbsp;one&nbsp;of:\n&quot;</span><span>,&nbsp;name,&nbsp;name);&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;<span class="keyword">for</span><span>&nbsp;(i&nbsp;=&nbsp;0&nbsp;;&nbsp;i&nbsp;&lt;&nbsp;SOUND_MIXER_NRDEVICES&nbsp;;&nbsp;i++)&nbsp;&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">if</span><span>&nbsp;((1&nbsp;&lt;&lt;&nbsp;i)&nbsp;&amp;&nbsp;devmask)&nbsp;</span><span class="comment">/*&nbsp;只显示有效的混音设备&nbsp;*/</span><span>&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fprintf(stderr,&nbsp;<span class="string">&quot;%s&nbsp;&quot;</span><span>,&nbsp;sound_device_names[i]);&nbsp;&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>&nbsp;&nbsp;fprintf(stderr,&nbsp;<span class="string">&quot;\n&quot;</span><span>);&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;exit(1);&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span>}&nbsp;&nbsp;&nbsp;</span></li>
<li><span>&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span><span class="datatypes">int</span><span>&nbsp;main(</span><span class="datatypes">int</span><span>&nbsp;argc,&nbsp;</span><span class="datatypes">char</span><span>&nbsp;*argv[])&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>{&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;<span class="datatypes">int</span><span>&nbsp;left,&nbsp;right,&nbsp;level;&nbsp;&nbsp;</span><span class="comment">/*&nbsp;增益设置&nbsp;*/</span><span>&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;<span class="datatypes">int</span><span>&nbsp;status;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">/*&nbsp;系统调用的返回值&nbsp;*/</span><span>&nbsp;&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>&nbsp;&nbsp;<span class="datatypes">int</span><span>&nbsp;device;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">/*&nbsp;选用的混音设备&nbsp;*/</span><span>&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;<span class="datatypes">char</span><span>&nbsp;*dev;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">/*&nbsp;混音设备的名称&nbsp;*/</span><span>&nbsp;&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>&nbsp;&nbsp;<span class="datatypes">int</span><span>&nbsp;i;&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;name&nbsp;=&nbsp;argv[0];&nbsp;&nbsp;&nbsp;</span></li>
<li><span>&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;<span class="comment">/*&nbsp;以只读方式打开混音设备&nbsp;*/</span><span>&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;fd&nbsp;=&nbsp;open(<span class="string">&quot;/dev/mixer&quot;</span><span>,&nbsp;O_RDONLY);&nbsp;&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>&nbsp;&nbsp;<span class="keyword">if</span><span>&nbsp;(fd&nbsp;==&nbsp;-1)&nbsp;{&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;&nbsp;perror(<span class="string">&quot;unable&nbsp;to&nbsp;open&nbsp;/dev/mixer&quot;</span><span>);&nbsp;&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;exit(1);&nbsp;&nbsp;&nbsp;</span></li>
<li><span>&nbsp;&nbsp;}&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></li>
<li><span>&nbsp;&nbsp;<span class="comment">/*&nbsp;获得所需要的信息&nbsp;*/</span><span>&nbsp;&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>&nbsp;&nbsp;status&nbsp;=&nbsp;ioctl(fd,&nbsp;SOUND_MIXER_READ_DEVMASK,&nbsp;&amp;devmask);&nbsp;&nbsp;&nbsp;</span></li>
<li><span>&nbsp;&nbsp;<span class="keyword">if</span><span>&nbsp;(status&nbsp;==&nbsp;-1)&nbsp;&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;perror(<span class="string">&quot;SOUND_MIXER_READ_DEVMASK&nbsp;ioctl&nbsp;failed&quot;</span><span>);&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;status&nbsp;=&nbsp;ioctl(fd,&nbsp;SOUND_MIXER_READ_STEREODEVS,&nbsp;&amp;stereodevs);&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;<span class="keyword">if</span><span>&nbsp;(status&nbsp;==&nbsp;-1)&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;&nbsp;perror(<span class="string">&quot;SOUND_MIXER_READ_STEREODEVS&nbsp;ioctl&nbsp;failed&quot;</span><span>);&nbsp;&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;</span></li>
<li><span>&nbsp;&nbsp;<span class="comment">/*&nbsp;检查用户输入&nbsp;*/</span><span>&nbsp;&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>&nbsp;&nbsp;<span class="keyword">if</span><span>&nbsp;(argc&nbsp;!=&nbsp;3&nbsp;&amp;&amp;&nbsp;argc&nbsp;!=&nbsp;4)&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;&nbsp;usage();&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;</span></li>
<li><span>&nbsp;&nbsp;<span class="comment">/*&nbsp;保存用户输入的混音器名称&nbsp;*/</span><span>&nbsp;&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>&nbsp;&nbsp;dev&nbsp;=&nbsp;argv[1];&nbsp;&nbsp;&nbsp;</span></li>
<li><span>&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;<span class="comment">/*&nbsp;确定即将用到的混音设备&nbsp;*/</span><span>&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;<span class="keyword">for</span><span>&nbsp;(i&nbsp;=&nbsp;0&nbsp;;&nbsp;i&nbsp;&lt;&nbsp;SOUND_MIXER_NRDEVICES&nbsp;;&nbsp;i++)&nbsp;&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">if</span><span>&nbsp;(((1&nbsp;&lt;&lt;&nbsp;i)&nbsp;&amp;&nbsp;devmask)&nbsp;&amp;&amp;&nbsp;!strcmp(dev,&nbsp;sound_device_names[i]))&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">break</span><span>;&nbsp;&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>&nbsp;&nbsp;<span class="keyword">if</span><span>&nbsp;(i&nbsp;==&nbsp;SOUND_MIXER_NRDEVICES)&nbsp;{&nbsp;</span><span class="comment">/*&nbsp;没有找到匹配项&nbsp;*/</span><span>&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;&nbsp;fprintf(stderr,&nbsp;<span class="string">&quot;%s&nbsp;is&nbsp;not&nbsp;a&nbsp;valid&nbsp;mixer&nbsp;device\n&quot;</span><span>,&nbsp;dev);&nbsp;&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;usage();&nbsp;&nbsp;&nbsp;</span></li>
<li><span>&nbsp;&nbsp;}&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;</span></li>
<li><span>&nbsp;&nbsp;<span class="comment">/*&nbsp;查找到有效的混音设备&nbsp;*/</span><span>&nbsp;&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>&nbsp;&nbsp;device&nbsp;=&nbsp;i;&nbsp;&nbsp;&nbsp;</span></li>
<li><span>&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;<span class="comment">/*&nbsp;获取增益值&nbsp;*/</span><span>&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;<span class="keyword">if</span><span>&nbsp;(argc&nbsp;==&nbsp;4)&nbsp;{&nbsp;&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">/*&nbsp;左、右声道均给定&nbsp;*/</span><span>&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;&nbsp;left&nbsp;&nbsp;=&nbsp;atoi(argv[2]);&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;right&nbsp;=&nbsp;atoi(argv[3]);&nbsp;&nbsp;&nbsp;</span></li>
<li><span>&nbsp;&nbsp;}&nbsp;<span class="keyword">else</span><span>&nbsp;{&nbsp;&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">/*&nbsp;左、右声道设为相等&nbsp;*/</span><span>&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;&nbsp;left&nbsp;&nbsp;=&nbsp;atoi(argv[2]);&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;right&nbsp;=&nbsp;atoi(argv[2]);&nbsp;&nbsp;&nbsp;</span></li>
<li><span>&nbsp;&nbsp;}&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></li>
<li><span>&nbsp;&nbsp;<span class="comment">/*&nbsp;对非立体声设备给出警告信息&nbsp;*/</span><span>&nbsp;&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>&nbsp;&nbsp;<span class="keyword">if</span><span>&nbsp;((left&nbsp;!=&nbsp;right)&nbsp;&amp;&amp;&nbsp;!((1&nbsp;&lt;&lt;&nbsp;i)&nbsp;&amp;&nbsp;stereodevs))&nbsp;{&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;&nbsp;fprintf(stderr,&nbsp;<span class="string">&quot;warning:&nbsp;%s&nbsp;is&nbsp;not&nbsp;a&nbsp;stereo&nbsp;device\n&quot;</span><span>,&nbsp;dev);&nbsp;&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>&nbsp;&nbsp;}&nbsp;&nbsp;&nbsp;</span></li>
<li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;<span class="comment">/*&nbsp;将两个声道的值合到同一变量中&nbsp;*/</span><span>&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;level&nbsp;=&nbsp;(right&nbsp;&lt;&lt;&nbsp;8)&nbsp;+&nbsp;left;&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></li>
<li><span>&nbsp;&nbsp;<span class="comment">/*&nbsp;设置增益&nbsp;*/</span><span>&nbsp;&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>&nbsp;&nbsp;status&nbsp;=&nbsp;ioctl(fd,&nbsp;MIXER_WRITE(device),&nbsp;&amp;level);&nbsp;&nbsp;&nbsp;</span></li>
<li><span>&nbsp;&nbsp;<span class="keyword">if</span><span>&nbsp;(status&nbsp;==&nbsp;-1)&nbsp;{&nbsp;&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;perror(<span class="string">&quot;MIXER_WRITE&nbsp;ioctl&nbsp;failed&quot;</span><span>);&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;&nbsp;exit(1);&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;}&nbsp;&nbsp;&nbsp;</span></li>
<li><span>&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;<span class="comment">/*&nbsp;获得从驱动返回的左右声道的增益&nbsp;*/</span><span>&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;left&nbsp;&nbsp;=&nbsp;level&nbsp;&amp;&nbsp;0xff;&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;right&nbsp;=&nbsp;(level&nbsp;&amp;&nbsp;0xff00)&nbsp;&gt;&gt;&nbsp;8;&nbsp;&nbsp;&nbsp;</span></li>
<li><span>&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;<span class="comment">/*&nbsp;显示实际设置的增益&nbsp;*/</span><span>&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;fprintf(stderr,&nbsp;<span class="string">&quot;%s&nbsp;gain&nbsp;set&nbsp;to&nbsp;%d%%&nbsp;/&nbsp;%d%%\n&quot;</span><span>,&nbsp;dev,&nbsp;left,&nbsp;right);&nbsp;&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;</span></li>
<li><span>&nbsp;&nbsp;<span class="comment">/*&nbsp;关闭混音设备&nbsp;*/</span><span>&nbsp;&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>&nbsp;&nbsp;close(fd);&nbsp;&nbsp;&nbsp;</span></li>
<li><span>&nbsp;&nbsp;<span class="keyword">return</span><span>&nbsp;0;&nbsp;&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>}&nbsp;&nbsp;</span></li>
</ol>
</div>
<div style="display: none;" class="cpp">/*  * mixer.c  */  #include &lt;unistd.h&gt;  #include <stdlib.h>  #include <stdio.h>  #include <sys ioctl.h="">  #include <fcntl.h>  #include</p>
<linux soundcard.h="">    /* 用来存储所有可用混音设备的名称 */  const char *sound_device_names[] = SOUND_DEVICE_NAMES;    int fd;                  /* 混音设备所对应的文件描述符 */  int devmask, stereodevs; /* 混音器信息对应的位图掩码 */  char *name;    /* 显示命令的使用方法及所有可用的混音设备 */  void usage()  {    int i;      fprintf(stderr, &quot;usage: %s <device> </device></linux>
</fcntl.h></sys></stdio.h></stdlib.h></div>
</div>
<p><span style="font-size: small;"><font face="宋体"> 编译好上面的程序之后，先不带任何参数执行一遍，</font></span><font size="3" face="宋体"><wbr></wbr><span style="font-size: small;">此时会列出声卡上所有可用的混音通道：&nbsp;<br />
&nbsp;<br />
[xiaowp@linuxgam sound]$ ./mixer&nbsp;<br />
usage: ./mixer &lt;device&gt; &lt;left-gain%&gt; &lt;right-gain%&gt;&nbsp;<br />
&nbsp; &nbsp;&nbsp; &nbsp; ./mixer &lt;device&gt; &lt;gain%&gt;&nbsp;<br />
&nbsp;<br />
Where &lt;device&gt; is one of:&nbsp;<br />
vol pcm speaker line mic cd igain line1 phin video&nbsp;<br />
&nbsp;<br />
&nbsp;<br />
&nbsp;<br />
之后就可以很方便地设置各个混音通道的增益大小了，</span><wbr></wbr><span style="font-size: small;">例如下面的命令就能够将CD输入的左、</span><wbr></wbr><span style="font-size: small;">右声道的增益分别设置为80%和90%：&nbsp;<br />
&nbsp;<br />
&nbsp;<br />
[xiaowp@linuxgam sound]$ ./mixer cd 80 90&nbsp;<br />
cd gain set to 80% / 90%&nbsp;<br />
&nbsp;<br />
五、小结&nbsp;<br />
&nbsp;<br />
随着Linux平台下多媒体应用的逐渐深入，</span><wbr></wbr><span style="font-size: small;">需要用到数字音频的场合必将越来越广泛。</span><wbr></wbr><span style="font-size: small;">虽然数字音频牵涉到的概念非常多，</span><wbr></wbr><span style="font-size: small;">但在Linux下进行最基本的音频  编程却并不十分复杂，</span><wbr></wbr><span style="font-size: small;">关键是掌握如何与OSS或者ALSA这类声卡驱动程序进行交互，</span><wbr></wbr><span style="font-size: small;">以及如何充分利用它们提供的各种功能，</span><wbr></wbr></font><span style="font-size: small;"><font face="宋体">熟悉一些最基本的音频编程框架  和模式对初学者来讲大有裨益。&nbsp;<br />
&nbsp;<br />
六、参考资料&nbsp;<br />
&nbsp;<br />
1. OSS是Linux上最早出现的声卡驱动程序，</font></span><a target="_blank" href="http://www.opensound.com/"><span style="font-size: small;"><font face="宋体" color="#0000ff"><u>http://</u></font></span><font size="3" face="宋体" color="#0000ff"><u><wbr></wbr></u></font></a><span style="font-size: small;"><a target="_blank" href="http://www.opensound.com/"><font face="宋体" color="#0000ff"><u>www.opensound.com</u></font></a><font face="宋体">是它的核心网站，</font></span><font size="3" face="宋体"><wbr></wbr><span style="font-size: small;">从中可以了解到许多与OSS相关的信息。&nbsp;<br />
&nbsp;<br />
2. ALSA是目前广泛使用的Linux声卡驱动程序，</span><wbr></wbr></font><span style="font-size: small;"><font face="宋体">并且提供了一些库函数来简化音频程序的编写，在其官方网站</font></span><a target="_blank" href="http://www.alsa-project.org/"><span style="font-size: small;"><font face="宋体" color="#0000ff"><u>htt</u></font></span><font size="3" face="宋体" color="#0000ff"><u><wbr></wbr></u></font></a><span style="font-size: small;"><a target="_blank" href="http://www.alsa-project.org/"><font face="宋体" color="#0000ff"><u>p://www.alsa-project.org/</u></font></a><font face="宋体">上可以了解</font></span><font size="3" face="宋体"><wbr></wbr><span style="font-size: small;">到ALSA的许多信息，并能够下载到最新的驱动程序和工具软件。</span><wbr></wbr><span style="font-size: small;">&nbsp;<br />
&nbsp;<br />
3. Ken C. Pohlmann著，苏菲译，数字音频原理与应用（第四合版），</span><wbr></wbr><span style="font-size: small;">北京：电子工业出版社，2002&nbsp;<br />
&nbsp;<br />
4. 钟玉琢等编著，多媒体技术及其应用，北京：机械工业出版社，</span><wbr></wbr></font><span style="font-size: small;"><font face="宋体">2003&nbsp;<br />
&nbsp;<br />
&nbsp;<br />
</font><font face="宋体" color="#ff0000">一个测试通过的音频播放程序</font></span></p>
<p>&nbsp;</p>
<div>
<div class="dp-highlighter">
<div class="bar">&nbsp;</div>
<ol start="1" class="dp-cpp">
<li class="alt"><span><span class="preprocessor">#include&nbsp;&lt;unistd.h&gt;&nbsp;</span><span>&nbsp;&nbsp;</span></span></li>
<li><span><span class="preprocessor">#include&nbsp;&lt;fcntl.h&gt;&nbsp;</span><span>&nbsp;&nbsp;</span></span></li>
<li class="alt"><span><span class="preprocessor">#include&nbsp;&lt;sys/types.h&gt;&nbsp;</span><span>&nbsp;&nbsp;</span></span></li>
<li><span><span class="preprocessor">#include&nbsp;&lt;sys/ioctl.h&gt;&nbsp;</span><span>&nbsp;&nbsp;</span></span></li>
<li class="alt"><span><span class="preprocessor">#include&nbsp;&lt;stdlib.h&gt;&nbsp;</span><span>&nbsp;&nbsp;</span></span></li>
<li><span><span class="preprocessor">#include&nbsp;&lt;stdio.h&gt;&nbsp;</span><span>&nbsp;&nbsp;</span></span></li>
<li class="alt"><span><span class="preprocessor">#include&nbsp;&lt;linux/soundcard.h&gt;&nbsp;</span><span>&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span><span class="preprocessor">#define&nbsp;LENGTH&nbsp;3&nbsp;&nbsp;&nbsp;&nbsp;/*&nbsp;存储秒数&nbsp;*/&nbsp;</span><span>&nbsp;&nbsp;</span></span></li>
<li><span><span class="preprocessor">#define&nbsp;RATE&nbsp;8000&nbsp;&nbsp;&nbsp;/*&nbsp;采样频率&nbsp;*/&nbsp;</span><span>&nbsp;&nbsp;</span></span></li>
<li class="alt"><span><span class="preprocessor">#define&nbsp;SIZE&nbsp;8&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/*&nbsp;量化位数&nbsp;*/&nbsp;</span><span>&nbsp;&nbsp;</span></span></li>
<li><span><span class="preprocessor">#define&nbsp;CHANNELS&nbsp;1&nbsp;&nbsp;/*&nbsp;声道数目&nbsp;*/&nbsp;</span><span>&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;</span></li>
<li><span><span class="comment">/*&nbsp;用于保存数字音频数据的内存缓冲区&nbsp;*/</span><span>&nbsp;&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>unsigned&nbsp;<span class="datatypes">char</span><span>&nbsp;buf[LENGTH*RATE*SIZE*CHANNELS/8];&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span><span class="datatypes">int</span><span>&nbsp;main()&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>{&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></li>
<li><span><span class="datatypes">int</span><span>&nbsp;fd;</span><span class="comment">/*&nbsp;声音设备的文件描述符&nbsp;*/</span><span>&nbsp;&nbsp;&nbsp;</span></span></li>
<li class="alt"><span><span class="datatypes">int</span><span>&nbsp;id;&nbsp;</span><span class="comment">/*声音输出文件描述符*/</span><span>&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span><span class="datatypes">int</span><span>&nbsp;arg;</span><span class="comment">/*&nbsp;用于ioctl调用的参数&nbsp;*/</span><span>&nbsp;&nbsp;&nbsp;</span></span></li>
<li class="alt"><span><span class="datatypes">int</span><span>&nbsp;status;&nbsp;&nbsp;&nbsp;</span><span class="comment">/*&nbsp;系统调用的返回值&nbsp;*/</span><span>&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span><span class="datatypes">int</span><span>&nbsp;i;&nbsp;&nbsp;&nbsp;</span></span></li>
<li class="alt"><span><span class="datatypes">int</span><span>&nbsp;j;&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;</span></li>
<li><span>&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span><span class="comment">/*&nbsp;打开声音设备&nbsp;*/</span><span>&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>fd&nbsp;=&nbsp;open(<span class="string">&quot;/dev/dsp&quot;</span><span>,&nbsp;O_RDWR);</span><span class="comment">//arm下的音频文件是&quot;/dev/sound/dsp&quot;;&nbsp;</span><span>&nbsp;&nbsp;</span></span></li>
<li class="alt"><span><span class="keyword">if</span><span>&nbsp;(fd&nbsp;&lt;&nbsp;0)&nbsp;{&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;perror(<span class="string">&quot;open&nbsp;of&nbsp;/dev/dsp&nbsp;failed&quot;</span><span>);&nbsp;&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;exit(1);&nbsp;&nbsp;&nbsp;</span></li>
<li><span>}&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span><span class="comment">/*打开输出文件*/</span><span>&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>id=open(<span class="string">&quot;Music.wav&quot;</span><span>,O_RDWR);&nbsp;&nbsp;&nbsp;</span></span></li>
<li class="alt"><span><span class="keyword">if</span><span>(id&nbsp;&lt;&nbsp;0){&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;perror(<span class="string">&quot;open&nbsp;of&nbsp;sound&nbsp;file&nbsp;failed&quot;</span><span>);&nbsp;&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;exit(1);&nbsp;&nbsp;&nbsp;</span></li>
<li><span>}&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span><span class="comment">/*&nbsp;设置采样时的量化位数&nbsp;*/</span><span>&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>arg&nbsp;=&nbsp;SIZE;&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span>status&nbsp;=&nbsp;ioctl(fd,&nbsp;SOUND_PCM_WRITE_BITS,&nbsp;&amp;arg);&nbsp;&nbsp;&nbsp;</span></li>
<li><span><span class="keyword">if</span><span>&nbsp;(status&nbsp;==&nbsp;-1)&nbsp;&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;perror(<span class="string">&quot;SOUND_PCM_WRITE_BITS&nbsp;ioctl&nbsp;failed&quot;</span><span>);&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span><span class="keyword">if</span><span>&nbsp;(arg&nbsp;!=&nbsp;SIZE)&nbsp;&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;perror(<span class="string">&quot;unable&nbsp;to&nbsp;set&nbsp;sample&nbsp;size&quot;</span><span>);&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span><span class="comment">/*&nbsp;设置采样时的声道数目&nbsp;*/</span><span>&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>arg&nbsp;=&nbsp;CHANNELS;&nbsp;&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span>status&nbsp;=&nbsp;ioctl(fd,&nbsp;SOUND_PCM_WRITE_CHANNELS,&nbsp;&amp;arg);&nbsp;&nbsp;&nbsp;</span></li>
<li><span><span class="keyword">if</span><span>&nbsp;(status&nbsp;==&nbsp;-1)&nbsp;&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;perror(<span class="string">&quot;SOUND_PCM_WRITE_CHANNELS&nbsp;ioctl&nbsp;failed&quot;</span><span>);&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span><span class="keyword">if</span><span>&nbsp;(arg&nbsp;!=&nbsp;CHANNELS)&nbsp;&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;perror(<span class="string">&quot;unable&nbsp;to&nbsp;set&nbsp;number&nbsp;of&nbsp;channels&quot;</span><span>);&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span><span class="comment">/*&nbsp;设置采样时的采样频率&nbsp;*/</span><span>&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>arg&nbsp;=&nbsp;RATE;&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span>status&nbsp;=&nbsp;ioctl(fd,&nbsp;SOUND_PCM_WRITE_RATE,&nbsp;&amp;arg);&nbsp;&nbsp;&nbsp;</span></li>
<li><span><span class="keyword">if</span><span>&nbsp;(status&nbsp;==&nbsp;-1)&nbsp;&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;perror(<span class="string">&quot;SOUND_PCM_WRITE_WRITE&nbsp;ioctl&nbsp;failed&quot;</span><span>);&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span><span class="comment">/*&nbsp;读取一定数量的音频数据，并将之写到输出文件中去&nbsp;*/</span><span>&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span><span class="keyword">for</span><span>(i=0;i&lt;10;i++){&nbsp;&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;j=read(id,&nbsp;buf,&nbsp;<span class="keyword">sizeof</span><span>(buf));&nbsp;&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">if</span><span>&nbsp;(j&nbsp;&gt;&nbsp;0){&nbsp;&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;write(fd,&nbsp;buf,&nbsp;j);&nbsp;<span class="comment">/*&nbsp;放音&nbsp;*/</span><span>&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;&nbsp;</span></li>
<li><span>&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span><span class="comment">/*&nbsp;关闭输入、输出文件&nbsp;*/</span><span>&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>close(fd);&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span>close(id);&nbsp;&nbsp;&nbsp;</span></li>
<li><span><span class="keyword">return</span><span>&nbsp;1;&nbsp;&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>}&nbsp;&nbsp;</span></li>
</ol>
</div>
<div style="display: none;" class="cpp">#include &lt;unistd.h&gt;  #include <fcntl.h>  #include <sys types.h="">  #include <sys ioctl.h="">  #include <stdlib.h>  #include <stdio.h>  #include</p>
<linux soundcard.h="">    #define LENGTH 3    /* 存储秒数 */  #define RATE 8000   /* 采样频率 */  #define SIZE 8      /* 量化位数 */  #define CHANNELS 1  /* 声道数目 */    /* 用于保存数字音频数据的内存缓冲区 */  unsigned char buf[LENGTH*RATE*SIZE*CHANNELS/8];    int main()  {       int fd;/* 声音设备的文件描述符 */  int id; /*声音输出文件描述符*/  int arg;/* 用于ioctl调用的参数 */  int status;   /* 系统调用的返回值 */  int i;  int j;        /* 打开声音设备 */  fd = open(&quot;/dev/dsp&quot;, O_RDWR);//arm下的音频文件是&quot;/dev/sound/dsp&quot;;  if (fd &lt; 0) {     perror(&quot;open of /dev/dsp failed&quot;);     exit(1);  }  /*打开输出文件*/  id=open(&quot;Music.wav&quot;,O_RDWR);  if(id &lt; 0){     perror(&quot;open of sound file failed&quot;);     exit(1);  }  /* 设置采样时的量化位数 */  arg = SIZE;  status = ioctl(fd, SOUND_PCM_WRITE_BITS, &amp;arg);  if (status == -1)     perror(&quot;SOUND_PCM_WRITE_BITS ioctl failed&quot;);  if (arg != SIZE)     perror(&quot;unable to set sample size&quot;);    /* 设置采样时的声道数目 */  arg = CHANNELS;   status = ioctl(fd, SOUND_PCM_WRITE_CHANNELS, &amp;arg);  if (status == -1)     perror(&quot;SOUND_PCM_WRITE_CHANNELS ioctl failed&quot;);  if (arg != CHANNELS)     perror(&quot;unable to set number of channels&quot;);    /* 设置采样时的采样频率 */  arg = RATE;  status = ioctl(fd, SOUND_PCM_WRITE_RATE, &amp;arg);  if (status == -1)     perror(&quot;SOUND_PCM_WRITE_WRITE ioctl failed&quot;);    /* 读取一定数量的音频数据，并将之写到输出文件中去 */  for(i=0;i&lt;10;i++){        j=read(id, buf, sizeof(buf));         if (j &gt; 0){          write(fd, buf, j); /* 放音 */        }      }    /* 关闭输入、输出文件 */  close(fd);  close(id);  return 1;  }</linux>
</stdio.h></stdlib.h></sys></sys></fcntl.h></div>
</div>
<p>&nbsp;</p>
]]></content:encoded>
			<wfw:commentRss>http://www.oursit.com/archives/123.html/feed</wfw:commentRss>
		</item>
		<item>
		<title>mysql proxy源代码初探</title>
		<link>http://www.oursit.com/archives/118.html</link>
		<comments>http://www.oursit.com/archives/118.html#comments</comments>
		<pubDate>Sat, 30 Aug 2008 05:19:55 +0000</pubDate>
		<dc:creator>Skylin</dc:creator>
		
		<category><![CDATA[C/C++]]></category>

		<category><![CDATA[mysql proxy]]></category>

		<category><![CDATA[源代码分析]]></category>

		<guid isPermaLink="false">http://www.oursit.com/?p=118</guid>
		<description><![CDATA[今天花了半天时间看了下mysql proxy源代码，主要是找出MYSQL协议部分，下面我来说一下过程，以便记录一下。
第一步：找出重点结构
1.network_mysqld_config
network_mysqld_config结构              在network-mysqld.h
主要用于mysqlproxy的整体配置结构，存储的一些服务器IP和端口地址。用于mysql proxy和链接客户端使用
2.netword_mysqld
netword_mysqld结构         network-mysqld.h
个人觉得主要存储mysql proxy的事件驱动机制和network_mysqld_config结构，还会存储一个HASH表结构，这个HASH表结构中存储的是一些功能函数，比如connections_select，config_select，help_select，authors_select函数，这些函数在mysql-proxy.c文件中，这个结构和network_mysqld_config结构是两个全局结构，基本上其他结构都会用到这两个结构体。
3.network_mysqld_table
netword_mysqld_table结构         network-mysqld.h
这个结构就是用在network_mysqld中的HASH表中的，用于存储上面HASH表存储的那几个功能函数。
4.netword_mysqld_con
netword_mysqld_con结构       network-mysqld.h
这个结构表示mysql proxy服务器和客户端的链接状态和请求状态，其中存储着套接字信息和MYSQL链接请求信息，还有模拟MYSQL协议的功能函数信息（以插件形式存在）
5.network_socket
network_socket结构     network-socket.h
里面存储的就是mysql proxy服务端和客户端的sockaddr信息了，包括IP地址字符串信息，主要使用在netword_mysqld_con结构中。其中还用到了network_address，network_queue结构，好像还包括用户名密码（应该是MYSQL的）
基本上主要结构体就是这些了，现在我已经在分析模拟MYSQL协议的地方了，有时间我会在继续写的。
]]></description>
			<content:encoded><![CDATA[<p>今天花了半天时间看了下mysql proxy源代码，主要是找出MYSQL协议部分，下面我来说一下过程，以便记录一下。</p>
<p><strong>第一步：找出重点结构</strong></p>
<p><strong>1.network_mysqld_config</strong></p>
<p>network_mysqld_config结构              在network-mysqld.h</p>
<p>主要用于mysqlproxy的整体配置结构，存储的一些服务器IP和端口地址。用于mysql proxy和链接客户端使用</p>
<p><strong>2.netword_mysqld</strong></p>
<p>netword_mysqld结构         network-mysqld.h</p>
<p>个人觉得主要存储mysql proxy的事件驱动机制和network_mysqld_config结构，还会存储一个HASH表结构，这个HASH表结构中存储的是一些功能函数，比如connections_select，config_select，help_select，authors_select函数，这些函数在mysql-proxy.c文件中，这个结构和network_mysqld_config结构是两个全局结构，基本上其他结构都会用到这两个结构体。</p>
<p><strong>3.network_mysqld_table</strong></p>
<p>netword_mysqld_table结构         network-mysqld.h</p>
<p>这个结构就是用在network_mysqld中的HASH表中的，用于存储上面HASH表存储的那几个功能函数。</p>
<p><strong>4.netword_mysqld_con</strong></p>
<p>netword_mysqld_con结构       network-mysqld.h</p>
<p>这个结构表示mysql proxy服务器和客户端的链接状态和请求状态，其中存储着套接字信息和MYSQL链接请求信息，还有模拟MYSQL协议的功能函数信息（以插件形式存在）</p>
<p><strong>5.network_socket</strong></p>
<p>network_socket结构     network-socket.h</p>
<p>里面存储的就是mysql proxy服务端和客户端的sockaddr信息了，包括IP地址字符串信息，主要使用在netword_mysqld_con结构中。其中还用到了network_address，network_queue结构，好像还包括用户名密码（应该是MYSQL的）</p>
<p>基本上主要结构体就是这些了，现在我已经在分析模拟MYSQL协议的地方了，有时间我会在继续写的。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.oursit.com/archives/118.html/feed</wfw:commentRss>
		</item>
		<item>
		<title>linux 2.6内核epoll用法举例说明</title>
		<link>http://www.oursit.com/archives/116.html</link>
		<comments>http://www.oursit.com/archives/116.html#comments</comments>
		<pubDate>Fri, 29 Aug 2008 13:49:05 +0000</pubDate>
		<dc:creator>Skylin</dc:creator>
		
		<category><![CDATA[C/C++]]></category>

		<category><![CDATA[epoll]]></category>

		<category><![CDATA[linux]]></category>

		<guid isPermaLink="false">http://www.oursit.com/?p=116</guid>
		<description><![CDATA[epoll用到的所有函数都是在头文件sys/epoll.
h中声明的，下面简要说明所用到的数据结构和函数：&#160;
所用到的数据结构 


&#160;

typedef&#160;union&#160;epoll_data&#160;{&#160;&#160;&#160;
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;void&#160;*ptr;&#160;&#160;&#160;
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;int&#160;fd;&#160;&#160;&#160;
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;__uint32_t&#160;u32;&#160;&#160;&#160;
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;__uint64_t&#160;u64;&#160;&#160;&#160;
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;}&#160;epoll_data_t;&#160;&#160;&#160;
&#160;&#160;&#160;
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;struct&#160;epoll_event&#160;{&#160;&#160;&#160;
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;__uint32_t&#160;events;&#160;&#160;&#160;&#160;&#160;&#160;/*&#160;Epoll&#160;events&#160;*/&#160;&#160;&#160;
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;epoll_data_t&#160;data;&#160;&#160;&#160;&#160;&#160;&#160;/*&#160;User&#160;data&#160;variable&#160;*/&#160;&#160;&#160;
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;};&#160;&#160;&#160;


typedef union epoll_data {                  void *ptr;                  int fd;             [...]]]></description>
			<content:encoded><![CDATA[<p><span style="font-size: small;"><font face="宋体">epoll用到的所有函数都是在头文件sys/epoll.</font></span></p>
<p><font size="3" face="宋体"><wbr></wbr><span style="font-size: small;">h中声明的，下面简要说明所用到的数据结构和函数：&nbsp;<br />
所用到的数据结构 </span><br />
</font></p>
<div class="dp-highlighter">
<div class="bar">&nbsp;</div>
<ol start="1" class="dp-cpp">
<li class="alt"><span><span class="keyword">typedef</span><span>&nbsp;</span><span class="keyword">union</span><span>&nbsp;epoll_data&nbsp;{&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">void</span><span>&nbsp;*ptr;&nbsp;&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="datatypes">int</span><span>&nbsp;fd;&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;__uint32_t&nbsp;u32;&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;__uint64_t&nbsp;u64;&nbsp;&nbsp;&nbsp;</span></li>
<li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;epoll_data_t;&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;</span></li>
<li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">struct</span><span>&nbsp;epoll_event&nbsp;{&nbsp;&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;__uint32_t&nbsp;events;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">/*&nbsp;Epoll&nbsp;events&nbsp;*/</span><span>&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;epoll_data_t&nbsp;data;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">/*&nbsp;User&nbsp;data&nbsp;variable&nbsp;*/</span><span>&nbsp;&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;};&nbsp;&nbsp;&nbsp;</span></li>
</ol>
</div>
<div style="display: none;" class="cpp">typedef union epoll_data {                  void *ptr;                  int fd;                  __uint32_t u32;                  __uint64_t u64;          } epoll_data_t;            struct epoll_event {                  __uint32_t events;      /* Epoll events */                  epoll_data_t data;      /* User data variable */          };</div>
<link rel="stylesheet" type="text/css" href="/wp-content/plugins/fckeditor_for_wordpress/fckeditor/editor/plugins/highlighter/dp.SyntaxHighlighter/Styles/SyntaxHighlighter.css" />
<p><span style="font-size: small;"><font face="宋体"> 结构体epoll_event 被用于注册所感兴趣的事件和回传所发生待处理的事件，</font></span><font size="3" face="宋体"><wbr></wbr><span style="font-size: small;">其中epoll_data  联合体用来保存触发事件的某个文件描述符相关的数据，</span><wbr></wbr><span style="font-size: small;">例如一个client连接到服务器，</span><wbr></wbr><span style="font-size: small;">服务器通过调用accept函数可以得到于这个client对应  的socket文件描述符，可以把这文件描述符赋给epoll_</span><wbr></wbr><span style="font-size: small;">data的fd字段以便后面的读写操作在这个文件描述符上进行。</span><wbr></wbr><span style="font-size: small;">epoll_event  结构体的events字段是表示感兴趣的事件和被触发的事件可能</span><wbr></wbr><span style="font-size: small;">的取值为：EPOLLIN  ：表示对应的文件描述符可以读；&nbsp;</span></font></p>
<p><font size="3" face="宋体"><span style="font-size: small;"><br />
EPOLLOUT：表示对应的文件描述符可以写；</span></font></p>
<p><font size="3" face="宋体"><span style="font-size: small;">&nbsp;<br />
EPOLLPRI：表示对应的文件描述符有紧急的数据可读（</span><wbr></wbr><span style="font-size: small;">我不太明白是什么意思，可能是类似client关闭&nbsp;&nbsp;</span><wbr></wbr><span style="font-size: small;">socket连接这样的事件）；&nbsp;</span></font></p>
<p><font size="3" face="宋体"><span style="font-size: small;"><br />
EPOLLERR：表示对应的文件描述符发生错误；&nbsp;</span></font></p>
<p><font size="3" face="宋体"><span style="font-size: small;"><br />
EPOLLHUP：表示对应的文件描述符被挂断；&nbsp;</span></font></p>
<p><font size="3" face="宋体"><span style="font-size: small;"><br />
EPOLLET：表示对应的文件描述符有事件发生；&nbsp;</span></font></p>
<p><font size="3" face="宋体"><span style="font-size: small;"><br />
所用到的函数：&nbsp;</span></font></p>
<p><font size="3" face="宋体"><span style="font-size: small;"><br />
1、epoll_create函数&nbsp;<br />
&nbsp;&nbsp; 函数声明：int epoll_create(int size)&nbsp;<br />
&nbsp;&nbsp; 该函数生成一个epoll专用的文件描述符，</span><wbr></wbr><span style="font-size: small;">其中的参数是指定生成描述符的最大范围（</span><wbr></wbr><span style="font-size: small;">我觉得这个参数和select函数的第一个参数应该是类似的但是</span><wbr></wbr><span style="font-size: small;">该怎么设置才好，我也不太清楚）。</span></font></p>
<p><font size="3" face="宋体"><span style="font-size: small;">&nbsp;<br />
2、epoll_ctl函数&nbsp;<br />
&nbsp;&nbsp; 函数声明：int epoll_ctl(int epfd, int op, int fd, struct epoll_event  *event)&nbsp;<br />
&nbsp;&nbsp; 该函数用于控制某个文件描述符上的事件，可以注册事件，</span><wbr></wbr><span style="font-size: small;">修改事件，删除事件。&nbsp;<br />
&nbsp;&nbsp; 参数：</span></font></p>
<p><font size="3" face="宋体"><span style="font-size: small;">&nbsp;&nbsp; epfd：由 epoll_create 生成的epoll专用的文件描述符；&nbsp;<br />
&nbsp;&nbsp; op：要进行的操作例如注册事件，可能的取值EPOLL_</span><wbr></wbr><span style="font-size: small;">CTL_ADD  注册、EPOLL_CTL_MOD 修改、EPOLL_CTL_DEL 删除&nbsp;<br />
&nbsp;&nbsp; fd：关联的文件描述符；&nbsp;<br />
&nbsp;&nbsp; event：指向epoll_event的指针；&nbsp;<br />
&nbsp;&nbsp; 如果调用成功返回0,不成功返回-1&nbsp;</span></font></p>
<p><font size="3" face="宋体"><span style="font-size: small;"><br />
3、epoll_wait函数&nbsp;<br />
&nbsp;&nbsp; 函数声明:int epoll_wait(int epfd,struct epoll_event * events,int  maxevents,int&nbsp; timeout)&nbsp;<br />
&nbsp;&nbsp; 该函数用于轮询I/O事件的发生；&nbsp;<br />
&nbsp;&nbsp; 参数：&nbsp;</span></font></p>
<p><font size="3" face="宋体"><span style="font-size: small;">&nbsp;&nbsp; epfd:由epoll_create 生成的epoll专用的文件描述符；&nbsp;<br />
&nbsp;&nbsp; epoll_event:用于回传代处理事件的数组；&nbsp;<br />
&nbsp;&nbsp; maxevents:每次能处理的事件数；&nbsp;<br />
&nbsp;&nbsp; timeout:等待I/O事件发生的超时值；&nbsp;<br />
&nbsp;&nbsp; 返回发生事件数。&nbsp;</span></font></p>
<p><font size="3" face="宋体"><span style="font-size: small;"><br />
例子： </span><br />
</font></p>
<p>&nbsp;</p>
<div>
<div class="dp-highlighter">
<div class="bar">&nbsp;</div>
<ol start="1" class="dp-cpp">
<li class="alt"><span><span class="preprocessor">#include&nbsp;&lt;iostream&gt;&nbsp;</span><span>&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span><span class="preprocessor">#include&nbsp;&lt;sys/socket.h&gt;&nbsp;</span><span>&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span><span class="preprocessor">#include&nbsp;&lt;sys/epoll.h&gt;&nbsp;</span><span>&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span><span class="preprocessor">#include&nbsp;&lt;netinet/in.h&gt;&nbsp;</span><span>&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span><span class="preprocessor">#include&nbsp;&lt;arpa/inet.h&gt;&nbsp;</span><span>&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span><span class="preprocessor">#include&nbsp;&lt;fcntl.h&gt;&nbsp;</span><span>&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span><span class="preprocessor">#include&nbsp;&lt;unistd.h&gt;&nbsp;</span><span>&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span><span class="preprocessor">#include&nbsp;&lt;stdio.h&gt;&nbsp;</span><span>&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;</span></li>
<li><span>&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span><span class="preprocessor">#define&nbsp;MAXLINE&nbsp;10&nbsp;</span><span>&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span><span class="preprocessor">#define&nbsp;OPEN_MAX&nbsp;100&nbsp;</span><span>&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span><span class="preprocessor">#define&nbsp;LISTENQ&nbsp;20&nbsp;</span><span>&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span><span class="preprocessor">#define&nbsp;SERV_PORT&nbsp;5555&nbsp;</span><span>&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span><span class="preprocessor">#define&nbsp;INFTIM&nbsp;1000&nbsp;</span><span>&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;</span></li>
<li><span>&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span><span class="keyword">void</span><span>&nbsp;setnonblocking(</span><span class="datatypes">int</span><span>&nbsp;sock)&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span>{&nbsp;&nbsp;&nbsp;</span></li>
<li><span>&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="datatypes">int</span><span>&nbsp;opts;&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;opts=fcntl(sock,F_GETFL);&nbsp;&nbsp;&nbsp;</span></li>
<li><span>&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">if</span><span>(opts&lt;0)&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{&nbsp;&nbsp;&nbsp;</span></li>
<li><span>&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;perror(<span class="string">&quot;fcntl(sock,GETFL)&quot;</span><span>);&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;exit(1);&nbsp;&nbsp;&nbsp;</span></li>
<li><span>&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;&nbsp;</span></li>
<li><span>&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;opts&nbsp;=&nbsp;opts|O_NONBLOCK;&nbsp;&nbsp;&nbsp;</span></li>
<li><span>&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">if</span><span>(fcntl(sock,F_SETFL,opts)&lt;0)&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{&nbsp;&nbsp;&nbsp;</span></li>
<li><span>&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;perror(<span class="string">&quot;fcntl(sock,SETFL,opts)&quot;</span><span>);&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;exit(1);&nbsp;&nbsp;&nbsp;</span></li>
<li><span>&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></li>
<li><span>&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span>}&nbsp;&nbsp;&nbsp;</span></li>
<li><span>&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;</span></li>
<li><span>&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span><span class="datatypes">int</span><span>&nbsp;main()&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span>{&nbsp;&nbsp;&nbsp;</span></li>
<li><span>&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="datatypes">int</span><span>&nbsp;i,&nbsp;maxi,&nbsp;listenfd,&nbsp;connfd,&nbsp;sockfd,epfd,nfds;&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ssize_t&nbsp;n;&nbsp;&nbsp;&nbsp;</span></li>
<li><span>&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="datatypes">char</span><span>&nbsp;line[MAXLINE];&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;socklen_t&nbsp;clilen;&nbsp;&nbsp;&nbsp;</span></li>
<li><span>&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">//声明epoll_event结构体的变量,ev用于注册事件,数组用于回传要处理的事件&nbsp;</span><span>&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">struct</span><span>&nbsp;epoll_event&nbsp;ev,events[20];&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">//生成用于处理accept的epoll专用的文件描述符&nbsp;</span><span>&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;epfd=epoll_create(256);&nbsp;&nbsp;&nbsp;</span></li>
<li><span>&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;</span></li>
<li><span>&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">struct</span><span>&nbsp;sockaddr_in&nbsp;clientaddr;&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">struct</span><span>&nbsp;sockaddr_in&nbsp;serveraddr;&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;listenfd&nbsp;=&nbsp;socket(AF_INET,&nbsp;SOCK_STREAM,&nbsp;0);&nbsp;&nbsp;&nbsp;</span></li>
<li><span>&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">//把socket设置为非阻塞方式&nbsp;</span><span>&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;setnonblocking(listenfd);&nbsp;&nbsp;&nbsp;</span></li>
<li><span>&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">//设置与要处理的事件相关的文件描述符&nbsp;</span><span>&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ev.data.fd=listenfd;&nbsp;&nbsp;&nbsp;</span></li>
<li><span>&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">//设置要处理的事件类型&nbsp;</span><span>&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ev.events=EPOLLIN|EPOLLET;&nbsp;&nbsp;&nbsp;</span></li>
<li><span>&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">//注册epoll事件&nbsp;</span><span>&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;epoll_ctl(epfd,EPOLL_CTL_ADD,listenfd,&amp;ev);&nbsp;&nbsp;&nbsp;</span></li>
<li><span>&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;</span></li>
<li><span>&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;bzero(&amp;serveraddr,&nbsp;<span class="keyword">sizeof</span><span>(serveraddr));&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;serveraddr.sin_family&nbsp;=&nbsp;AF_INET;&nbsp;&nbsp;&nbsp;</span></li>
<li><span>&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;</span></li>
<li><span>&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="datatypes">char</span><span>&nbsp;*local_addr=</span><span class="string">&quot;200.200.200.204&quot;</span><span>;&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;inet_aton(local_addr,&amp;(serveraddr.sin_addr));<span class="comment">//htons(SERV_PORT);&nbsp;</span><span>&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;serveraddr.sin_port=htons(SERV_PORT);&nbsp;&nbsp;&nbsp;</span></li>
<li><span>&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;bind(listenfd,(sockaddr&nbsp;*)&amp;serveraddr,&nbsp;<span class="keyword">sizeof</span><span>(serveraddr));&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;listen(listenfd,&nbsp;LISTENQ);&nbsp;&nbsp;&nbsp;</span></li>
<li><span>&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;</span></li>
<li><span>&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;maxi&nbsp;=&nbsp;0;&nbsp;&nbsp;&nbsp;</span></li>
<li><span>&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">for</span><span>&nbsp;(&nbsp;;&nbsp;;&nbsp;)&nbsp;{&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">//等待epoll事件的发生&nbsp;</span><span>&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;nfds=epoll_wait(epfd,events,20,500);&nbsp;&nbsp;&nbsp;</span></li>
<li><span>&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">//处理所发生的所有事件&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span>&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">for</span><span>(i=0;i&lt;nfds;++i)&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{&nbsp;&nbsp;&nbsp;</span></li>
<li><span>&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">if</span><span>(events.data.fd==listenfd)&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{&nbsp;&nbsp;&nbsp;</span></li>
<li><span>&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;</span></li>
<li><span>&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;connfd&nbsp;=&nbsp;accept(listenfd,(sockaddr&nbsp;*)&amp;clientaddr,&nbsp;&amp;clilen);&nbsp;&nbsp;&nbsp;</span></li>
<li><span>&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">if</span><span>(connfd&lt;0){&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;perror(<span class="string">&quot;connfd&lt;0&quot;</span><span>);&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;exit(1);&nbsp;&nbsp;&nbsp;</span></li>
<li><span>&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;&nbsp;</span></li>
<li><span>&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;setnonblocking(connfd);&nbsp;&nbsp;&nbsp;</span></li>
<li><span>&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;</span></li>
<li><span>&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="datatypes">char</span><span>&nbsp;*str&nbsp;=&nbsp;inet_ntoa(clientaddr.sin_addr);&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;std::cout&lt;&lt;<span class="string">&quot;connect&nbsp;from&nbsp;&quot;</span><span>&lt;_u115&nbsp;?tr&lt;&lt;std::endl;&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">//设置用于读操作的文件描述符&nbsp;</span><span>&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ev.data.fd=connfd;&nbsp;&nbsp;&nbsp;</span></li>
<li><span>&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">//设置用于注测的读操作事件&nbsp;</span><span>&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ev.events=EPOLLIN|EPOLLET;&nbsp;&nbsp;&nbsp;</span></li>
<li><span>&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">//注册ev&nbsp;</span><span>&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;epoll_ctl(epfd,EPOLL_CTL_ADD,connfd,&amp;ev);&nbsp;&nbsp;&nbsp;</span></li>
<li><span>&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;&nbsp;</span></li>
<li><span>&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">else</span><span>&nbsp;</span><span class="keyword">if</span><span>(events.events&amp;EPOLLIN)&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{&nbsp;&nbsp;&nbsp;</span></li>
<li><span>&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">if</span><span>&nbsp;(&nbsp;(sockfd&nbsp;=&nbsp;events.data.fd)&nbsp;&lt;&nbsp;0)&nbsp;</span><span class="keyword">continue</span><span>;&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">if</span><span>&nbsp;(&nbsp;(n&nbsp;=&nbsp;read(sockfd,&nbsp;line,&nbsp;MAXLINE))&nbsp;&lt;&nbsp;0)&nbsp;{&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">if</span><span>&nbsp;(errno&nbsp;==&nbsp;ECONNRESET)&nbsp;{&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;</span></li>
<li><span>&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;close(sockfd);&nbsp;&nbsp;&nbsp;</span></li>
<li><span>&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;events.data.fd&nbsp;=&nbsp;-1;&nbsp;&nbsp;&nbsp;</span></li>
<li><span>&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;<span class="keyword">else</span><span>&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;std::cout&lt;&lt;<span class="string">&quot;readline&nbsp;error&quot;</span><span>&lt;&lt;std::endl;&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;<span class="keyword">else</span><span>&nbsp;</span><span class="keyword">if</span><span>&nbsp;(n&nbsp;==&nbsp;0)&nbsp;{&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;close(sockfd);&nbsp;&nbsp;&nbsp;</span></li>
<li><span>&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;events.data.fd&nbsp;=&nbsp;-1;&nbsp;&nbsp;&nbsp;</span></li>
<li><span>&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;&nbsp;</span></li>
<li><span>&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">//设置用于写操作的文件描述符&nbsp;</span><span>&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ev.data.fd=sockfd;&nbsp;&nbsp;&nbsp;</span></li>
<li><span>&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">//设置用于注测的写操作事件&nbsp;</span><span>&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ev.events=EPOLLOUT|EPOLLET;&nbsp;&nbsp;&nbsp;</span></li>
<li><span>&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">//修改sockfd上要处理的事件为EPOLLOUT&nbsp;</span><span>&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;epoll_ctl(epfd,EPOLL_CTL_MOD,sockfd,&amp;ev);&nbsp;&nbsp;&nbsp;</span></li>
<li><span>&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;&nbsp;</span></li>
<li><span>&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">else</span><span>&nbsp;</span><span class="keyword">if</span><span>(events.events&amp;EPOLLOUT)&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></li>
<li><span>&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sockfd&nbsp;=&nbsp;events.data.fd;&nbsp;&nbsp;&nbsp;</span></li>
<li><span>&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;write(sockfd,&nbsp;line,&nbsp;n);&nbsp;&nbsp;&nbsp;</span></li>
<li><span>&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">//设置用于读操作的文件描述符&nbsp;</span><span>&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ev.data.fd=sockfd;&nbsp;&nbsp;&nbsp;</span></li>
<li><span>&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">//设置用于注测的读操作事件&nbsp;</span><span>&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ev.events=EPOLLIN|EPOLLET;&nbsp;&nbsp;&nbsp;</span></li>
<li><span>&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">//修改sockfd上要处理的事件为EPOLIN&nbsp;</span><span>&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;epoll_ctl(epfd,EPOLL_CTL_MOD,sockfd,&amp;ev);&nbsp;&nbsp;&nbsp;</span></li>
<li><span>&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;&nbsp;</span></li>
<li><span>&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;</span></li>
<li><span>&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;&nbsp;</span></li>
<li><span>&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;</span></li>
<li><span>&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;&nbsp;</span></li>
<li><span>&nbsp;&nbsp;&nbsp;</span></li>
<li class="alt"><span>}&nbsp;&nbsp;</span></li>
</ol>
</div>
<div style="display: none;" class="cpp">#include &lt;iostream&gt;    #include <sys socket.h="">    #include <sys epoll.h="">    #include <netinet in.h="">    #include <arpa inet.h="">    #include <fcntl.h>    #include <unistd.h>    #include <stdio.h>        #define MAXLINE 10    #define OPEN_MAX 100    #define LISTENQ 20    #define SERV_PORT 5555    #define INFTIM 1000        void setnonblocking(int sock)    {         int opts;         opts=fcntl(sock,F_GETFL);         if(opts&lt;0)         {              perror(&quot;fcntl(sock,GETFL)&quot;);              exit(1);         }         opts = opts|O_NONBLOCK;         if(fcntl(sock,F_SETFL,opts)&lt;0)         {              perror(&quot;fcntl(sock,SETFL,opts)&quot;);              exit(1);         }       }        int main()    {         int i, maxi, listenfd, connfd, sockfd,epfd,nfds;         ssize_t n;         char line[MAXLINE];         socklen_t clilen;         //声明epoll_event结构体的变量,ev用于注册事件,数组用于回传要处理的事件         struct epoll_event ev,events[20];         //生成用于处理accept的epoll专用的文件描述符         epfd=epoll_create(256);             struct sockaddr_in clientaddr;         struct sockaddr_in serveraddr;         listenfd = socket(AF_INET, SOCK_STREAM, 0);         //把socket设置为非阻塞方式         setnonblocking(listenfd);         //设置与要处理的事件相关的文件描述符         ev.data.fd=listenfd;         //设置要处理的事件类型         ev.events=EPOLLIN|EPOLLET;         //注册epoll事件         epoll_ctl(epfd,EPOLL_CTL_ADD,listenfd,&amp;ev);             bzero(&amp;serveraddr, sizeof(serveraddr));         serveraddr.sin_family = AF_INET;             char *local_addr=&quot;200.200.200.204&quot;;         inet_aton(local_addr,&amp;(serveraddr.sin_addr));//htons(SERV_PORT);         serveraddr.sin_port=htons(SERV_PORT);         bind(listenfd,(sockaddr *)&amp;serveraddr, sizeof(serveraddr));         listen(listenfd, LISTENQ);             maxi = 0;         for ( ; ; ) {              //等待epoll事件的发生              nfds=epoll_wait(epfd,events,20,500);              //处理所发生的所有事件                   for(i=0;i</stdio.h></unistd.h></fcntl.h></arpa></netinet></sys></sys></div>
</div>
<p>&nbsp;</p>
]]></content:encoded>
			<wfw:commentRss>http://www.oursit.com/archives/116.html/feed</wfw:commentRss>
		</item>
		<item>
		<title>flex3配合JS上传照片(服务器不保存上传图片)</title>
		<link>http://www.oursit.com/archives/111.html</link>
		<comments>http://www.oursit.com/archives/111.html#comments</comments>
		<pubDate>Fri, 29 Aug 2008 03:55:26 +0000</pubDate>
		<dc:creator>Skylin</dc:creator>
		
		<category><![CDATA[FLEX3]]></category>

		<category><![CDATA[flex]]></category>

		<category><![CDATA[截图]]></category>

		<category><![CDATA[上传照片]]></category>

		<guid isPermaLink="false">http://www.oursit.com/?p=111</guid>
		<description><![CDATA[前段时间因为自己的项目需要上传照片并对照片进行简单的处理，所以使用FLEX制作了一个上传照片的小应用。
这个小应用的特点是FLEX上传图片之后，后台PHP对图片进行处理转换成一种图片格式，然后把图片路径返回给FLEX显示，FLEX显示之后会在请求后台PHP一次删除图片（其实这里做的复杂了一点，可以直接让PHP把图片转换成一种图片格式之后直接把图片数据返回给FLEX，然后删除图片文件的），在flex中对照片进行处理并截取指定图片数据，把图片数据传递给JS，JS在对图片数据进行处理，这样可以进行表单整体提交，来达到不上传对于的图片文件到服务器浪费服务器的空间。
DEMO：http://www.oursit.com/demo/updatepic_demo/
这里我们先来说下这个DEMO的用法，首先我们点击“浏览“，会弹出一个选择窗口，选择我们的图片并上传。这时候上传图片窗口会显示我们上传的图片（这里上传的图片文件就已经删除了），我们可以使用鼠标拖动图片位置和左下角的进度条可以调整图片大小。我们选择好图片在上传图片中显示的样子之后，只要双击上传图片窗口中的图片，就会把我们想要截取的图片显示在右边的保存图片窗口中，下面的文本框中会出现很多数据，其实这些数据就是保存图片窗口中图片的二进制数据。这样我们就可以提交表单来对图片数据进行处理了。
上面只是说明使用方法，可能大家都会觉得这两个窗口不美观而且太小了，因为我自己项目的局限性的问题请大家原谅:)(什么项目？保密)。
下面我就来介绍一下实现方法
如果要用FLEX制作一个我这样的上传照片应用需要使用到
PNGEncoder;URLUtil; PopUpManager;FileReference;BitmapData这几个类
首先我们介绍上传图片
我们点击浏览按钮的时候会调用下面函数
private function onBrowse():void
{
m_browse.addEventListener(Event.SELECT,onSelect);    //选择好图片调用的事件
var m_filefilter:FileFilter = new FileFilter(&#8221;Images (*.jpg , *gif , *png)&#8221;, &#8220;*.jpg;*.gif;*.png&#8221;);  //这里只支持jpg,gif,png图片
m_browse.browse([m_filefilter]);
}
选择好图片然后点击开发的时候会触发 m_browse的Event.SELECT事件,下面请看onSelect函数
private function onSelect(event:Event):void
{
m_browse.removeEventListener(Event.SELECT,onSelect);
m_browse.addEventListener(Event.OPEN,onOpenStart);
m_browse.addEventListener(IOErrorEvent.IO_ERROR,onIOError);
m_browse.addEventListener(ProgressEvent.PROGRESS,onProgress);
m_browse.addEventListener(Event.COMPLETE,onComplete);
m_browse.addEventListener(DataEvent.UPLOAD_COMPLETE_DATA,onUploadCompleteData);
var urlrequest:URLRequest;
//Alert.show(URLUtil.getProtocol(Application.application.url));
//下面一块的作用是FLEX在IE和FF调用后台文件的路径不一样，所以这里必须要知道我们要调用的后台PHP文件在哪里，这里的PHP文件和上传图片的SWF文件放在同一目录
if(URLUtil.getProtocol(Application.application.url)==&#8221;file&#8221;)
{
urlrequest = new URLRequest(&#8221;index.php&#8221;);
}
else
{
var url:Array = Application.application.url.split(&#8221;/&#8221;);
url.pop();
//Alert.show(url.join(&#8221;/&#8221;)+&#8221;/index.php&#8221;);
urlrequest = new URLRequest(url.join(&#8221;/&#8221;)+&#8221;/index.php&#8221;);
}
var variables:URLVariables = new URLVariables();
variables.width = t_img_Picture.width;
variables.height = t_img_Picture.height;
urlrequest.method = URLRequestMethod.POST;
urlrequest.data = variables;
m_browse.upload(urlrequest,&#8221;Pic&#8221;);
}
这里上传图片完成之后会触发m_browse的DataEvent.UPLOAD_COMPLETE_DATA事件，我们在来看下onUploadCompleteData函数
private function onUploadCompleteData(event:DataEvent):void
{
t_img_Picture.addEventListener(Event.COMPLETE,onPicComplete);    //上传图片窗口显示图片之后触发的事件
path = event.data;
t_img_Picture.source = event.data; [...]]]></description>
			<content:encoded><![CDATA[<p>前段时间因为自己的项目需要上传照片并对照片进行简单的处理，所以使用FLEX制作了一个上传照片的小应用。</p>
<p>这个小应用的特点是FLEX上传图片之后，后台PHP对图片进行处理转换成一种图片格式，然后把图片路径返回给FLEX显示，FLEX显示之后会在请求后台PHP一次删除图片（其实这里做的复杂了一点，可以直接让PHP把图片转换成一种图片格式之后直接把图片数据返回给FLEX，然后删除图片文件的），在flex中对照片进行处理并截取指定图片数据，把图片数据传递给JS，JS在对图片数据进行处理，这样可以进行表单整体提交，来达到不上传对于的图片文件到服务器浪费服务器的空间。</p>
<p>DEMO：<a href="http://www.oursit.com/demo/updatepic_demo/" target="_blank">http://www.oursit.com/demo/updatepic_demo/</a></p>
<p>这里我们先来说下这个DEMO的用法，首先我们点击“浏览“，会弹出一个选择窗口，选择我们的图片并上传。这时候上传图片窗口会显示我们上传的图片（这里上传的图片文件就已经删除了），我们可以使用鼠标拖动图片位置和左下角的进度条可以调整图片大小。我们选择好图片在上传图片中显示的样子之后，只要双击上传图片窗口中的图片，就会把我们想要截取的图片显示在右边的保存图片窗口中，下面的文本框中会出现很多数据，其实这些数据就是保存图片窗口中图片的二进制数据。这样我们就可以提交表单来对图片数据进行处理了。</p>
<p>上面只是说明使用方法，可能大家都会觉得这两个窗口不美观而且太小了，因为我自己项目的局限性的问题请大家原谅:)(什么项目？保密)。</p>
<p>下面我就来介绍一下实现方法</p>
<p>如果要用FLEX制作一个我这样的上传照片应用需要使用到</p>
<p>PNGEncoder;URLUtil; PopUpManager;FileReference;BitmapData这几个类</p>
<p>首先我们介绍上传图片</p>
<p>我们点击浏览按钮的时候会调用下面函数</p>
<p>private function onBrowse():void<br />
{<br />
m_browse.addEventListener(Event.SELECT,onSelect);    //选择好图片调用的事件<br />
var m_filefilter:FileFilter = new FileFilter(&#8221;Images (*.jpg , *gif , *png)&#8221;, &#8220;*.jpg;*.gif;*.png&#8221;);  //这里只支持jpg,gif,png图片<br />
m_browse.browse([m_filefilter]);</p>
<p>}</p>
<p>选择好图片然后点击开发的时候会触发 m_browse的Event.SELECT事件,下面请看onSelect函数</p>
<p>private function onSelect(event:Event):void<br />
{<br />
m_browse.removeEventListener(Event.SELECT,onSelect);<br />
m_browse.addEventListener(Event.OPEN,onOpenStart);<br />
m_browse.addEventListener(IOErrorEvent.IO_ERROR,onIOError);<br />
m_browse.addEventListener(ProgressEvent.PROGRESS,onProgress);<br />
m_browse.addEventListener(Event.COMPLETE,onComplete);<br />
m_browse.addEventListener(DataEvent.UPLOAD_COMPLETE_DATA,onUploadCompleteData);<br />
var urlrequest:URLRequest;<br />
//Alert.show(URLUtil.getProtocol(Application.application.url));</p>
<p>//下面一块的作用是FLEX在IE和FF调用后台文件的路径不一样，所以这里必须要知道我们要调用的后台PHP文件在哪里，这里的PHP文件和上传图片的SWF文件放在同一目录<br />
if(URLUtil.getProtocol(Application.application.url)==&#8221;file&#8221;)<br />
{<br />
urlrequest = new URLRequest(&#8221;index.php&#8221;);<br />
}<br />
else<br />
{<br />
var url:Array = Application.application.url.split(&#8221;/&#8221;);<br />
url.pop();<br />
//Alert.show(url.join(&#8221;/&#8221;)+&#8221;/index.php&#8221;);<br />
urlrequest = new URLRequest(url.join(&#8221;/&#8221;)+&#8221;/index.php&#8221;);<br />
}<br />
var variables:URLVariables = new URLVariables();<br />
variables.width = t_img_Picture.width;<br />
variables.height = t_img_Picture.height;<br />
urlrequest.method = URLRequestMethod.POST;<br />
urlrequest.data = variables;<br />
m_browse.upload(urlrequest,&#8221;Pic&#8221;);<br />
}</p>
<p>这里上传图片完成之后会触发m_browse的DataEvent.UPLOAD_COMPLETE_DATA事件，我们在来看下onUploadCompleteData函数</p>
<p>private function onUploadCompleteData(event:DataEvent):void<br />
{<br />
t_img_Picture.addEventListener(Event.COMPLETE,onPicComplete);    //上传图片窗口显示图片之后触发的事件</p>
<p>path = event.data;<br />
t_img_Picture.source = event.data;   //上传图片窗口中显示</p>
<p>}</p>
<p>上面函数表示后台PHP程序返回给我们一个刚才上传的图片路径，我们在上传图片窗口中显示，并触发t_img_Picture的Event.COMPLETE事件，我们在来看看onPicComplete函数</p>
<p>private function onPicComplete(event:Event):void<br />
{<br />
//Alert.show();<br />
var m_urlrequest:URLRequest;</p>
<p>//Alert.show(URLUtil.getProtocol(Application.application.url));<br />
if(URLUtil.getProtocol(Application.application.url)==&#8221;file&#8221;)<br />
{<br />
m_urlrequest = new URLRequest(&#8221;deletepic.php&#8221;);<br />
}<br />
else<br />
{<br />
var url:Array = Application.application.url.split(&#8221;/&#8221;);<br />
url.pop();<br />
//Alert.show(url.join(&#8221;/&#8221;)+&#8221;/index.php&#8221;);<br />
m_urlrequest = new URLRequest(url.join(&#8221;/&#8221;)+&#8221;/deletepic.php&#8221;);<br />
}<br />
m_urlrequest.method = URLRequestMethod.POST;<br />
var variables:URLVariables = new URLVariables();<br />
variables.op = &#8216;delete&#8217;;<br />
var pathtemp:Array = path.split(&#8221;/&#8221;);</p>
<p>variables.file = pathtemp[pathtemp.length-1];</p>
<p>m_urlrequest.data = variables;<br />
var m_urlloader:URLLoader = new URLLoader(m_urlrequest);<br />
m_urlloader.load(m_urlrequest);<br />
t_img_Picture.removeEventListener(Event.COMPLETE,onPicComplete)<br />
}</p>
<p>上面函数主要用来在图片加载到上传图片窗口中之后删除服务器中的图片文件（其实这里我们可以不必要这么麻烦，直接在上传的时候转换图片格式一致性之后获得图片数据并删除图片文件，然后只需要把图片数据返回给FLEX就可以了。大家可以试试）</p>
<p>现在刚才上传的图片就显示在上传图片窗口中了，下面在来介绍一下拖动图片和放大缩小图片。其实这两个操作都比较简单，看下面代码。这里我不做说明了，这些方法全部作为t_img_Picture的事件</p>
<p>private function onMouseDownImg():void    //鼠标按下事件<br />
{<br />
imgisdrag = true;<br />
t_img_Picture.startDrag();</p>
<p>}</p>
<p>private function onMouseUpImg():void   //放开鼠标的事件<br />
{</p>
<p>if(imgisdrag)<br />
{<br />
t_img_Picture.stopDrag();<br />
onMouseMove()<br />
imgisdrag = false;</p>
<p>}</p>
<p>}</p>
<p>private function onMouseOverImg():void     //鼠标移进来的事件<br />
{<br />
t_img_Picture.mouseChildren = false;<br />
t_img_Picture.buttonMode = true;<br />
t_img_Picture.useHandCursor = true;<br />
}</p>
<p>private function onMouseOutImg():void     //鼠标移出去的事件<br />
{<br />
t_img_Picture.mouseChildren = true;<br />
t_img_Picture.buttonMode = false;<br />
t_img_Picture.useHandCursor = false;<br />
}</p>
<p>private function OnDragChange():void     //放大缩小的事件<br />
{</p>
<p>if(direction &gt; zoom.value)<br />
{<br />
t_img_Picture.height-=direction-zoom.value;<br />
t_img_Picture.width-=direction-zoom.value;<br />
}<br />
else<br />
{<br />
t_img_Picture.height+=zoom.value-direction;<br />
t_img_Picture.width+=zoom.value-direction;<br />
}<br />
direction = zoom.value;</p>
<p>}</p>
<p>private function onMouseMove():void     //用于图片不能拖出窗口。显示图片拖动范围，这个可以用也可以不用<br />
{<br />
/*if(imgisdrag)<br />
{<br />
if(t_img_Picture.x&gt;0)<br />
{<br />
t_img_Picture.x=0;<br />
}<br />
if(t_img_Picture.y&gt;0)<br />
{<br />
t_img_Picture.y=0;<br />
}<br />
if((t_img_Picture.width+t_img_Picture.x)&lt;my_canvas.width)<br />
{<br />
t_img_Picture.x = -(t_img_Picture.width-my_canvas.width);<br />
}<br />
if((t_img_Picture.height+t_img_Picture.y)&lt;my_canvas.height)<br />
{<br />
t_img_Picture.y = -(t_img_Picture.height-my_canvas.height);<br />
}<br />
//Alert.show(t_img_Picture.x.toString());<br />
}*/</p>
<p>}</p>
<p>下面就要来介绍把指定图片数据传递给JS，并把图片显示在右边保存图片窗口中</p>
<p>private function onDoubleClick():void     //双击左边图片开始保存图片数据显示在右边窗口中，并传递二进制数据给JS<br />
{<br />
m_pictureBitmapData = new BitmapData(my_canvas.width,my_canvas.height);<br />
m_pictureBitmapData.draw(my_canvas);    //获得左边图片数据的BitmapData数据<br />
//Alert.show(&#8221;aaaaaa&#8221;);<br />
var m_pictureBitmap:Bitmap = new Bitmap(m_pictureBitmapData);<br />
//save_Picture.addChild(m_pictureBitmap);<br />
save_Picture.source = m_pictureBitmap;   //显示在右边窗口中</p>
<p>var jpegEnc:JPEGEncoder = new JPEGEncoder(100);<br />
var jpegData:ByteArray = jpegEnc.encode(m_pictureBitmapData);  //把BitmapData数据转换成jpg图片二进制数据</p>
<p>//下面把二进制数据数组转换成字符串<br />
var m_Data:String = &#8221;;<br />
for(var i:int=0;i&lt;jpegData.length;i++)<br />
{<br />
if(m_Data.length &gt; 0)<br />
{<br />
m_Data += &#8220;,&#8221; + jpegData[i].toString();<br />
}<br />
else<br />
{<br />
m_Data = jpegData[i].toString();<br />
}<br />
//Alert.show(&#8221;bbbbbbb&#8221;);<br />
}</p>
<p>//调用JS函数setPic把二进制字串传递进去<br />
ExternalInterface.call(&#8221;setPic&#8221;,save_Picture.width,save_Picture.height,m_Data);<br />
}</p>
<p>现在FLEX的工作就完成了。下面讲下后台PHP代码，首先是上传图片</p>
<p>index.php    //主要工作是把上传的图片统一成PNG格式的图片，并返回给FLEX图片路径</p>
<p>&lt;?php</p>
<p>$path_parts = pathinfo($_FILES['Pic']['name']);</p>
<p>$fname = time().&#8221;_&#8221;.mt_rand(0,10000);</p>
<p>$filename = $fname.&#8221;.&#8221;.$path_parts['extension'];</p>
<p>if(move_uploaded_file($_FILES['Pic']['tmp_name'],&#8221;upload/&#8221;.$filename))<br />
{<br />
$size = getimagesize(&#8221;upload/&#8221;.$filename);<br />
$newwidth = $size[0];<br />
$newheight = $size[1];</p>
<p>$thumb = imagecreatetruecolor($newwidth, $newheight);<br />
switch($size[2])<br />
{<br />
case 1:   //GIF<br />
$source = imagecreatefromgif(&#8221;upload/&#8221;.$filename);<br />
break;<br />
case 2:   //JPG<br />
$source = imagecreatefromjpeg(&#8221;upload/&#8221;.$filename);<br />
break;<br />
case 3:   //PNG<br />
$source = imagecreatefrompng(&#8221;upload/&#8221;.$filename);<br />
break;<br />
}<br />
imagecopyresized($thumb, $source, 0, 0, 0, 0, $newwidth, $newheight, $size[0], $size[1]);<br />
unset($source);<br />
unlink(&#8221;upload/&#8221;.$filename);<br />
/*switch($size[2])<br />
{<br />
case 1:   //GIF<br />
imagegif($thumb,&#8221;upload/&#8221;.$filename);<br />
break;<br />
case 2:   //JPG<br />
imagejpeg($thumb,&#8221;upload/&#8221;.$filename);<br />
break;<br />
case 3:   //PNG*/<br />
imagepng($thumb,&#8221;upload/&#8221;.$fname.&#8221;.png&#8221;);<br />
/*break;<br />
}*/</p>
<p>die(&#8221;upload/&#8221;.$fname.&#8221;.png&#8221;);<br />
}<br />
?&gt;</p>
<p>deletepic.php    //在FLEX加载完上传图片之后，删除图片</p>
<p>&lt;?php</p>
<p>if($_POST['op'] == &#8216;delete&#8217;)<br />
{<br />
$path_parts = pathinfo($_POST['file']);<br />
if($path_parts['extension']==&#8217;png&#8217;)<br />
{<br />
@unlink(&#8221;upload/&#8221;.$_POST['file']);<br />
}</p>
<p>die();<br />
}</p>
<p>?&gt;</p>
<p>下面就是JS函数了，比较简单</p>
<p>//获得图片数据<br />
function setPic(width,height,data)<br />
{</p>
<p>document.getElementById(&#8221;update_photo&#8221;).value = data;<br />
}</p>
<p>下载DEMO：<a href="http://www.oursit.com/demo/updatepic_demo/updatepic_demo.rar" target="_blank">updatepic_demo.rar</a></p>
<p>下载代码：<a href="http://www.oursit.com/demo/updatepic_demo/updatephoto.rar" target="_blank">updatephoto.rar</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.oursit.com/archives/111.html/feed</wfw:commentRss>
		</item>
	</channel>
</rss>
