﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>BlogJava-备注学院-文章分类-Java</title><link>http://www.blogjava.net/smildlzj/category/27375.html</link><description>LuLu</description><language>zh-cn</language><lastBuildDate>Sun, 30 Mar 2008 09:30:16 GMT</lastBuildDate><pubDate>Sun, 30 Mar 2008 09:30:16 GMT</pubDate><ttl>60</ttl><item><title>Java权限控制的算法 </title><link>http://www.blogjava.net/smildlzj/articles/189575.html</link><dc:creator>smildlzj</dc:creator><author>smildlzj</author><pubDate>Sun, 30 Mar 2008 02:33:00 GMT</pubDate><guid>http://www.blogjava.net/smildlzj/articles/189575.html</guid><wfw:comment>http://www.blogjava.net/smildlzj/comments/189575.html</wfw:comment><comments>http://www.blogjava.net/smildlzj/articles/189575.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/smildlzj/comments/commentRss/189575.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/smildlzj/services/trackbacks/189575.html</trackback:ping><description><![CDATA[这里笔者介绍一种很常用，也比较专业的权限控制思路。这里用java语言描述，其实都差不多的。要换成其他的语言主，自己转一下就可以了。为了方便起见，我们这里定义a^b为：a的b次方。这里，我们为每一个操作设定一个唯一的整数值，比如：
<p>删除Ａ－－－0<br />
修改Ａ－－－1<br />
添加Ａ－－－2</p>
<!--newszw_hzh_begin-->
<table cellspacing="0" cellpadding="0" align="left" border="0">
    <tbody>
        <tr>
            <td>
            <div id="PublicRelation5" name="PublicRelation">&nbsp;</div>
            </td>
        </tr>
    </tbody>
</table>
<!--newszw_hzh_end-->
<p>删除Ｂ－－－3<br />
修改Ｂ－－－4<br />
添加Ｂ－－－5</p>
<p>&#8230;&#8230;</p>
<p>　　理论上可以有Ｎ个操作，这取决于你用于储存用户权限值的数据类型了。</p>
<p>　　这样，如果用户有权限：添加Ａ－－－2；删除Ｂ－－－3；修改Ｂ－－－4。那用户的权限值 purview =2^2+2^3+2^4＝28，也就是2的权的和了。化成二进制可以表示为11100。这样，如果要验证用户是否有删除Ｂ的权限，就可以通过位与运算来实现。在Ｊａｖａ里，位与运算运算符号为＆，即是：</p>
<p class="code">int value = purview &amp;((int)Math.pow(2,3));</p>
<p>　　你会发现，当用户有操作权限时，运算出来的结果都会等于这个操作需要的权限值！</p>
<p>　　原理：</p>
<p>　　位与运算，顾名思义就是对位进行与运算：</p>
<p>　　以上面的式子为例：purview &amp; 2^3 也就是　28&amp;8</p>
<p>　　将它们化成二进制有</p>
<p>　11100<br />
＆ 01000<br />
-------------------<br />
　 01000 == 8(十进制)　＝＝　2^3</p>
<p>　　同理，如果要验证是否有删除Ａ－－－0的权限</p>
<p>　　可以用：purview &amp;((int)Math.pow(2,0));</p>
<p>　　即：</p>
<p>　11100<br />
＆ 00001<br />
------------------------<br />
　 00000 == 0(十进制)　　！＝　2^0 </p>
<p>　　这种算法的一个优点是速度快。可以同时处理Ｎ个权限。如果想验证是否同时有删除Ａ－－－0和删除Ｂ－－－3的权限，可以用purview&amp;(2^0+2^3)==(2^0+2^3)?true:false;设置多角色用户。根据权限值判断用户的角色。</p>
<p>　　下面提供一个java的单操作权限判断的代码：</p>
<p class="code">//userPurview是用户具有的总权限<br />
//optPurview是一个操作要求的权限为一个整数（没有经过权的！）<br />
public static boolean checkPower(int userPurview, int optPurview)<br />
{<br />
&nbsp; int purviewValue = (int)Math.pow(2, optPurview);<br />
&nbsp; return (userPurview &amp; purviewValue) == purviewValue;<br />
}</p>
<p>　　当然，多权限的验证只要扩展一下就可以了。</p>
<p>　　几点注意事项：首先，一个系统可能有很多的操作，因此，请建立数据字典，以便查阅，修改时使用。其次，如果用数据库储存用户权限，请注意数值的有效范围。操作权限值请用唯一的整数！&nbsp;</p>
<br />
<img src ="http://www.blogjava.net/smildlzj/aggbug/189575.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/smildlzj/" target="_blank">smildlzj</a> 2008-03-30 10:33 <a href="http://www.blogjava.net/smildlzj/articles/189575.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[转载]用 AOP 来记录每个方法的执行时间 </title><link>http://www.blogjava.net/smildlzj/articles/179310.html</link><dc:creator>smildlzj</dc:creator><author>smildlzj</author><pubDate>Mon, 04 Feb 2008 14:56:00 GMT</pubDate><guid>http://www.blogjava.net/smildlzj/articles/179310.html</guid><wfw:comment>http://www.blogjava.net/smildlzj/comments/179310.html</wfw:comment><comments>http://www.blogjava.net/smildlzj/articles/179310.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/smildlzj/comments/commentRss/179310.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/smildlzj/services/trackbacks/179310.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 有时候我们要跟踪方法的执行时间，来观察系统的性能、时间分布。特别是要找出那些十分耗时的操作。如果是在每个方法中起始和结束位置记下时间相减，那是不太现实的，对代码的侵入性太过份，而且在产品环境中又得屏闭那部份代码。幸好现在有了 AOP，通过配置方式再加上外部辅助代码就能达到我们的要求，正式上线时只需要简单改个配置项拆卸下来即可。下面介绍三种方式来打印每个方法的执行时间，分别是：...&nbsp;&nbsp;<a href='http://www.blogjava.net/smildlzj/articles/179310.html'>阅读全文</a><img src ="http://www.blogjava.net/smildlzj/aggbug/179310.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/smildlzj/" target="_blank">smildlzj</a> 2008-02-04 22:56 <a href="http://www.blogjava.net/smildlzj/articles/179310.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>排序工具类NavigableSet </title><link>http://www.blogjava.net/smildlzj/articles/171479.html</link><dc:creator>smildlzj</dc:creator><author>smildlzj</author><pubDate>Sat, 29 Dec 2007 04:54:00 GMT</pubDate><guid>http://www.blogjava.net/smildlzj/articles/171479.html</guid><wfw:comment>http://www.blogjava.net/smildlzj/comments/171479.html</wfw:comment><comments>http://www.blogjava.net/smildlzj/articles/171479.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/smildlzj/comments/commentRss/171479.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/smildlzj/services/trackbacks/171479.html</trackback:ping><description><![CDATA[<font color="#008080">
<div style="border-right: #cccccc 1px solid; padding-right: 5px; border-top: #cccccc 1px solid; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left: #cccccc 1px solid; width: 98%; word-break: break-all; padding-top: 4px; border-bottom: #cccccc 1px solid; background-color: #eeeeee"><span style="color: #008080">&nbsp;1</span>&nbsp;<span style="color: #0000ff">import</span><span style="color: #000000">&nbsp;java.util.ArrayList;<br />
</span><span style="color: #008080">&nbsp;2</span>&nbsp;<span style="color: #0000ff">import</span><span style="color: #000000">&nbsp;java.util.List;<br />
</span><span style="color: #008080">&nbsp;3</span>&nbsp;<span style="color: #0000ff">import</span><span style="color: #000000">&nbsp;java.util.NavigableSet;<br />
</span><span style="color: #008080">&nbsp;4</span>&nbsp;<span style="color: #0000ff">import</span><span style="color: #000000">&nbsp;java.util.TreeSet;<br />
</span><span style="color: #008080">&nbsp;5</span>&nbsp;<span style="color: #000000"><br />
</span><span style="color: #008080">&nbsp;6</span>&nbsp;<span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">class</span><span style="color: #000000">&nbsp;NavigableSetTest{<br />
</span><span style="color: #008080">&nbsp;7</span>&nbsp;<span style="color: #000000"><br />
</span><span style="color: #008080">&nbsp;8</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;</span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">static</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">void</span><span style="color: #000000">&nbsp;main(String[]&nbsp;args)&nbsp;{<br />
</span><span style="color: #008080">&nbsp;9</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;List</span><span style="color: #000000">&lt;</span><span style="color: #000000">Integer</span><span style="color: #000000">&gt;</span><span style="color: #000000">&nbsp;list&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">new</span><span style="color: #000000">&nbsp;ArrayList</span><span style="color: #000000">&lt;</span><span style="color: #000000">Integer</span><span style="color: #000000">&gt;</span><span style="color: #000000">();<br />
</span><span style="color: #008080">10</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;list.add(</span><span style="color: #000000">1</span><span style="color: #000000">);<br />
</span><span style="color: #008080">11</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;list.add(</span><span style="color: #000000">2</span><span style="color: #000000">);<br />
</span><span style="color: #008080">12</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;list.add(</span><span style="color: #000000">10</span><span style="color: #000000">);<br />
</span><span style="color: #008080">13</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;list.add(</span><span style="color: #000000">4</span><span style="color: #000000">);<br />
</span><span style="color: #008080">14</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;list.add(</span><span style="color: #000000">5</span><span style="color: #000000">);<br />
</span><span style="color: #008080">15</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;list.add(</span><span style="color: #000000">9</span><span style="color: #000000">);<br />
</span><span style="color: #008080">16</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;list.add(</span><span style="color: #000000">8</span><span style="color: #000000">);<br />
</span><span style="color: #008080">17</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;list.add(</span><span style="color: #000000">7</span><span style="color: #000000">);<br />
</span><span style="color: #008080">18</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;list.add(</span><span style="color: #000000">6</span><span style="color: #000000">);<br />
</span><span style="color: #008080">19</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;<br />
</span><span style="color: #008080">20</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;NavigableSet</span><span style="color: #000000">&lt;</span><span style="color: #000000">Integer</span><span style="color: #000000">&gt;</span><span style="color: #000000">&nbsp;ns&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">new</span><span style="color: #000000">&nbsp;TreeSet</span><span style="color: #000000">&lt;</span><span style="color: #000000">Integer</span><span style="color: #000000">&gt;</span><span style="color: #000000">(list);<br />
</span><span style="color: #008080">21</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(</span><span style="color: #000000">"</span><span style="color: #000000">默认正序:&nbsp;</span><span style="color: #000000">"</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">+</span><span style="color: #000000">&nbsp;ns);<br />
</span><span style="color: #008080">22</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(</span><span style="color: #000000">"</span><span style="color: #000000">倒序:&nbsp;</span><span style="color: #000000">"</span><span style="color: #000000">+</span><span style="color: #000000">&nbsp;ns.descendingSet());<br />
</span><span style="color: #008080">23</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(</span><span style="color: #000000">"</span><span style="color: #000000">第一个对象是:&nbsp;</span><span style="color: #000000">"</span><span style="color: #000000">+</span><span style="color: #000000">ns.first());<br />
</span><span style="color: #008080">24</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(</span><span style="color: #000000">"</span><span style="color: #000000">比4小的对象:&nbsp;</span><span style="color: #000000">"</span><span style="color: #000000">+</span><span style="color: #000000">ns.lower(</span><span style="color: #000000">4</span><span style="color: #000000">));</span><span style="color: #008000">//</span><span style="color: #008000">只返回比N小的第一个对象</span><span style="color: #008000"><br />
</span><span style="color: #008080">25</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(</span><span style="color: #000000">"</span><span style="color: #000000">比2大的对象:&nbsp;</span><span style="color: #000000">"</span><span style="color: #000000">+</span><span style="color: #000000">ns.higher(</span><span style="color: #000000">2</span><span style="color: #000000">));</span><span style="color: #008000">//</span><span style="color: #008000">只返回比N大的第一个对象</span><span style="color: #008000"><br />
</span><span style="color: #008080">26</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;NavigableSet</span><span style="color: #000000">&lt;</span><span style="color: #000000">String</span><span style="color: #000000">&gt;</span><span style="color: #000000">&nbsp;nss&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">new</span><span style="color: #000000">&nbsp;TreeSet</span><span style="color: #000000">&lt;</span><span style="color: #000000">String</span><span style="color: #000000">&gt;</span><span style="color: #000000">();<br />
</span><span style="color: #008080">27</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;nss.add(</span><span style="color: #000000">"</span><span style="color: #000000">a</span><span style="color: #000000">"</span><span style="color: #000000">);<br />
</span><span style="color: #008080">28</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;nss.add(</span><span style="color: #000000">"</span><span style="color: #000000">B</span><span style="color: #000000">"</span><span style="color: #000000">);<br />
</span><span style="color: #008080">29</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;nss.add(</span><span style="color: #000000">"</span><span style="color: #000000">C</span><span style="color: #000000">"</span><span style="color: #000000">);<br />
</span><span style="color: #008080">30</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;nss.add(</span><span style="color: #000000">"</span><span style="color: #000000">d</span><span style="color: #000000">"</span><span style="color: #000000">);<br />
</span><span style="color: #008080">31</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;nss.add(</span><span style="color: #000000">"</span><span style="color: #000000">1</span><span style="color: #000000">"</span><span style="color: #000000">);<br />
</span><span style="color: #008080">32</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;nss.add(</span><span style="color: #000000">"</span><span style="color: #000000">3</span><span style="color: #000000">"</span><span style="color: #000000">);<br />
</span><span style="color: #008080">33</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;nss.add(</span><span style="color: #000000">"</span><span style="color: #000000">3</span><span style="color: #000000">"</span><span style="color: #000000">);<br />
</span><span style="color: #008080">34</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;nss.add(</span><span style="color: #000000">"</span><span style="color: #000000">~</span><span style="color: #000000">"</span><span style="color: #000000">);<br />
</span><span style="color: #008080">35</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;nss.add(</span><span style="color: #000000">"</span><span style="color: #000000">)</span><span style="color: #000000">"</span><span style="color: #000000">);<br />
</span><span style="color: #008080">36</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;nss.add(</span><span style="color: #000000">"</span><span style="color: #000000">abc</span><span style="color: #000000">"</span><span style="color: #000000">);<br />
</span><span style="color: #008080">37</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;nss.add(</span><span style="color: #000000">"</span><span style="color: #000000">aaa</span><span style="color: #000000">"</span><span style="color: #000000">);<br />
</span><span style="color: #008080">38</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(</span><span style="color: #000000">"</span><span style="color: #000000">字符串默认排序:&nbsp;</span><span style="color: #000000">"</span><span style="color: #000000">+</span><span style="color: #000000">nss);<br />
</span><span style="color: #008080">39</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;<br />
</span><span style="color: #008080">40</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;<br />
</span><span style="color: #008080">41</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;}<br />
</span><span style="color: #008080">42</span>&nbsp;<span style="color: #000000">}</span></div>
<br />
<br />
输出<br />
<br />
默认正序: [1, 2, 4, 5, 6, 7, 8, 9, 10]<br />
倒序: [10, 9, 8, 7, 6, 5, 4, 2, 1]<br />
第一个对象是: 1<br />
比4小的对象: 2<br />
比2大的对象: 4<br />
[), 1, 3, B, C, a, aaa, abc, d, ~]<br />
</font>
<img src ="http://www.blogjava.net/smildlzj/aggbug/171479.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/smildlzj/" target="_blank">smildlzj</a> 2007-12-29 12:54 <a href="http://www.blogjava.net/smildlzj/articles/171479.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>用 Apache Derby 进行数据库开发，第 6 部分</title><link>http://www.blogjava.net/smildlzj/articles/163584.html</link><dc:creator>smildlzj</dc:creator><author>smildlzj</author><pubDate>Tue, 27 Nov 2007 16:17:00 GMT</pubDate><guid>http://www.blogjava.net/smildlzj/articles/163584.html</guid><wfw:comment>http://www.blogjava.net/smildlzj/comments/163584.html</wfw:comment><comments>http://www.blogjava.net/smildlzj/articles/163584.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/smildlzj/comments/commentRss/163584.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/smildlzj/services/trackbacks/163584.html</trackback:ping><description><![CDATA[<blockquote>与创建数据库模式和用数据填充表一样，有选择地修改数据是数据库开发人员必备的最重要的技能之一。本文教您如何有选择地删除或更新现有表中的数据以及如何修改现有表的结构。要对更复杂的数据库模式执行数据修改，您将通过数据更新和数据插入操作来学习涉及到标量和表的嵌入式子查找。您还将学习如何使用 Apache Derby 数据库删除和修改复杂模式中的数据。</blockquote><!--start RESERVED FOR FUTURE USE INCLUDE FILES--><!-- include java script once we verify teams wants to use this and it will work on dbcs and cyrillic characters --><!--end RESERVED FOR FUTURE USE INCLUDE FILES-->
<p><a name="N10059"><span class="atitle">简介</span></a></p>
<p>本 <a href="http://www.ibm.com/developerworks/cn/views/opensource/articles.jsp?view_by=search&amp;search_by=%E7%94%A8+Apache+Derby+%E8%BF%9B%E8%A1%8C%E5%BC%80%E5%8F%91+%E2%80%94%E2%80%94+%E5%8F%96%E5%BE%97%E8%8A%82%E8%8A%82%E8%83%9C%E5%88%A9">系列</a> 的前几篇文章已经：</p>
<ul>
    <li>介绍了 Apache Derby 数据库。
    <li>介绍了 <code>ij</code> 工具。
    <li>演示了如何创建数据库模式、设计关系数据库表以及将数据插入表中。
    <li>演示了如何通过编写 SQL 查询提取数据。 </li>
</ul>
<p>尚未介绍的一个重要任务是如何修改现有数据。本文介绍 SQL <code>DELETE</code> 和 <code>UPDATE</code> 语句，您可以使用它们有选择地删除或修改 Apache Derby 数据库中的现有数据。</p>
<p>要进行本文的示例，您需要：</p>
<ol>
    <li>具有可工作的 Apache Derby 数据库安装，本系列的 <a href="http://www.ibm.com/developerworks/cn/opensource/os-ad-trifecta2/index.html">第一篇文章</a> 有介绍。
    <li>熟悉 Apache Derby <code>ij</code> 命令行工具，本系列的 <a href="http://www.ibm.com/developerworks/cn/opensource/os-ad-trifecta3/index.html">第二篇文章</a> 有介绍。
    <li>具有正确初始化的 Bigdog 的 Surf Shop 示例数据库，本系列的 <a href="http://www.ibm.com/developerworks/cn/opensource/os-ad-trifecta5/index.html">第四篇文章</a> 和 <a href="http://www.ibm.com/developerworks/cn/opensource/os-ad-trifecta6/index.html">第五篇文章</a> 有详细介绍。
    <li>熟悉 SQL <code>SELECT</code> 语句的基础知识，本系列的 <a href="http://www.ibm.com/developerworks/cn/opensource/os-ad-trifecta6/index.html">第五篇文章</a> 有介绍。 </li>
</ol>
<p>如果您还不具备这些条件，请确保在继续下文之前完成上述步骤，通过回顾本系列的前几篇文章可以很容易地实现。</p>
<br />
<table cellspacing="0" cellpadding="0" width="100%" border="0">
    <tbody>
        <tr>
            <td><img height="1" alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" width="100%" /><br />
            <img height="6" alt="" src="http://www.ibm.com/i/c.gif" width="8" border="0" /></td>
        </tr>
    </tbody>
</table>
<table class="no-print" cellspacing="0" cellpadding="0" align="right">
    <tbody>
        <tr align="right">
            <td><img height="4" alt="" src="http://www.ibm.com/i/c.gif" width="100%" /><br />
            <table cellspacing="0" cellpadding="0" border="0">
                <tbody>
                    <tr>
                        <td valign="middle"><img height="16" alt="" src="http://www.ibm.com/i/v14/icons/u_bold.gif" width="16" border="0" /><br />
                        </td>
                        <td valign="top" align="right"><a class="fbox" href="http://www.ibm.com/developerworks/cn/opensource/os-ad-trifecta7/index.html#main"><strong>回页首</strong></a></td>
                    </tr>
                </tbody>
            </table>
            </td>
        </tr>
    </tbody>
</table>
<br />
<br />
<p><a name="N100B5"><span class="atitle">删除数据</span></a></p>
<p>本文将介绍的第一个数据修改技术是删除数据。要删除 Apache Derby 数据库中的数据，可以使用 SQL <code>DELETE</code> 语句，它可以删除表中的所有行，也可以删除特定的行子集。可以用于 Apache Derby 数据库的 SQL <code>DELETE</code> 语句的正式语法相当简单，如下所示： </p>
<code>DELETE FROM tableName<br />
[WHERE clause]</code><br />
<br />
<p><code>DELETE</code> 语句从指定表中删除满足可选 <code>WHERE</code> 子句的所有行。如果没有包括任何 <code>WHERE</code> 子句，则删除表中的所有行。为了演示 <code>DELETE</code> 语句的这种用法，创建一个临时表，插入几行，然后全部删除，如 <a href="http://www.ibm.com/developerworks/cn/opensource/os-ad-trifecta7/index.html#list1">清单 1</a> 所示。 </p>
<br />
<a name="list1"><strong>清单 1. 删除行</strong></a><br />
<table cellspacing="0" cellpadding="0" width="100%" border="0">
    <tbody>
        <tr>
            <td class="code-outline">
            <pre class="displaycode">ij&gt; CREATE TABLE bigdog.temp (aValue INT) ;
            0 rows inserted/updated/deleted
            ij&gt; INSERT INTO bigdog.temp VALUES(0), (1), (2), (3) ;
            4 rows inserted/updated/deleted
            ij&gt; SELECT COUNT(*) AS COUNT FROM bigdog.temp ;
            COUNT
            -----------
            4
            1 row selected
            ij&gt; DELETE FROM bigdog.temp ;
            4 rows inserted/updated/deleted
            ij&gt; SELECT COUNT(*) AS COUNT FROM bigdog.temp ;
            COUNT
            -----------
            0
            1 row selected
            ij&gt; DROP TABLE bigdog.temp ;
            0 rows inserted/updated/deleted</pre>
            </td>
        </tr>
    </tbody>
</table>
<br />
<p>本例创建保存整数值的单列临时表。您将四行插入数据库中，然后执行 <code>SELECT</code> 语句以验证新表包含四行。通过使用无约束的 <code>DELETE</code> 语句，将删除临时表中的全部四行，这通过来自 Apache Derby 的消息 <code>4 rows inserted/updated/deleted</code> 和第二个 <code>SELECT</code> 语句来验证，该语句指明临时表包含 0 行。最后，<code>DROP TABLE</code> 语句删除模式中的空表。 </p>
<p>但是，一般地，您不希望删除表中的所有行；而是有选择地删除行。为此，创建一个适当的 <code>WHERE</code> 子句来标识所有相关行。与 <code>DELETE</code> 一起使用的 <code>WHERE</code> 子句的语法与 <a href="http://www.ibm.com/developerworks/cn/opensource/os-ad-trifecta5/">第 4 部分</a> 中讨论的语法一样，该部分提供了完全的 SQL <code>SELECT</code> 语句语法。在 <code>WHERE</code> 子句中构造布尔表达式的基本构建块在那篇文章的表 1 提供，并在本文的 <a href="http://www.ibm.com/developerworks/cn/opensource/os-ad-trifecta7/index.html#list2">清单 2</a> 中演示，在此您将删除至少满足两个条件之一的所有行。</p>
<br />
<a name="list2"><strong>清单 2. 删除所选行</strong></a><br />
<table cellspacing="0" cellpadding="0" width="100%" border="0">
    <tbody>
        <tr>
            <td class="code-outline">
            <pre class="displaycode">ij&gt; DELETE FROM bigdog.products
            WHERE description LIKE '%towel%' OR itemNumber &lt;= 3 ;
            5 rows inserted/updated/deleted
            ij&gt; SELECT itemNumber, description FROM bigdog.products ;
            ITEMNUMBER |DESCRIPTION
            ----------------------------------------------------
            4          |Male bathing suit, blue
            5          |Female bathing suit, one piece, aqua
            6          |Child sand toy set
            9          |Flip-flop
            10         |Open-toed sandal
            5 rows selected</pre>
            </td>
        </tr>
    </tbody>
</table>
<br />
<p>在本例中，<code>DELETE</code> 语句包括了一个标识 5 行的 <code>WHERE</code> 子句，您可以通过 <code>ij</code> 工具由 Apache Derby 返回的帮助消息 <code>5 rows inserted/updated/deleted</code> 中看到。<code>WHERE</code> 子句包含由 <code>OR</code> 操作符联结的两个表达式，这意味着对于特定行，如果任一表达式值为 <code>TRUE</code>，则将删除该行。 </p>
<p>第一个表达式查找产品描述中包含单词 &#8220;towel&#8221; 的所有行。如果回忆本系列前几篇文章（或者在 <code>DELETE</code> 语句之前执行 <code>SELECT</code> 语句），则 <code>bigdog.products</code> 表中有两个 towel，其 <code>itemNumber</code> 列值为 7 和 8。另一个表达式选择 <code>itemNumber</code> 列值小于或等于 3 的所有行。<code>bigdog.products</code> 表的内容最终用一个简单的 <code>SELECT</code> 语句显示，展示了只有原来 10 行中的 5 行保留在表中。 </p>
<p>您还可以包括 <a href="http://www.ibm.com/developerworks/cn/opensource/os-ad-trifecta6/">第 5 部分</a> 中讨论的 SQL 函数以获得对删除行的选择的更多控制，但是本例中没有明确演示这些函数的使用。可用于 <code>DELETE</code> 语句的 <code>WHERE</code> 子句中的相同函数和其他操作符还可以与 <code>UPDATE</code> 语句一起使用，从而有选择地修改表中行的值，如下一节所述。 </p>
<br />
<table cellspacing="0" cellpadding="0" width="100%" border="0">
    <tbody>
        <tr>
            <td><img height="1" alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" width="100%" /><br />
            <img height="6" alt="" src="http://www.ibm.com/i/c.gif" width="8" border="0" /></td>
        </tr>
    </tbody>
</table>
<table class="no-print" cellspacing="0" cellpadding="0" align="right">
    <tbody>
        <tr align="right">
            <td><img height="4" alt="" src="http://www.ibm.com/i/c.gif" width="100%" /><br />
            <table cellspacing="0" cellpadding="0" border="0">
                <tbody>
                    <tr>
                        <td valign="middle"><img height="16" alt="" src="http://www.ibm.com/i/v14/icons/u_bold.gif" width="16" border="0" /><br />
                        </td>
                        <td valign="top" align="right"><a class="fbox" href="http://www.ibm.com/developerworks/cn/opensource/os-ad-trifecta7/index.html#main"><strong>回页首</strong></a></td>
                    </tr>
                </tbody>
            </table>
            </td>
        </tr>
    </tbody>
</table>
<br />
<br />
<p><a name="N10181"><span class="atitle">更新数据</span></a></p>
<p>您需要进行的处理数据的最后一个 SQL 任务是更新表中选定行的特定列值。在某种程度上，SQL <code>UPDATE</code> 语句是 SQL <code>INSERT</code> 和 <code>DELETE</code> 语句的联合，因为您必须选择要修改的行，还必须指定如何修改它们。形式上，<code>UPDATE</code> 语句语法非常简单，因为您必须指定要更新的行集合的新的列值，如 <a href="http://www.ibm.com/developerworks/cn/opensource/os-ad-trifecta7/index.html#list3">清单 3</a> 所示。 </p>
<br />
<a name="list3"><strong>清单 3. SQL UPDATE 语句语法</strong></a><br />
<table cellspacing="0" cellpadding="0" width="100%" border="0">
    <tbody>
        <tr>
            <td class="code-outline">
            <pre class="displaycode">UPDATE tableName
            SET columnName = Value
            [ , columnName = Value} ]*
            [WHERE clause]</pre>
            </td>
        </tr>
    </tbody>
</table>
<br />
<p>如该 SQL 语法所示，SQL <code>UPDATE</code> 语句必须至少具有一个 <code>SET</code> 组件来更新一列，以及一个或多个 <code>SET</code> 组件和一个 <code>WHERE</code> 子句，这些是可选的。如果没有包括 <code>WHERE</code> 子句，则 <code>UPDATE</code> 语句将修改表中所有行的指定列。 </p>
<p>执行 <code>UPDATE</code> 语句相当容易，如 <a href="http://www.ibm.com/developerworks/cn/opensource/os-ad-trifecta7/index.html#list4">清单 4</a> 所示，其中修改了单个行的两列。 </p>
<br />
<a name="list4"><strong>清单 4. 更新所选行</strong></a><br />
<table cellspacing="0" cellpadding="0" width="100%" border="0">
    <tbody>
        <tr>
            <td class="code-outline">
            <pre class="displaycode">ij&gt; SELECT itemNumber, price, stockDate FROM bigdog.products WHERE itemNumber = 6 ;
            ITEMNUMBER |PRICE   |STOCKDATE
            -------------------------------
            6          |9.95    |2006-01-15
            1 row selected
            ij&gt; UPDATE bigdog.products
            SET price = price * 1.25, stockDate = CURRENT_DATE
            WHERE itemNumber = 6 ;
            1 row inserted/updated/deleted
            ij&gt; SELECT itemNumber, price, stockDate FROM bigdog.products WHERE itemNumber = 6 ;
            ITEMNUMBER |PRICE   |STOCKDATE
            -------------------------------
            6          |12.43   |2006-06-20
            1 row selected</pre>
            </td>
        </tr>
    </tbody>
</table>
<br />
<p>本示例在 <code>UPDATE</code> 语句的前后都使用了 <code>SELECT</code> 语句，以证实对目标行的更改。<code>SELECT</code> 语句从 <code>bigdog.products</code> 表选择了单个行（<code>itemNumber</code> 列值为 6 的行）的三列。<code>UPDATE</code> 语句修改该特定行的 <code>price</code> 和 <code>stockDate</code> 列。<code>price</code> 列中的值增加 25%（例如，可能由于货品很抢手），<code>stockDate</code> 列被修改以保存当前日期，通过在 SQL 查询中使用 <code>CURRENT_DATE</code> 内置函数，可以在 Apache Derby 中很容易获得该日期。 </p>
<p>Apache Derby 包括一些内置函数，您可以使用它们获得与当前数据库连接相关的数据。这些内置函数的完整列表如 <a href="http://www.ibm.com/developerworks/cn/opensource/os-ad-trifecta7/index.html#table1">表 1</a> 所示。</p>
<br />
<a name="table1"><strong>表 1. Apache Derby SQL 当前函数</strong></a><br />
<table class="data-table-1" cellspacing="0" cellpadding="0" width="100%" summary="Table using a heading tag for the caption, all columns left-aligned" border="0">
    <tbody>
        <tr>
            <th>函数</th>
            <th>描述</th>
        </tr>
        <tr>
            <td><code>CURRENT_DATE</code></td>
            <td>以合适的 Apache Derby <code>DATE</code> 格式返回当前日期</td>
        </tr>
        <tr>
            <td><code>CURRENT_ISOLATION</code></td>
            <td>以两字符字符串返回当前事务处理隔离级别，这将在后续文章中详细讨论</td>
        </tr>
        <tr>
            <td><code>CURRENT_SCHEMA</code></td>
            <td>以最多 128 个字符的字符串返回模式名称，用于限定未限定的数据库对象名称</td>
        </tr>
        <tr>
            <td><code>CURRENT_TIME</code></td>
            <td>以合适的 Apache Derby <code>TIME</code> 格式返回当前时间</td>
        </tr>
        <tr>
            <td><code>CURRENT_TIMESTAMP</code></td>
            <td>以合适的 Apache Derby <code>TIMESTAMP</code> 格式返回当前时间戳</td>
        </tr>
        <tr>
            <td><code>CURRENT_USER</code></td>
            <td>以最多 128 个字符的字符串返回当前用户的授权标识符，如果没有当前用户，则返回 <code>APP</code></td>
        </tr>
    </tbody>
</table>
<p>上例演示了如何修改单个表中特定行的多个列值。但是有时候，用于选择要更新的行的逻辑比较复杂。例如，假设您需要修改 <code>bigdog.products</code> 表中从 Quiet Beach Industries 中获得的所有对象的价格，Quiet Beach Industries 在 <code>bigdog.vendors</code> 表中 <code>vendorNumber</code> 列的值为 3。为此，您需要使用嵌入式查询，如 <a href="http://www.ibm.com/developerworks/cn/opensource/os-ad-trifecta7/index.html#list5">清单 5</a> 所示。 </p>
<br />
<a name="list5"><strong>清单 5. 使用嵌入式 SELECT 更新行</strong></a><br />
<table cellspacing="0" cellpadding="0" width="100%" border="0">
    <tbody>
        <tr>
            <td class="code-outline">
            <pre class="displaycode">ij&gt; UPDATE bigdog.products
            SET price = price * 1.10, description = 'NEW: ' || description
            WHERE itemNumber IN
            ( SELECT v.itemNumber
            FROM bigdog.products as p, bigdog.vendors as v
            WHERE p.itemNumber = v.itemNumber AND v.vendorNumber = 3 ) ;
            2 rows inserted/updated/deleted
            ij&gt; SELECT * FROM bigdog.products ;
            ITEMNUMBER |PRICE   |STOCKDATE |DESCRIPTION
            ------------------------------------------------------------------------
            4          |29.95   |2006-02-10|Male bathing suit, blue
            5          |49.95   |2006-02-20|Female bathing suit, one piece, aqua
            6          |12.43   |2006-06-20|Child sand toy set
            9          |14.24   |2006-03-12|NEW: Flip-flop
            10         |38.44   |2006-01-24|NEW: Open-toed sandal
            5 rows selected</pre>
            </td>
        </tr>
    </tbody>
</table>
<br />
<p>在本例中，<code>UPDATE</code> 语句修改从 <code>bigdog.vendors</code> 表中 <code>vendorNumber</code> 列值为 3 的供应商获得的所有产品的 <code>price</code> 和 <code>description</code> 列。因为不能在 <code>UPDATE</code> 语句中进行简单联结，所以必须在 <code>WHERE</code> 子句中包括子查询，以提取与来自 Quiet Beach Industries 的产品对应的 <code>itemNumber</code> 行。<code>UPDATE</code> 中的 <code>WHERE</code> 子句使用 <code>IN</code> 操作符选择 <code>itemNumber</code> 列值属于嵌入式子查询所选的值集合的那些行。 </p>
<p>两种查询可以用于 <code>UPDATE</code> 语句的 <code>WHERE</code> 子句中：<em>标量子查询</em> 和<em>表子查询</em>。标量子查询是一种嵌入式查询，返回包含单个列的单个行，本质上就是单个值，该值称为<em>标量</em>。可以使用标量子查询选择将用于 <code>WHERE</code> 子句的表达式中的特定值。例如，<code>itemNumber = (标量子查询)</code> 更新 <code>itemNumber</code> 列值与标量子查询结果匹配的任何行。 </p>
<p>另一方面，表子查询可以返回多个行，这些行通常只有一列。在某些情况下，表子查询可以包含多个列。要使用表子查询，需要使用 SQL 操作符将嵌入式查询与布尔表达式组合在一起。例如，如上一代码清单所示，<code>IN</code> 操作符选择 <code>bigdog.products</code> 表中由 Quiet Beach Industries 生产的所有行。<code>IN</code> 操作符是可以用于表子查询的四个 SQL 操作符之一。全部四个操作符如 <a href="http://www.ibm.com/developerworks/cn/opensource/os-ad-trifecta7/index.html#table2">表 2</a> 所述。 </p>
<br />
<a name="table2"><strong>表 2. Apache Derby SQL 操作符和表子查询</strong></a><br />
<table class="data-table-1" cellspacing="0" cellpadding="0" width="100%" summary="Table using a heading tag for the caption, all columns left-aligned" border="0">
    <tbody>
        <tr>
            <th>操作符</th>
            <th>示例</th>
            <th>描述</th>
        </tr>
        <tr>
            <td><code>IN</code></td>
            <td><code>itemNumber IN（表子查询）</code></td>
            <td>如果表达式的值在表子查询中，则返回 <code>TRUE</code>，该表子查询只能返回单个列。可以包括 <code>NOT</code> 操作符，如 <code>NOT IN</code>，以仅选择不在表查询中的行。</td>
        </tr>
        <tr>
            <td><code>EXISTS</code></td>
            <td><code>EXISTS（表子查询）</code></td>
            <td>如果表子查询返回任何行，则返回 <code>TRUE</code>，如果没有选择任何行，则返回 <code>FALSE</code>。这意味着，取决于表子查询选择的行数，将修改所有行或不修改任何行。可以包括 <code>NOT</code> 操作符以反转该规则。</td>
        </tr>
        <tr>
            <td><code>ALL</code></td>
            <td><code>itemNumber = ALL（表子查询）</code></td>
            <td>称为<em>量化比较</em>，因为 <code>ALL</code> 关键字修改比较操作符（<code>=</code>、<code>&lt;</code>、<code>&gt;</code>、<code>&lt;=</code>、<code>&gt;=</code> 或 <code>&lt;&gt;</code> 之一），所以仅当对所有行都为真时，结果才为 <code>TRUE</code>。该表子查询可以返回多个行，但它们必须只有一个列。</td>
        </tr>
        <tr>
            <td><code>ANY</code></td>
            <td><code>itemNumber = ANY （表子查询）</code></td>
            <td>另一个量化比较，但是在这个查询中，如果它对于任一行为真，则结果为 <code>TRUE</code>。<code>SOME</code> 可以用作 <code>ANY</code> 的同义词。该表子查询可以返回多个行，但它们必须只有一个列。</td>
        </tr>
    </tbody>
</table>
<p>通过使用 <a href="http://www.ibm.com/developerworks/cn/opensource/os-ad-trifecta7/index.html#table2">表 2</a> 中的信息，应该看到如果您重新编写 <a href="http://www.ibm.com/developerworks/cn/opensource/os-ad-trifecta7/index.html#list4">清单 4</a> 中 <code>UPDATE</code> 语句中的 <code>WHERE</code> 子句，以使用量化比较和相同的表子查询 <code>WHERE itemNumber = ANY (...)</code>，您将获得相同的结果。如果使用 <code>ALL</code> 操作符和相同的表子查询，则不更新任何行，因为 <code>bigdog.products</code> 表中的所有 <code>itemNumber</code> 值不在表查询中。另一方面，如果使用 <code>EXISTS</code> 操作符，则将修改所有行，因为至少有一个 <code>itemNumber</code> 值存在于表子查询中。 </p>
<br />
<table cellspacing="0" cellpadding="0" width="100%" border="0">
    <tbody>
        <tr>
            <td><img height="1" alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" width="100%" /><br />
            <img height="6" alt="" src="http://www.ibm.com/i/c.gif" width="8" border="0" /></td>
        </tr>
    </tbody>
</table>
<table class="no-print" cellspacing="0" cellpadding="0" align="right">
    <tbody>
        <tr align="right">
            <td><img height="4" alt="" src="http://www.ibm.com/i/c.gif" width="100%" /><br />
            <table cellspacing="0" cellpadding="0" border="0">
                <tbody>
                    <tr>
                        <td valign="middle"><img height="16" alt="" src="http://www.ibm.com/i/v14/icons/u_bold.gif" width="16" border="0" /><br />
                        </td>
                        <td valign="top" align="right"><a class="fbox" href="http://www.ibm.com/developerworks/cn/opensource/os-ad-trifecta7/index.html#main"><strong>回页首</strong></a></td>
                    </tr>
                </tbody>
            </table>
            </td>
        </tr>
    </tbody>
</table>
<br />
<br />
<p><a name="N103C8"><span class="atitle">修改表模式</span></a></p>
<p>上一节讨论了修改表中现有的数据。还可以修改数据库表的结构或模式。这可以采用添加列、更改列的数据类型、添加约束或者甚至删除列的方式来实现。 该过程并不简单，所以当您开始设计模式时一定要认真。如果不需要修改表的结构，则需要使用临时表，如 <a href="http://www.ibm.com/developerworks/cn/opensource/os-ad-trifecta7/index.html#list6">清单 6 </a>所示。 </p>
<br />
<a name="list6"><strong>清单 6. 更新表</strong></a><br />
<table cellspacing="0" cellpadding="0" width="100%" border="0">
    <tbody>
        <tr>
            <td class="code-outline">
            <pre class="displaycode">ij&gt; CREATE TABLE bigdog.newProducts (
            itemNumber INT NOT NULL,
            price DECIMAL(5, 2),
            stockDate DATE,
            count INT NOT NULL DEFAULT 0,
            description VARCHAR(40)
            ) ;
            0 rows inserted/updated/deleted
            ij&gt; INSERT INTO bigdog.newProducts(itemNumber, price, stockDate, description)
            SELECT itemNumber, price, stockDate, description FROM bigdog.products ;
            5 rows inserted/updated/deleted
            ij&gt; DROP TABLE bigdog.products ;
            0 rows inserted/updated/deleted
            ij&gt; RENAME TABLE bigdog.newProducts TO products ;
            0 rows inserted/updated/deleted
            ij&gt; SELECT * FROM bigdog.products ;
            ITEMNUMBER |PRICE   |STOCKDATE |COUNT      |DESCRIPTION
            ------------------------------------------------------------------------------------
            4          |29.95   |2006-02-10|0          |Male bathing suit, blue
            5          |49.95   |2006-02-20|0          |Female bathing suit, one piece, aqua
            6          |12.43   |2006-06-20|0          |Child sand toy set
            9          |14.24   |2006-03-12|0          |NEW: Flip-flop
            10         |38.44   |2006-01-24|0          |NEW: Open-toed sandal
            5 rows selected</pre>
            </td>
        </tr>
    </tbody>
</table>
<br />
<p>如本例所示，要修改表，在本例中是将一个新列 <code>count</code> 添加到 <code>bigdog.products</code> 表中，首先要创建一个具有需要的正确模式的表。本例需要包括列约束 <code>NOT NULL</code> 使之始终具有有效的值，并通过使用列约束 <code>DEFAULT 0</code> 为 <code>count</code> 列分配默认值 0。注意如何通过将列顺序列出来合并多列约束。 </p>
<p>下一步是将现有数据从原始表复制到新表中。可以通过使用 SQL <code>INSERT</code> 语句来实现，该语句使用一个子查询来获得要插入的值。这是一种功能强大的技术，允许您很容易地将现有表的全部或部分复制到第二个表中。 </p>
<p>创建新表并复制了合适的数据之后，通过使用 SQL <code>DROP TABLE</code> 语句删除旧表，并通过使用 SQL <code>RENAME TABLE</code> 语句将新表重命名为原来的名称。重命名操作十分简单：将 <em>oldTableName</em> 重命名为 <em>newTableName</em>，但不为新表名提供模式名称，因为 <code>RENAME</code> 操作不能在不同的数据模式间移动表。本例最后执行 <code>SELECT</code> 语句以显示新 <code>bigdog.products</code> 表的模式和内容。可以看到，新表具有 5 列，<code>count</code> 列始终为 0。这时，真正的应用程序将通过执行必要的 SQL <code>UPDATE</code> 语句来适当修改 <code>count</code> 列。 </p>
<br />
<table cellspacing="0" cellpadding="0" width="100%" border="0">
    <tbody>
        <tr>
            <td><img height="1" alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" width="100%" /><br />
            <img height="6" alt="" src="http://www.ibm.com/i/c.gif" width="8" border="0" /></td>
        </tr>
    </tbody>
</table>
<table class="no-print" cellspacing="0" cellpadding="0" align="right">
    <tbody>
        <tr align="right">
            <td><img height="4" alt="" src="http://www.ibm.com/i/c.gif" width="100%" /><br />
            <table cellspacing="0" cellpadding="0" border="0">
                <tbody>
                    <tr>
                        <td valign="middle"><img height="16" alt="" src="http://www.ibm.com/i/v14/icons/u_bold.gif" width="16" border="0" /><br />
                        </td>
                        <td valign="top" align="right"><a class="fbox" href="http://www.ibm.com/developerworks/cn/opensource/os-ad-trifecta7/index.html#main"><strong>回页首</strong></a></td>
                    </tr>
                </tbody>
            </table>
            </td>
        </tr>
    </tbody>
</table>
<br />
<br />
<p><a name="N10426"><span class="atitle">结束语</span></a></p>
<p>本文专门介绍修改 Apache Derby 数据库中的数据。讨论的第一种数据修改技术是数据删除，这通过使用 SQL <code>DELETE</code> 语句来执行。然后使用 SQL <code>UPDATE</code> 语句来修改表中选定行的列值。最后，使用临时表来修改现有数据表的结果。本文还演示了如何通过使用嵌入式子查询来修改比较复杂的数据库模式。下一篇文章将介绍其他一些高级的数据库主题，之后本系列将开始讨论如何从 Java 应用程序连接到 Apache Derby 数据库。</p>
<img src ="http://www.blogjava.net/smildlzj/aggbug/163584.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/smildlzj/" target="_blank">smildlzj</a> 2007-11-28 00:17 <a href="http://www.blogjava.net/smildlzj/articles/163584.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>用 Apache Derby 进行数据库开发，第 3 部分</title><link>http://www.blogjava.net/smildlzj/articles/163575.html</link><dc:creator>smildlzj</dc:creator><author>smildlzj</author><pubDate>Tue, 27 Nov 2007 15:39:00 GMT</pubDate><guid>http://www.blogjava.net/smildlzj/articles/163575.html</guid><wfw:comment>http://www.blogjava.net/smildlzj/comments/163575.html</wfw:comment><comments>http://www.blogjava.net/smildlzj/articles/163575.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/smildlzj/comments/commentRss/163575.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/smildlzj/services/trackbacks/163575.html</trackback:ping><description><![CDATA[<blockquote>学习如何创建自文档化 SQL 命令文件，通过将 SQL 命令与有用的注释一起放置在文本文件中，可以根据需要执行任意多次。介绍 SQL 脚本文件的基本原理之后，本文展示了三种执行脚本文件的方法。然后您将回顾使用 SQL <code>INSERT</code> 语句将数据插入表中的基本原理，其中包括查看使用不同方式插入 10 个新行的示例。最后，本文展示了一个脚本，该脚本自动化该 <code>INSERT</code> 操作并显示新插入的数据以供验证。</blockquote><!--start RESERVED FOR FUTURE USE INCLUDE FILES--><!-- include java script once we verify teams wants to use this and it will work on dbcs and cyrillic characters --><!--end RESERVED FOR FUTURE USE INCLUDE FILES-->
<p><a name="N1006E"><span class="atitle">SQL 脚本</span></a></p>
<p>在本系列的上一篇文章 &#8220;<a href="http://www.ibm.com/developerworks/cn/opensource/os-ad-trifecta3/">用 Apache Derby 进行数据库开发，第 2 部分：模式</a>&#8221;（2006 年 4 月），在 <code>ij</code> 工具的提示符处直接执行 SQL 命令。通过使用 <code>ij</code> 工具，可以简单地用不同的 SQL 或 Derby 命令进行试验。但是，通常您将需要执行多个复杂的命令。为了简化调试一组复杂的 SQL 命令，将其写入文本文件中然后一次执行文本文件中的所有命令通常更加容易。该操作被称为<em>运行 SQL 脚本</em>，可以通过使用 Apache Derby 很容易地实现该操作。通过将 SQL 命令放置在脚本文件中，您将获得能够根据需要多次执行命令的附加好处。</p>
<p>脚本文件不难使用，如 <a href="http://www.ibm.com/developerworks/cn/opensource/os-ad-trifecta4/#list1">清单 1</a> 所示的第一个 Derby SQL 脚本示例。</p>
<br />
<a name="list1"><strong>清单 1. 第一个 Derby SQL 脚本</strong></a><br />
<table cellspacing="0" cellpadding="0" width="100%" border="0">
    <tbody>
        <tr>
            <td class="code-outline">
            <pre class="displaycode">-- Ignore the database not created warning if present
            connect 'jdbc:derby:test;create=true' ;
            -- First delete the tables if they exist.
            -- Ignore the table does not exist error if present
            DROP TABLE bigdog.products ;
            DROP TABLE bigdog.vendors ;
            -- CREATE the products table for bigdog's Surf Shop
            CREATE TABLE bigdog.products (
            itemNumber INT NOT NULL,
            price DECIMAL(5, 2),
            stockDate DATE,
            description VARCHAR(128)
            ) ;
            -- CREATE the products table for bigdog's Surf Shop
            CREATE TABLE bigdog.vendors (
            itemNumber INT NOT NULL,
            vendornumber INT NOT NULL,
            vendorName CHAR(64)
            ) ;
            exit ;
            </pre>
            </td>
        </tr>
    </tbody>
</table>
<br />
<p><a href="http://www.ibm.com/developerworks/cn/opensource/os-ad-trifecta4/#list1">清单 1</a> 所示的脚本重新创建了本系列上一篇文章中演示的 <code>bigdog</code> 模式和两个表（<code>products</code> 和 <code>vendors</code>）。如果不清楚其中任何一个概念，在继续本文之前您应该返回并 <a href="http://www.ibm.com/developerworks/cn/opensource/os-ad-trifecta3/">阅读该文章</a>。因为本文将介绍将数据插入表的基本原理，所以您首先需要创建准备接受新数据的表。 </p>
<table cellspacing="0" cellpadding="0" width="40%" align="right" border="0">
    <tbody>
        <tr>
            <td width="10"><img height="1" alt="" src="http://www.ibm.com/i/c.gif" width="10" /></td>
            <td>
            <table cellspacing="0" cellpadding="5" width="100%" border="1">
                <tbody>
                    <tr>
                        <td bgcolor="#eeeeee"><a name="scriptfile"><strong>编辑 Derby SQL 脚本</strong></a><br />
                        脚本文件只是一种包含可以从 Apache Derby <code>ij</code> 工具直接运行的 SQL 命令和 Apache Derby 命令的组合的文本文件。脚本文件简化了 Apache Derby 数据库的开发和维护，并提供了一种用于构建数据库的自文档化技术。您应该将这些文件存储为 ASCII 文本文件，而非 RTF 文件（或其他任何格式），以防止文本编码错误。一些文本应用程序（比如 Microsoft&#174; Windows&#174; 系统中的写字板）可能试图将文件自动保存为富文本文件。一定要小心这一点，否则可能在尝试执行脚本文件时出现问题。 </td>
                    </tr>
                </tbody>
            </table>
            </td>
        </tr>
    </tbody>
</table>
<p>无需将用于创建表的 SQL 命令直接输入到 Derby <code>ij</code> 工具中，您可以将其放入文本文件中，并让 <code>ij</code> 工具直接运行文件中的命令。本文包括一个 .zip 文件（参阅 <a href="http://www.ibm.com/developerworks/cn/opensource/os-ad-trifecta4/#download">下载</a> 一节以访问该文件），其中包含两个脚本文件；一个是 derby.create.sql，如 <a href="http://www.ibm.com/developerworks/cn/opensource/os-ad-trifecta4/#list1">清单 1</a> 所示。因为本文将逐步介绍该脚本文件中的代码行，所以您既可以参照 <a href="http://www.ibm.com/developerworks/cn/opensource/os-ad-trifecta4/#list1">清单 1</a> 所示的代码，也可以用您偏爱的文本编辑器打开该脚本文件。 </p>
<p>该脚本文件包括了用两个破折号 (<code>--</code>) 开头的几行。这些行是 SQL 注释；您应该使用它们来提供脚本文件中每个主要组件的用途的基本描述。 脚本中的第一个实际命令是 Derby <code>connect</code> 命令，它告诉 <code>ij</code> 工具连接 <code>test</code> 数据库，必要的话要先创建数据库。下一个命令是 SQL <code>DROP</code> 语句，它删除 <code>bigdog</code> 模式中的产品和供应商表。如果表不存在（当数据库刚创建时就会出现这种情况），将显示一条错误消息；但前面的 SQL 注释指明，您可以安全地忽略这些消息。 </p>
<p>如果存在的话，首先放弃这些表，以便您可以用所需的正确的列定义创建新表。后两条 SQL 语句就执行该操作，在 <code>bigdog</code> 模式中创建产品和供应商表。脚本以 <code>exit</code> 命令结束，终止了与数据库的连接，并允许 <code>ij</code> 工具优雅地退出。下一步将学习如何执行 Derby 脚本文件。</p>
<p><a name="N10100"><span class="smalltitle">在 ij 中运行脚本</span></a></p>
<p>脚本文件仅在可用于执行文件中列出的命令时才有用。要执行 SQL 脚本文件中的命令，最简单的方法是从 <code>ij</code> 工具中运行脚本文件。但是，在可以运行之前，需要创建一个测试目录并展开 derby4.zip 文件，该文件可在本文下载（参阅 <a href="http://www.ibm.com/developerworks/cn/opensource/os-ad-trifecta4/#download">下载</a> 一节）。该过程如 <a href="http://www.ibm.com/developerworks/cn/opensource/os-ad-trifecta4/#list2">清单 2</a> 所示。 </p>
<br />
<a name="list2"><strong>清单 2. 在 ij 中运行 SQL 脚本</strong></a><br />
<table cellspacing="0" cellpadding="0" width="100%" border="0">
    <tbody>
        <tr>
            <td class="code-outline">
            <pre class="displaycode">rb$ mkdir test
            rb$ cp derby4.zip test/
            rb$ cd test/
            rb$ unzip derby4.zip
            Archive:  derby4.zip
            inflating: derby.create.sql
            inflating: derby.insert.sql
            rb$ ls
            derby.create.sql      derby.insert.sql      derby4.zip
            rb$ java org.apache.derby.tools.ij
            ij version 10.1
            ij&gt; run 'derby.create.sql' ;
            ij&gt; -- Ignore the database not created warning if present
            connect 'jdbc:derby:test;create=true' ;
            ij&gt; -- First delete the tables if they exist.
            -- Ignore the table does not exist error if present
            DROP TABLE bigdog.products ;
            ERROR 42Y07: Schema 'BIGDOG' does not exist
            ij&gt; DROP TABLE bigdog.vendors ;
            ERROR 42Y07: Schema 'BIGDOG' does not exist
            ij&gt; -- CREATE the products table for Bigdog's Surf Shop
            CREATE TABLE bigdog.products (
            itemNumber INT NOT NULL,
            price DECIMAL(5, 2),
            stockDate DATE,
            description VARCHAR(128)
            ) ;
            0 rows inserted/updated/deleted
            ij&gt; -- CREATE the products table for Bigdog's Surf Shop
            CREATE TABLE bigdog.vendors (
            itemNumber INT NOT NULL,
            vendornumber INT NOT NULL,
            vendorName CHAR(64)
            ) ;
            0 rows inserted/updated/deleted
            ij&gt; exit ;
            </pre>
            </td>
        </tr>
    </tbody>
</table>
<br />
<p>虽然 <a href="http://www.ibm.com/developerworks/cn/opensource/os-ad-trifecta4/#list2">清单 2</a> 似乎对于执行 Derby 脚本有些冗长，但过程十分简单。该示例假设您具有开放的终端（或Windows Command 进程窗口，但要注意，本例中的一些步骤是特定于 UNIX&#174; 的），并且您已经更改到保存包含本文提供的 <a href="http://www.ibm.com/developerworks/cn/opensource/os-ad-trifecta4/#download">两个脚本文件</a> 的 derby4.zip 文件的目录。要最小化任何错误的几率，首先创建一个新目录，将 derby4.zip 文件复制到新目录中，并更改到这个新目录。然后展开示例 .zip 文件。如目录清单所示，现在您在新目录中具有三个文件：derby4.zip、derby.create.sql 和 derby.insert.sql。现在，您将只使用 <em>create</em> 脚本文件； <em>insert</em> 脚本文件将在本文的最后使用。 </p>
<table cellspacing="0" cellpadding="0" width="40%" align="right" border="0">
    <tbody>
        <tr>
            <td width="10"><img height="1" alt="" src="http://www.ibm.com/i/c.gif" width="10" /></td>
            <td>
            <table cellspacing="0" cellpadding="5" width="100%" border="1">
                <tbody>
                    <tr>
                        <td bgcolor="#eeeeee"><a name="scriptfile"><strong>如果出问题怎么办？</strong></a><br />
                        有时候，不管您怎么努力，事情不会总是如您所愿。如果不能安全地执行 derby.create.sql 脚本，有许多可能性需要检查：
                        <ul>
                            <li>确保 Derby <code>ij</code> 工具正确启动。若非如此，您可能遇到 <code>CLASSPATH</code> 工具问题。
                            <li>确保具有创建新数据库的空闲磁盘空间。
                            <li>确保在试图执行脚本文件的目录中具有正确的权限（读取脚本文件和创建新数据库）。
                            <li>确保脚本文件是简单的 ASCII 文本文件。 </li>
                        </ul>
                        如果全都不是，则检查最新的 Derby 文档，该文档可从 Apache Derby Web 站点（参阅 <a href="http://www.ibm.com/developerworks/cn/opensource/os-ad-trifecta4/#resources">参考资料</a> 一节中的链接）上免费获得，或在 Derby 邮件列表中询问您的问题。 </td>
                    </tr>
                </tbody>
            </table>
            </td>
        </tr>
    </tbody>
</table>
<p><a href="http://www.ibm.com/developerworks/cn/opensource/os-ad-trifecta4/#list2">清单 2</a> 的其余部分展示如何从 Derby <code>ij</code> 工具中执行 derby.create.sql 脚本文件。 首先启动 <code>ij</code> 工具。如果启动时出现问题，您可能需要回顾 <a href="http://www.ibm.com/developerworks/cn/opensource/os-ad-trifecta1/">本系列第一篇文章</a> 中提供的 Derby 安装验证步骤。看到 <code>ij&gt;</code> 提示之后，就可以运行合适的脚本文件了。通过使用 <code>run</code> 命令可实现该操作，该命令接受单个参数：单引号括起的脚本文件名。</p>
<p>当该脚本执行时，您可能会看到新 <code>ij&gt;</code> 提示、命令和警告或错误消息的组合。这种显示可能有些笨拙，但 <code>run</code> 命令会执行您的脚本文件，就像您直接将命令键入 <code>ij</code> 工具中一样。最后，处理 <code>exit</code> 命令，脚本完成，关闭 <code>ij</code> 工具。如果第一个脚本执行的输出与 <a href="http://www.ibm.com/developerworks/cn/opensource/os-ad-trifecta4/#list2">清单 2</a> 所示的相匹配，那么恭喜您了。您现在已经有了一个带有两个可以保存数据的新表的新测试数据库了。 </p>
<p>虽然从 <code>ij</code> 工具中执行脚本十分有效，但是有时候进一步自动化该过程会更加容易。下一节将讨论如何从命令行直接执行 Derby 脚本文件。 </p>
<p><a name="N10191"><span class="smalltitle">从命令行运行脚本</span></a></p>
<p>本节介绍从命令行运行脚本的两种方法。第一种方法如 <a href="http://www.ibm.com/developerworks/cn/opensource/os-ad-trifecta4/#list3">清单 3</a> 所示。 </p>
<br />
<a name="list3"><strong>清单 3. 从命令行运行 SQL 脚本</strong></a><br />
<table cellspacing="0" cellpadding="0" width="100%" border="0">
    <tbody>
        <tr>
            <td class="code-outline">
            <pre class="displaycode">rb$ java org.apache.derby.tools.ij derby.create.sql
            ij version 10.1
            ij&gt; -- Ignore the database not created warning if present
            connect 'jdbc:derby:test;create=true' ;
            WARNING 01J01: Database 'test' not created, connection made to existing database instead.
            ij&gt; -- First delete the tables if they exist.
            -- Ignore the table does not exist error if present
            DROP TABLE bigdog.products ;
            0 rows inserted/updated/deleted
            ij&gt; DROP TABLE bigdog.vendors ;
            0 rows inserted/updated/deleted
            ij&gt; -- CREATE the products table for Bigdog's Surf Shop
            CREATE TABLE bigdog.products (
            itemNumber INT NOT NULL,
            price DECIMAL(5, 2),
            stockDate DATE,
            description VARCHAR(128)
            ) ;
            0 rows inserted/updated/deleted
            ij&gt; -- CREATE the products table for Bigdog's Surf Shop
            CREATE TABLE bigdog.vendors (
            itemNumber INT NOT NULL,
            vendornumber INT NOT NULL,
            vendorName CHAR(64)
            ) ;
            0 rows inserted/updated/deleted
            ij&gt; exit ;
            </pre>
            </td>
        </tr>
    </tbody>
</table>
<br />
<p><a href="http://www.ibm.com/developerworks/cn/opensource/os-ad-trifecta4/#list3">清单 3</a> 展示了直接从命令行执行脚本文件的第一种方法。在这种情况下，提供脚本文件名作为 <code>ij</code> 工具的命令行参数。脚本文件中的行像以前一样读取，并顺序处理。如果首先从 <code>ij</code> 工具中直接执行 derby.create.sql 文件，现在在命令行运行相同目录中的同一脚本文件，您应该会看到类似于 <a href="http://www.ibm.com/developerworks/cn/opensource/os-ad-trifecta4/#list3">清单 3</a> 中的输出（一切都在清单中第一行之后）。如上所示，您收到一条警告消息，指明测试数据库未创建，因为它已经存在。但是，这次您不会收到指明不能放弃两个表的错误消息，因为您已经创建了它们（如 <a href="http://www.ibm.com/developerworks/cn/opensource/os-ad-trifecta4/#list2">清单 2</a> 所示）。在放弃产品和供应商表之后，您重新创建它们，脚本退出。 </p>
<p>还有另一种方法来运行 Derby 脚本：重定向 <code>ij</code> 工具的标准输入以从脚本文件中读取。在基于 UNIX 的操作系统中，通过使用适合您的 shell 的 STDIN 重定向字符最容易实现了，比如为 Bash shell 使用小于号 (<code>&lt;</code>)。这种方法在 <a href="http://www.ibm.com/developerworks/cn/opensource/os-ad-trifecta4/#list4">清单 4</a> 中展示，具有减少屏幕上显示的输出量的好处。 </p>
<br />
<a name="list4"><strong>清单 4. 从命令行运行 SQL 脚本（第 2 部分）</strong></a><br />
<table cellspacing="0" cellpadding="0" width="100%" border="0">
    <tbody>
        <tr>
            <td class="code-outline">
            <pre class="displaycode">rb$ java org.apache.derby.tools.ij &lt; derby.create.sql
            ij version 10.1
            ij&gt; WARNING 01J01: Database 'test' not created, connection made to existing database instead.
            <span style="margin-top: 0px; font-size: 11px; margin-bottom: 0px; color: #ff0000; font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace">|-------- XML error:  The previous line is longer than the max of 90 characters ---------|</span>
            ij&gt; 0 rows inserted/updated/deleted
            ij&gt; 0 rows inserted/updated/deleted
            ij&gt; 0 rows inserted/updated/deleted
            ij&gt; 0 rows inserted/updated/deleted
            ij&gt;
            rb$
            </pre>
            </td>
        </tr>
    </tbody>
</table>
<br />
<p>在 <a href="http://www.ibm.com/developerworks/cn/opensource/os-ad-trifecta4/#list4">清单 4</a> 中可以看到，当您通过重定向 <code>ij</code> 工具的标准输入执行脚本时，惟一显示的文本是来自 <code>ij</code> 工具的消息，其中包括 <code>0 rows inserted/updated/deleted</code> 等信息消息或警告和错误消息。如果想要消除这些消息，可以重定向 <code>ij</code> 工具的标准输出和标准错误。例如，如果正在 Bash shell 中工作，则可以使用 <br />
<br />
<code>java org.apache.derby.tools.ij &lt; derby.create.sql &gt; derby.create.out 2&gt; derby.create.err</code> <br />
<br />
实现这一点，它运行 derby.create.sql 脚本文件，将输出消息保存到 <code>derby.create.out</code> 中，并将所有 <code>ij</code> 错误消息保存到 <code>derby.create.err</code> 中。 </p>
<p>现在您将关注使用 Apache Derby 将数据插入表的过程。要继续进行，您需要一个 Derby 数据库，它必须具有可用的产品表。如果您还未实现此步骤，您需要执行 derby.create.sql 脚本文件。 </p>
<br />
<table cellspacing="0" cellpadding="0" width="100%" border="0">
    <tbody>
        <tr>
            <td><img height="1" alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" width="100%" /><br />
            <img height="6" alt="" src="http://www.ibm.com/i/c.gif" width="8" border="0" /></td>
        </tr>
    </tbody>
</table>
<table class="no-print" cellspacing="0" cellpadding="0" align="right">
    <tbody>
        <tr align="right">
            <td><img height="4" alt="" src="http://www.ibm.com/i/c.gif" width="100%" /><br />
            <table cellspacing="0" cellpadding="0" border="0">
                <tbody>
                    <tr>
                        <td valign="middle"><img height="16" alt="" src="http://www.ibm.com/i/v14/icons/u_bold.gif" width="16" border="0" /><br />
                        </td>
                        <td valign="top" align="right"><a class="fbox" href="http://www.ibm.com/developerworks/cn/opensource/os-ad-trifecta4/#main"><strong>回页首</strong></a></td>
                    </tr>
                </tbody>
            </table>
            </td>
        </tr>
    </tbody>
</table>
<br />
<br />
<p><a name="N10207"><span class="atitle">在 Apache Derby 中插入数据</span></a></p>
<p>构建数据库应用程序时最重要的任务之一是将数据插入到数据库中。这与数据库软件的好坏无关，如果将坏数据放入数据库中，其他一切都不重要了。有许多方法可以将数据插入数据库中，但下文将主要使用 SQL <code>INSERT</code> 语句将数据插入 Apache Derby 数据库中。 </p>
<p><a name="N10215"><span class="smalltitle">SQL INSERT 语句</span></a></p>
<p>在使用 SQL <code>INSERT</code> 语句将数据插入 Apache Derby 数据库中之前，必须知道如果正确地使用该语句。<a href="http://www.ibm.com/developerworks/cn/opensource/os-ad-trifecta4/#list5">清单 5</a> 提供了 Apache Derby 中 SQL <code>INSERT</code> 语句的完整语法。 </p>
<br />
<a name="list5"><strong>清单 5. SQL INSERT 语法</strong></a><br />
<table cellspacing="0" cellpadding="0" width="100%" border="0">
    <tbody>
        <tr>
            <td class="code-outline">
            <pre class="displaycode">INSERT INTO table-Name
            [ (Simple-column-Name [ , Simple-column-Name]* ) ]
            Expression
            </pre>
            </td>
        </tr>
    </tbody>
</table>
<br />
<p>该语法应该比较熟悉。如本系列的 <a href="http://www.ibm.com/developerworks/cn/opensource/os-ad-trifecta3/">上一篇文章</a> 所述，方括号 (<code>[</code> <code>]</code>) 包括可选参数。其用途不是立即清楚的惟一组件是 <code>Expression</code>；但这个简单的短语能够有多复杂呢？当然，外表可能会蒙蔽人；<code>Expression</code> 词可以扩展为下列四个不同的结构之一：</p>
<ul>
    <li>单行 <code>VALUES</code> 列表
    <li>多行 <code>VALUES</code> 列表
    <li><code>SELECT</code> 表达式
    <li><code>UNION</code> 表达式 </li>
</ul>
<p>其中，最后两个超出了本文范围，将在后续文章中详细介绍。前两个相似；惟一的区别在于第一种形式将一行插入表中，而后一种形式将多行插入表中。 </p>
<p>可以使用 SQL <code>INSERT</code> 语句的可选部分指定要插入到表中的值的列顺序。默认情况下，数据插入到表中的列顺序与创建表时列的列出顺序相同。有时候您希望更改这种顺序或可能希望只为具有 <code>NOT NULL</code> 约束的列指定值。通过在 SQL <code>INSERT</code> 语句中显式列出列，您将获得对操作的更多控制，并可以更容易地处理这些特定的用例。 </p>
<p>SQL <code>VALUES</code> 表达式的语法相当简单，如 <a href="http://www.ibm.com/developerworks/cn/opensource/os-ad-trifecta4/#list6">清单 6</a> 所示。 </p>
<br />
<a name="list6"><strong>清单 6. SQL VALUES 语法</strong></a><br />
<table cellspacing="0" cellpadding="0" width="100%" border="0">
    <tbody>
        <tr>
            <td class="code-outline">
            <pre class="displaycode">{
            VALUES ( Value {, Value }* )
            [ , ( Value {, Value }* ) ]* |
            VALUES Value [ , Value ]*
            }
            </pre>
            </td>
        </tr>
    </tbody>
</table>
<br />
<p>该语法首先显示多行格式，然后是单行格式（记住，竖线字符 <code>|</code> 表示<em>或者</em>，星号字符 <code>*</code> 表示一个或多个）。<code>value</code> 词表示想要插入特定列的值。要将数据插入多列，必须将一行的数据括在逗号分隔的括号内。 </p>
<p>下面两节展示要实现的语法示例。 </p>
<p><a name="N102A4"><span class="smalltitle">使用 SQL 插入数据</span></a></p>
<p>如 <a href="http://www.ibm.com/developerworks/cn/opensource/os-ad-trifecta4/#list7">清单 7</a> 所示，要将数据插入表中，首先需要启动 <code>ij</code> 工具并连接数据库。记住，要将数据插入表中，表必须存在。如果还没有表的话，则执行本文之前所述的用于创建表的脚本。</p>
<br />
<a name="list7"><strong>清单 7. 插入单行</strong></a><br />
<table cellspacing="0" cellpadding="0" width="100%" border="0">
    <tbody>
        <tr>
            <td class="code-outline">
            <pre class="displaycode">rb$ java org.apache.derby.tools.ij
            ij version 10.1
            ij&gt; connect 'jdbc:derby:test' ;
            ij&gt; INSERT INTO bigdog.products
            VALUES(1, 19.95, '2006-03-31', 'Hooded sweatshirt') ;
            1 row inserted/updated/deleted
            ij&gt; INSERT INTO bigdog.products(itemNumber, price, stockDate, description)
            VALUES(2, 99.99, '2006-03-29', 'Beach umbrella') ;
            1 row inserted/updated/deleted
            ij&gt; INSERT INTO bigdog.products(itemNumber, price, stockDate)
            VALUES(3, 0.99, '2006-02-28') ;
            1 row inserted/updated/deleted
            ij&gt; exit ;
            </pre>
            </td>
        </tr>
    </tbody>
</table>
<br />
<p>本例展示了对 <code>bigdog.products</code> 表的三个单行插入。第一个 SQL <code>INSERT</code> 语句没有提供列列表；它插入 <code>itemNumber</code>、<code>price</code>、<code>stockDate</code> 和 <code>description</code>。注意，插入到 <code>stockDate</code> 和 <code>description</code> 列的值括在单引号字符中。<code>description</code> 列是长度可变的字符串，所以它预计是一个字符串（通过将字符数据括在单引号中指明）。另一方面，<code>stockDate</code> 列是一个日期列；它需要您将日期括在单引号中以正确解析出正确的日、月和年信息。（有关 SQL <code>INSERT</code> 操作期间数据类型格式的更多指南，请阅读联机文档或参阅本系列的 <a href="http://www.ibm.com/developerworks/cn/opensource/os-ad-trifecta3/">上一篇文章</a>。） </p>
<p>第二个 SQL <code>INSERT</code> 语句显式列出所有四列并相应地插入新值。最后一个 SQL <code>INSERT</code> 语句只列出三列并只插入三个值。<code>description</code> 列留为空白，这意味着它将具有 <code>NULL</code> 值。 </p>
<p>虽然单行 SQL <code>INSERT</code> 语句可能有用，但当您需要插入多行时，直接插入多行可能更有效，如 <a href="http://www.ibm.com/developerworks/cn/opensource/os-ad-trifecta4/#list8">清单 8</a> 所示。 </p>
<br />
<a name="list8"><strong>清单 8. 插入多行</strong></a><br />
<table cellspacing="0" cellpadding="0" width="100%" border="0">
    <tbody>
        <tr>
            <td class="code-outline">
            <pre class="displaycode">rb$ java org.apache.derby.tools.ij
            ij version 10.1
            ij&gt; connect 'jdbc:derby:test' ;
            ij&gt; INSERT INTO bigdog.products(itemNumber, price, stockDate, description)
            VALUES (4, 29.95, '2006-02-10', 'Male bathing suit, blue'),
            (5, 49.95, '2006-02-20', 'Female bathing suit, one piece, aqua'),
            (6, 9.95, '2006-01-15', 'Child sand toy set'),
            (7, 24.95, '2005-12-20', 'White beach towel'),
            (8, 32.95, '2005-12-22', 'Blue-striped beach towel'),
            (9, 12.95, '2006-03-12', 'Flip-flop'),
            (10, 34.95, '2006-01-24', 'Open-toed sandal') ;
            7 rows inserted/updated/deleted
            ij&gt; exit ;
            </pre>
            </td>
        </tr>
    </tbody>
</table>
<br />
<p>在本例中，首先启动 <code>ij</code> 工具并连接数据库。下一代码行通过显式列出所有四列并为每行提供新值，将 7 行插入数据库中。如前所述，多行插入将每个新行的值包括在括号内，这些值之间用逗号分隔。该 SQL <code>INSERT</code> 语句执行之后，<code>ij</code> 工具报告这 7 新行已经插入。 </p>
<p><a name="N10329"><span class="smalltitle">在 Apache Derby 中插入数据</span></a></p>
<p>多行插入优于多个单行插入；但更好的方法是将 SQL <code>INSERT</code> 语句放在脚本文件中，运行脚本来插入数据。这种方法允许您更容易地修复错误或根据需要重新插入数据，而无需重新创建必需的 SQL <code>INSERT</code> 语句。如前所述，可以 <a href="http://www.ibm.com/developerworks/cn/opensource/os-ad-trifecta4/#download">随本文下载</a> 的 .zip 文件包括两个 SQL 脚本文件。第二个脚本文件 (derby.insert.sql) 将上一节提供的 10 行插入到数据库中，并执行简单查询以显示结果，从而验证插入操作。执行查询操作的机制将在下一篇文章中详细讨论，但您不必理解查询就能够运行插入脚本。 </p>
<p>要执行脚本，可以选择本文开头展示的三个方法之一。在 <a href="http://www.ibm.com/developerworks/cn/opensource/os-ad-trifecta4/#list9">清单 9</a> 中，通过重定向 <code>ij</code> 工具的标准输入以从脚本文件中读取的方式，来执行插入脚本。插入 10 行，然后结果显示到屏幕上。 </p>
<br />
<a name="list9"><strong>清单 9. 验证插入操作</strong></a><br />
<table cellspacing="0" cellpadding="0" width="100%" border="0">
    <tbody>
        <tr>
            <td class="code-outline">
            <pre class="displaycode">$ java org.apache.derby.tools.ij &lt; derby.insert.sql
            ij version 10.1
            ij&gt; ij&gt; 10 rows inserted/updated/deleted
            ij&gt; ITEMNUMBER |PRICE   |STOCKDATE |DESCRIPTION
            -------------------------------------------------------------------------------
            1          |19.95   |2006-03-31|Hooded sweatshirt
            2          |99.99   |2006-03-29|Beach umbrella
            3          |0.99    |2006-02-28|
            4          |29.95   |2006-02-10|Male bathing suit, blue
            5          |49.95   |2006-02-20|Female bathing suit, one piece, aqua
            6          |9.95    |2006-01-15|Child sand toy set
            7          |24.95   |2005-12-20|White beach towel
            8          |32.95   |2005-12-22|Blue-striped beach towel
            9          |12.95   |2006-03-12|Flip-flop
            10         |34.95   |2006-01-24|Open-toed sandal
            10 rows selected
            ij&gt; ij&gt; rb$
            </pre>
            </td>
        </tr>
    </tbody>
</table>
<br />
<br />
<table cellspacing="0" cellpadding="0" width="100%" border="0">
    <tbody>
        <tr>
            <td><img height="1" alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" width="100%" /><br />
            <img height="6" alt="" src="http://www.ibm.com/i/c.gif" width="8" border="0" /></td>
        </tr>
    </tbody>
</table>
<table class="no-print" cellspacing="0" cellpadding="0" align="right">
    <tbody>
        <tr align="right">
            <td><img height="4" alt="" src="http://www.ibm.com/i/c.gif" width="100%" /><br />
            <table cellspacing="0" cellpadding="0" border="0">
                <tbody>
                    <tr>
                        <td valign="middle"><img height="16" alt="" src="http://www.ibm.com/i/v14/icons/u_bold.gif" width="16" border="0" /><br />
                        </td>
                        <td valign="top" align="right"><a class="fbox" href="http://www.ibm.com/developerworks/cn/opensource/os-ad-trifecta4/#main"><strong>回页首</strong></a></td>
                    </tr>
                </tbody>
            </table>
            </td>
        </tr>
    </tbody>
</table>
<br />
<br />
<p><a name="N10353"><span class="atitle">结束语</span></a></p>
<p>本文讨论了两个主要主题。首先向您介绍了 SQL 脚本文件的概念，该脚本文件可用于以自动方式执行多个 SQL（或 Derby）命令。使用 Apache Derby <code>ij</code> 工具执行 SQL 脚本文件有三种方法：从工具中、使用 <code>run</code> 命令或直接从命令行使用这两种方法之一。然后，您回顾了 <code>INSERT</code> 语句的 SQL 语法，并查看了如何使用该语句将数据插入 Derby 数据库中的示例。后续文章将在此基础上查询、更新和删除 Apache Derby 数据库中的数据。</p>
<br />
<br />
<table cellspacing="0" cellpadding="0" width="100%" border="0">
    <tbody>
        <tr>
            <td><img height="1" alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" width="100%" /><br />
            <img height="6" alt="" src="http://www.ibm.com/i/c.gif" width="8" border="0" /></td>
        </tr>
    </tbody>
</table>
<table class="no-print" cellspacing="0" cellpadding="0" align="right">
    <tbody>
        <tr align="right">
            <td><img height="4" alt="" src="http://www.ibm.com/i/c.gif" width="100%" /><br />
            <table cellspacing="0" cellpadding="0" border="0">
                <tbody>
                    <tr>
                        <td valign="middle"><img height="16" alt="" src="http://www.ibm.com/i/v14/icons/u_bold.gif" width="16" border="0" /><br />
                        </td>
                        <td valign="top" align="right"><a class="fbox" href="http://www.ibm.com/developerworks/cn/opensource/os-ad-trifecta4/#main"><strong>回页首</strong></a></td>
                    </tr>
                </tbody>
            </table>
            </td>
        </tr>
    </tbody>
</table>
<br />
<br />
<p><span class="atitle"><a name="download">下载</a></span></p>
<table class="data-table-1" cellspacing="0" cellpadding="0" width="100%" border="0">
    <tbody>
        <tr>
            <th scope="col">描述</th>
            <th scope="col">名字</th>
            <th scope="col" align="right">大小</th>
            <th scope="col">下载方法</th>
        </tr>
        <tr>
            <th class="tb-row" scope="row">Derby SQL scripts for this article</th>
            <td noWrap>derby4.zip</td>
            <td noWrap align="right">1KB</td>
            <td noWrap><a class="fbox" href="http://download.boulder.ibm.com/ibmdl/pub/software/dw/opensource/derby4.zip"><strong>HTTP</strong></a></td>
        </tr>
    </tbody>
</table>
<table cellspacing="0" cellpadding="0" border="0">
    <tbody>
        <tr valign="top">
            <td colspan="5"><img height="12" alt="" src="http://www.ibm.com/i/c.gif" width="12" border="0" /></td>
        </tr>
        <tr>
            <td><img height="16" alt="" src="http://www.ibm.com/i/v14/icons/fw.gif" width="16" /></td>
            <td><a class="fbox" href="http://www.ibm.com/developerworks/cn/whichmethod.html">关于下载方法的信息</a></td>
            <td><img height="1" alt="" src="http://www.ibm.com/i/c.gif" width="50" /></td>
        </tr>
    </tbody>
</table>
<br />
<img src ="http://www.blogjava.net/smildlzj/aggbug/163575.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/smildlzj/" target="_blank">smildlzj</a> 2007-11-27 23:39 <a href="http://www.blogjava.net/smildlzj/articles/163575.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>用 Apache Derby 进行数据库开发，第 2 部分</title><link>http://www.blogjava.net/smildlzj/articles/163572.html</link><dc:creator>smildlzj</dc:creator><author>smildlzj</author><pubDate>Tue, 27 Nov 2007 15:05:00 GMT</pubDate><guid>http://www.blogjava.net/smildlzj/articles/163572.html</guid><wfw:comment>http://www.blogjava.net/smildlzj/comments/163572.html</wfw:comment><comments>http://www.blogjava.net/smildlzj/articles/163572.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/smildlzj/comments/commentRss/163572.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/smildlzj/services/trackbacks/163572.html</trackback:ping><description><![CDATA[<blockquote>本文将学习几个基本的数据库概念，包括模式、表、列数据类型以及结构化查询语言（SQL）的简单介绍。这篇文章 —— 侧重于数据库开发人员的角色 —— 介绍可以用来在 Apache Derby 数据库中保存数据的基本数据类型，然后用它们在 Apache Derby 中创建一个带有两个表的简单模式，供一个虚拟的商店使用。要查看数据库的模式内容，可以使用 Apache Derby 的工具 —— dblook，导出数据库的内容。文章结束时简单讨论了如何删除表。</blockquote><!--start RESERVED FOR FUTURE USE INCLUDE FILES--><!-- include java script once we verify teams wants to use this and it will work on dbcs and cyrillic characters --><!--end RESERVED FOR FUTURE USE INCLUDE FILES-->
<p><a name="N10059"><span class="atitle">关系数据库系统基础</span></a></p>
<p>在开发数据库应用程序之前，需要理解它的基本概念。这一节介绍在 Apache Derby 中可以使用的数据类型，以及对设计和创建有用的 Derby 数据库应用程序的能力有影响的规则。 </p>
<p>关系数据库容纳数据。数据可以是不同类型的，例如数值型、字符型或日期型。在数据库中，数据被组织到叫做<em>表</em> 的逻辑单元中。表就像工作簿一样，因为它包含数据行。每行由许多列组成。列容纳特定数据类型的数据，例如整型值或字符串。在多数情况下，一个数据库有多个表。为了将表关联在一起，数据库设计师利用表之间的自然（或人为）链接。在工作簿中，可以通过单元格的值链接不同工作簿中的行。同样的概念在关系数据库中也存在，用来进行链接的列叫做<em>键列（key column）</em>。 </p>
<p>为了让表或列的用途更容易理解，应当选择合适的名称。对于不同的数据库，命名约定可能不同。对于 Apache Derby 数据库系统，名称应当：</p>
<ul>
    <li>不区分大小。
    <li>最长 128 个字符。
    <li>必须以字母开头。
    <li>必须只包含 Unicode 字母、下划线和 Unicode 数字。 </li>
</ul>
<p>通过把名称放在双引号中，可以<em>避开</em> 这些规则，使用双引号允许名称区分大小写以及包含附加字符（包括空格）。但是，这么做通常是不好的做法：它要求名称总被括在双引号中，很容易把维护代码的其他人弄糊涂。</p>
<table cellspacing="0" cellpadding="0" width="40%" align="right" border="0">
    <tbody>
        <tr>
            <td width="10"><img height="1" alt="" src="http://www.ibm.com/i/c.gif" width="10" /></td>
            <td>
            <table cellspacing="0" cellpadding="5" width="100%" border="1">
                <tbody>
                    <tr>
                        <td bgcolor="#eeeeee"><a name="namecase"><strong>Derby 风格</strong></a><br />
                        这个 <a href="http://www.ibm.com/developerworks/cn/views/opensource/articles.jsp?view_by=search&amp;search_by=%E7%94%A8+Apache+Derby+%E8%BF%9B%E8%A1%8C%E5%BC%80%E5%8F%91+%E2%80%94%E2%80%94+%E5%8F%96%E5%BE%97%E8%8A%82%E8%8A%82%E8%83%9C%E5%88%A9">文章系列</a> 遵守特定的风格：所有 SQL 命令都用大写，项目名称采用 camelCase 方式，在 camelCase 风格中，单词被连在一起，第一个单词之后的每个单词的第一个字母大写，例如 <code>aLongIdentifier</code>。把这两种风格组合在一起，这些文章写 SQL 命令时的风格是这样：<code>SELECT aLongIdentifier FROM bigdog.dataTable ;</code>. </td>
                    </tr>
                </tbody>
            </table>
            </td>
        </tr>
    </tbody>
</table>
<p>关联的表通常组织在一起，形成一个<em>模式（schema）</em>。可以把模式当成特定数据库中所有相关结构定义的容器。在指定模式中，表的名称必须惟一。所以，通过使用模式，可以在不同模式的范围内拥有名称相同的对象（例如表）。在使用 Apache Derby 数据库时，表总在模式中。如果没有显式地指定模式，Derby 就会隐式地使用内置的 <code>apps</code> 模式。叫做 <code>sys</code> 的第二个内置模式用来隔离系统表。</p>
<p>可以用模式名对名称进行<em>限定（qualify）</em>。要做这件事，可以在模式名后加圆点，然后加表名。例如，<code>bigdog.products</code> 表示 <code>bigdog</code> 模式中的 <code>products</code> 表。没有相应的模式名，表名就被认为是<em>未限定的（unqualified）</em>，例如 <code>products</code>。当模式名和表名都完全指定的时候，就像 <code>bigdog.products</code>，名称被称为<em>完全限定的（fully qualified）</em>。</p>
<p>从抽象意义上来说，这些数据库概念看起来可能让人混淆。但在实践上，它们相当简单。例如，假设有一个商店，叫做 Bigdog's Surf Shop，这家店销售各种商品，例如太阳镜、衬衫等等。如果想赢利，就必须管理库存，以便可以容易地订购额外的商品或改变供应商，从而把开支控制在最小。跟踪这些信息的一个简单方法，就是用表格式编写条目，如 <a href="http://www.ibm.com/developerworks/cn/opensource/os-ad-trifecta3/#fig1">图 1</a> 所示。 </p>
<br />
<a name="fig1"><strong>图 1. Bigdog's Surf Shop 的示例模式</strong></a><br />
<img height="447" alt="Bigdog's Surf Shop 的示例模式，显示了一个 Products 表和一个 Vendors 表" src="http://www.ibm.com/developerworks/cn/opensource/os-ad-trifecta3/figure1.jpg" width="400" /> <br />
<p>从这个简单的可视设计中，可以容易地把业务逻辑直接映射到数据库表。有两个表：Products 和 Vendors，它们自然地通过商品名称链接在一起。列的数据类型很容易确定。这篇文章其余的部分将侧重于在 Derby 数据库中创建 Bigdog's Surf Shop 的示例模式 —— 模式中包含这两个表。 </p>
<br />
<table cellspacing="0" cellpadding="0" width="100%" border="0">
    <tbody>
        <tr>
            <td><img height="1" alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" width="100%" /><br />
            <img height="6" alt="" src="http://www.ibm.com/i/c.gif" width="8" border="0" /></td>
        </tr>
    </tbody>
</table>
<table class="no-print" cellspacing="0" cellpadding="0" align="right">
    <tbody>
        <tr align="right">
            <td><img height="4" alt="" src="http://www.ibm.com/i/c.gif" width="100%" /><br />
            <table cellspacing="0" cellpadding="0" border="0">
                <tbody>
                    <tr>
                        <td valign="middle"><img height="16" alt="" src="http://www.ibm.com/i/v14/icons/u_bold.gif" width="16" border="0" /><br />
                        </td>
                        <td valign="top" align="right"><a class="fbox" href="http://www.ibm.com/developerworks/cn/opensource/os-ad-trifecta3/#main"><strong>回页首</strong></a></td>
                    </tr>
                </tbody>
            </table>
            </td>
        </tr>
    </tbody>
</table>
<br />
<br />
<p><a name="N100DE"><span class="atitle">处理关系数据库：结构化查询语言</span></a></p>
<table cellspacing="0" cellpadding="0" width="40%" align="right" border="0">
    <tbody>
        <tr>
            <td width="10"><img height="1" alt="" src="http://www.ibm.com/i/c.gif" width="10" /></td>
            <td>
            <table cellspacing="0" cellpadding="5" width="100%" border="1">
                <tbody>
                    <tr>
                        <td bgcolor="#eeeeee"><a name="sqlnull"><strong>SQL NULL 类型</strong></a><br />
                        在开始创建数据库表之前，必须知道列没有指定值的时候要做什么。为了理解这一点，请想像一下填写 Web 表单时的情况。如果某个具体列为空，那么插到数据库中的是什么呢？可以想像，如果必须跟踪<em>无值</em> 标记，问题会很麻烦。幸运的是，SQL 定义了一个特殊值，<code>NULL</code>，表示列没有值。 </td>
                    </tr>
                </tbody>
            </table>
            </td>
        </tr>
    </tbody>
</table>
<p>数据库系统会成为软件中复杂的部分，特别是在规模扩大到支持企业级应用程序的时候。所以，可以想像每个数据库都会有自己的应用程序编程接口（API），而这些 API 可能彼此不同。当关系数据库刚开发出来的时候，情况就是这样。但是，幸运的是，许多开发商同意开发一个标准的语言，用来访问和操纵数据库。这个语言称作结构化查询语言（或 SQL，发音是 <em>sea-quill</em>）。至今已经形成了多个官方标准版本，包括 1992 年的版本，这一版被称为 SQL-92，还有 1999 年的版本被称为 SQL-99。Apache Derby 数据库为 SQL-92 标准提供了几乎完整的实现，所以用 Deryby 开发的应用程序可以容易地移植到其他数据库系统。</p>
<p>SQL 有两个主要部分：数据定义语言（DDL）和数据操纵语言（DML）。DDL 命令用来创建、修改或删除数据库中的项目（例如表）。DML 命令用来在数据库表中添加、修改、删除或选择数据。这篇文章后面的部分将提供对 SQL 的 DDL 部分的基本介绍。未来的文章将侧重于 DML 命令和更高级的 DDL 命令。</p>
<p><a name="N100FC"><span class="smalltitle">SQL 数据类型</span></a></p>
<p>SQL 作为一个编程语言，定义了丰富的数据类型层次结构。数据库已经变得更强大了，所以这个类型层次结构也变得更复杂。但是最简单的数据库并不要求使用所有允许的类型，通常只需要保存数值型、字符型和日期（或时间）数据。为了简单，表 1、2、3、4 显示了 Derby 中实现的基本 SQL 数据类型。</p>
<p>如表 1 所示，Derby 提供了对三种整型数据类型的支持。这些类型由它们可以保存的整数的范围区分，也就是由它们在数据库中需要的存储空间区分。在设计数据库时要记住的一个关键问题就是，应当一直把表使用的空间控制在最小。一般来说，表越小，性能越高。但是必须能够在生成的表中保存需要的数据。2<sup>31</sup> 等于 2,147,483,648，2<sup>63</sup> 等于 9,223,372,036,854,775,808，所以使用这些类型可以保存非常大的整数！ </p>
<table class="data-table-1" cellspacing="0" cellpadding="0" width="100%" summary="Table description" border="0">
    <caption><em>表 1. Derby 中的基本整数数据类型</em></caption>
    <tbody>
        <tr>
            <th>数据类型</th>
            <th>最小值</th>
            <th>最大值</th>
            <th>示例</th>
            <th>说明</th>
        </tr>
        <tr>
            <td><code>SMALLINT</code></td>
            <td>-32768 (-2<sup>15</sup>)</td>
            <td>32767 (2<sup>15</sup> - 1)</td>
            <td><code>itemNumber SMALLINT</code></td>
            <td>2 字节整数表示</td>
        </tr>
        <tr>
            <td><code>INT</code></td>
            <td>-2<sup>31</sup></td>
            <td>2<sup>31</sup> - 1</td>
            <td><code>itemNumber INT</code></td>
            <td>4 字节整数表示</td>
        </tr>
        <tr>
            <td><code>BIGINT</code></td>
            <td>-2<sup>63</sup></td>
            <td>2<sup>63</sup> - 1</td>
            <td><code>itemNumber BIGINT</code></td>
            <td>8 字节整数表示</td>
        </tr>
    </tbody>
</table>
<p>多数数值型数据不能用整数表示。Derby 对实数提供了多种格式的支持：单精度浮点、双精度浮点以及准确的算术表示，如表 2 所示。 </p>
<table class="data-table-1" cellspacing="0" cellpadding="0" width="100%" summary="Table description" border="0">
    <caption><em>表 2. Derby 中的基本数值类型</em></caption>
    <tbody>
        <tr>
            <th>数据类型</th>
            <th>最小值</th>
            <th>最大值</th>
            <th>示例</th>
            <th>说明</th>
        </tr>
        <tr>
            <td><code>REAL</code></td>
            <td>-3.402x10<sup>+38</sup></td>
            <td>3.402x10<sup>+38</sup></td>
            <td><code>price REAL</code></td>
            <td>IEEE 浮点数（4 字节）</td>
        </tr>
        <tr>
            <td><code>DOUBLE</code></td>
            <td>-1.79769x10<sup>+308</sup></td>
            <td>1.79769x10<sup>+308</sup></td>
            <td><code>price DOUBLE</code></td>
            <td>IEEE 浮点数（8 字节）</td>
        </tr>
        <tr>
            <td><code>DECIMAL</code></td>
            <td colspan="2">31 （最大精度）</td>
            <td><code>price DECIMAL(5,2)</code></td>
            <td>准确算术表示</td>
        </tr>
    </tbody>
</table>
<p>如果从未遇到过准确精度数据类型，那么对算术类型和浮点类型可能有些迷惑。区别在于一个事实：计算机中使用的浮点数据类型无法包含每个实数。这看起来可能有些怪，但是想想实数的数量是无限的。大多数实数都无法保存在几个字节的内存中。对于某些应用程序，精度的损失是可以接受的，而在许多情况下，则不可接受。例如，财务应用程序不能容忍仅仅因为某个数字不能保存在计算机中，就损失金钱。 </p>
<p>这个问题的解决方案是使用 <code>DECIMAL</code> 数据类型，它可以控制计算机存储的数字位数（<em>精度</em>）和小数点后的位数（<em>刻度</em>）。要创建算术类型，应当指定保存的数据的精度，并可选地指定数据的刻度。<code>DECIMAL</code> 数据类型需要的存储空间通常要比浮点数据类型大得多。所以应当小心地使用这个类型，否则应用程序的性能会降低。默认情况下，<code>DECIMAL</code> 类型的刻度为 0，这意味着 <code>DECIMAL</code> 数据类型模拟了整数类型。 </p>
<p>数值类型有多个同义词。例如，<code>DECIMAL</code> 数据类型可以缩短为 <code>DEC</code> 或表示为 <code>NUMERIC</code>。<code>DOUBLE</code> 类型也可以表示为 <code>DOUBLE PRECISION</code>，虽然为什么在需要双精度数字时要输入额外的单词，原因不明。更常用的同义词是 <code>FLOAT</code> 类型，它拥有任意的浮点精度，可以在声明数据类型时指定，例如 <code>FLOAT(val)</code>。精度必须是小于 53 的正整数；如果不是，就会出错。如果指定了小于等于 23 的精度值，<code>FLOAT(val)</code> 就等价于 <code>REAL</code>；如果精度在 24 和 53 之间，那么 <code>FLOAT(val)</code> 等价于 <code>DOUBLE</code>。 </p>
<p>除了数值类型，数据库中最常用的保存数据的另一个类型是字符数据。字符数据的示例包括产品说明、人名或地址信息。Derby 提供了保存字符数据的两个简单技术：<code>CHAR</code> 类型和 <code>VARCHAR</code> 类型，详情如表 3 所示。对于这两种类型，都可以指定 <code>length</code> 参数，如果没指定，默认为 1。在这两个字符数据类型之间有两个主要区别。首先，<code>CHAR</code> 类型的最大长度是 254 个字符，而 <code>VARCHAR</code> 类型最多可以容纳 32,672 个字符。第二个区别比较微妙：<code>CHAR</code> 类型的长度总是指定的长度。如果没有指定足够的字符，那么会插入额外的空白来填满剩余位置。而使用 <code>VARCHAR</code> 时，字符的数量是可变的，不执行额外的填充。 </p>
<table class="data-table-1" cellspacing="0" cellpadding="0" width="100%" summary="Table description" border="0">
    <caption><em>表 3. Derby 中的基本字符串数据类型</em></caption>
    <tbody>
        <tr>
            <th>数据类型</th>
            <th>最大长度</th>
            <th>示例</th>
            <th>说明</th>
        </tr>
        <tr>
            <td><code>CHAR</code></td>
            <td>254</td>
            <td><code>description CHAR(128)</code></td>
            <td>定长字符串</td>
        </tr>
        <tr>
            <td><code>VARCHAR</code></td>
            <td>32,672</td>
            <td><code>description VARCHAR(128)</code></td>
            <td>变长字符串</td>
        </tr>
    </tbody>
</table>
<p>因为长度可变，所以 <code>VARCHAR</code> 类型在实际的存储空间方面会更有效率，但在性能上效率就会更低。<code>CHAR</code> 数据类型有助于性能提高，因为数据库确切地知道每个 <code>CHAR</code> 列有多大，所以在读写数据时就可以执行某种性能优化。<code>VARCHAR</code> 列的最大长度看起来可能足够大了，但是 Derby 还提供了更大的字符数据类型，这个类型将在未来的文章中讨论。</p>
<p>Derby 提供了最后一类简单的数据类型来保存日期和时间，如表 4 所示。<code>TIME</code> 数据类型以 24 小时格式保存小时、分钟和秒（<code>HH:MM:SS</code>）。<code>DATE</code> 数据类型保存月、日和年，可以用不同的格式指定，包括以下格式：
<ul>
    <li><code>yyyy-mm-dd</code>
    <li><code>mm/dd/yyyy</code>
    <li><code>dd.mm.yyyy</code> </li>
</ul>
<p>&nbsp;</p>
<table class="data-table-1" cellspacing="0" cellpadding="0" width="100%" summary="Table description" border="0">
    <caption><em>表 4. Derby 中的基本日期和时间数据类型</em></caption>
    <tbody>
        <tr>
            <th>数据类型</th>
            <th>最小值</th>
            <th>最大值</th>
            <th>示例</th>
            <th>说明</th>
        </tr>
        <tr>
            <td><code>TIME</code></td>
            <td>00:00:00</td>
            <td>24:00:00</td>
            <td><code>start TIME</code></td>
            <td>时间表示（精确到秒）</td>
        </tr>
        <tr>
            <td><code>DATE</code></td>
            <td>0001-01-01</td>
            <td>9999-12-31</td>
            <td><code>stockDate DATE</code></td>
            <td>日期表示（精确到天）</td>
        </tr>
    </tbody>
</table>
<p>Derby 还提供了 <code>TIMESTAMP</code> 数据类型，把 <code>TIME</code> 和 <code>DATE</code> 数据类型组合到一个类型中，表示准确的时间。</p>
<br />
<table cellspacing="0" cellpadding="0" width="100%" border="0">
    <tbody>
        <tr>
            <td><img height="1" alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" width="100%" /><br />
            <img height="6" alt="" src="http://www.ibm.com/i/c.gif" width="8" border="0" /></td>
        </tr>
    </tbody>
</table>
<table class="no-print" cellspacing="0" cellpadding="0" align="right">
    <tbody>
        <tr align="right">
            <td><img height="4" alt="" src="http://www.ibm.com/i/c.gif" width="100%" /><br />
            <table cellspacing="0" cellpadding="0" border="0">
                <tbody>
                    <tr>
                        <td valign="middle"><img height="16" alt="" src="http://www.ibm.com/i/v14/icons/u_bold.gif" width="16" border="0" /><br />
                        </td>
                        <td valign="top" align="right"><a class="fbox" href="http://www.ibm.com/developerworks/cn/opensource/os-ad-trifecta3/#main"><strong>回页首</strong></a></td>
                    </tr>
                </tbody>
            </table>
            </td>
        </tr>
    </tbody>
</table>
<br />
<br />
<p><a name="N102F5"><span class="atitle">在 Derby 中创建表</span></a></p>
<p>目前为止，已经学习了如何设计表，包括规划表的列和定义每个列的数据类型。在正确地设计了表之后，用 SQL 创建表的方法就很简单了。<a href="http://www.ibm.com/developerworks/cn/opensource/os-ad-trifecta3/#list1">清单 1</a> 显示了在 Derby 中创建表的正式语法。 </p>
<br />
<a name="list1"><strong>清单 1. Apache Derby 的 CREATE TABLE 语法</strong></a><br />
<table cellspacing="0" cellpadding="0" width="100%" border="0">
    <tbody>
        <tr>
            <td class="code-outline">
            <pre class="displaycode">--  Comment describing the purpose and layout of the table
            CREATE TABLE [schemaName.]tableName (
            { &lt;columnDefinition&gt; | &lt;tableLevelConstraint&gt;  } [,
            { &lt;columnDefinition&gt; | &lt;tableLevelConstraint&gt;  }
            ]*
            ) ;
            </pre>
            </td>
        </tr>
    </tbody>
</table>
<br />
<p>第一次看这个语法时，可能感觉到迷惑不解。但是有了基础之后，接下来就容易了；而且如果想掌握 Derby，对正式语法的理解是必需的。方括号（<code>[</code> 和 <code>]</code>）中的是可选参数。从正式语法中可以看出，模式名是可选的，在必需的头一个列之后（创建连一个列都没有的表是没有意义的），其他列定义或表级约束都是可选的。 </p>
<p>您可能理解列定义的含义，但是可能不理解<em>约束</em> 的意义。约束有两种类型：表级约束和列约束。约束通过某种方式对列或表进行限制。例如，可以用约束要求列总要有实际的值（没有 <code>NULL</code> 值），或者列中的每个项必须是惟一的，或者列被自动分配默认值。在未来的文章中将更详细地介绍约束。</p>
<p>最后一个结束方括号之后的星号（<code>*</code>）代表可以包含一个或多个包含项。这意味着表必须有一个或多个列级或表级约束。竖线（<code>|</code>）表明 &#8220;可有可无&#8221; 条件。在这个语法示例中，必须定义一个新列或者定义一个表级约束。花括号（<code>{</code> 和 <code>}</code>）把相关项组织在一起，而圆括号（<code>(</code> 和 <code>)</code>）中是必需的元素 。最后，分号（<code>;</code>）表示 SQL 语句的结束。 </p>
<p>把这些规则投入使用则相当简单。<a href="http://www.ibm.com/developerworks/cn/opensource/os-ad-trifecta3/#list2">清单 2</a> 显示了如何用 Derby 提供的 <code>ij</code> 创建前面在 <a href="http://www.ibm.com/developerworks/cn/opensource/os-ad-trifecta3/#fig1">图 1</a> 中演示的表。 </p>
<br />
<a name="list2"><strong>清单 2. 在 Apache Derby 中创建表</strong></a><br />
<table cellspacing="0" cellpadding="0" width="100%" border="0">
    <tbody>
        <tr>
            <td class="code-outline">
            <pre class="displaycode">rb$ java org.apache.derby.tools.ij
            ij version 10.1
            ij&gt; connect 'jdbc:derby:test;create=true' ;
            ij&gt; CREATE TABLE bigdog.products (
            itemNumber INT NOT NULL,
            price DECIMAL(5, 2),
            stockDate DATE,
            description VARCHAR(128)
            ) ;
            0 rows inserted/updated/deleted
            ij&gt; CREATE TABLE bigdog.vendors (
            itemNumber INT NOT NULL,
            vendorNumber INT NOT NULL,
            vendorName CHAR(64)
            ) ;
            0 rows inserted/updated/deleted
            ij&gt; exit ;
            </pre>
            </td>
        </tr>
    </tbody>
</table>
<br />
<p>与 Derby 数据库进行交互的最简单方式是使用 <code>ij</code> 工具，在这个系列的第一篇文章 &#8220;<a href="http://www.ibm.com/developerworks/opensource/library/os-ad-trifecta1/">用 Apache Derby 进行开发 —— 取得节节胜利：Apache Derby 介绍</a>&#8221;（developerWorks，2006 年 2 月）中已经介绍过。如果按照 <a href="http://www.ibm.com/developerworks/cn/opensource/os-ad-trifecta3/#list2">清单 2</a> 中的步骤进行，就会创建一个新的数据库，名为 <code>test</code>。如果 <code>test</code> 数据库已经存在，在发出 <code>connect</code> 语句时，会得到警告消息。可以安全地忽略这个警告。接下来，隐式地创建一个名为 <code>bigdog</code> 的新模式，并显式地创建两个新表 —— <code>products</code> 和 <code>vendors</code> —— 这两个表保存在 <code>bigdog</code> 模式中。模式的创建所以是隐式的，是因为没有发出 <code>CREATE SCHEMA</code> 语句。</p>
<p><code>products</code> 表有四个列：<code>itemNumber</code>、<code>price</code>、<code>stockDate</code> 和 <code>description</code>。<code>itemNumber</code> 列提供了每个商品（或列）的惟一标识，它上面还有列级约束，强制要求提供正确的值（<code>NOT NULL</code>）。如果没有这个要求，<code>itemNumber</code> 列就无法保持惟一，因为多个行都可能被分配 <code>NULL</code> 值。<code>price</code> 列创建为 <code>DECIMAL</code> 数据类型，精度为 5，刻度为 2。这意味着每个商品的最高价格可以是 $999.99。最后两个列很简单：<code>stockDate</code> 列以 <code>Date</code> 类型保存，<code>description</code> 列以字符串类型保存，最长 128 个字符，使用的空间是实际的字符串长度。 </p>
<p><code>vendors</code> 表有三列：<code>itemNumber</code>、 <code>vendorNumber</code> 和 <code>vendorName</code>。在这个示例中，<code>itemNumber</code> 和 <code>vendorNumber</code> 列都有列级约束（<code>NOT NULL</code>）。另外，<code>vendorName</code> 列以字符串类型保存，最大长度为 64。因为 <code>vendorName</code> 列用 <code>CHAR</code> 数据类型保存，所以总是保留 64 个字符空间。 </p>
<p>在创建了各种项目之后，可能想知道是否有种简单的方式可以查看数据库中保存了什么项目。幸运的是，答案是肯定的，可以使用 <code>dblook</code> 工具。运行这个工具，如 <a href="http://www.ibm.com/developerworks/cn/opensource/os-ad-trifecta3/#list3">清单 3</a> 所示，提供了特定数据库中已经创建的项目的详细清单。 </p>
<br />
<a name="list3"><strong>清单 3. 用 dblook 查看模式</strong></a><br />
<table cellspacing="0" cellpadding="0" width="100%" border="0">
    <tbody>
        <tr>
            <td class="code-outline">
            <pre class="displaycode">rb$ java org.apache.derby.tools.dblook -d jdbc:derby:test
            -- Timestamp: 2006-03-04 10:52:34.056
            -- Source database is: test
            -- Connection URL is: jdbc:derby:test
            -- appendLogs: false
            -- ----------------------------------------------
            -- DDL Statements for schemas
            -- ----------------------------------------------
            CREATE SCHEMA "BIGDOG";
            -- ----------------------------------------------
            -- DDL Statements for tables
            -- ----------------------------------------------
            CREATE TABLE "BIGDOG"."PRODUCTS" (
            "ITEMNUMBER" INTEGER NOT NULL,
            "PRICE" DECIMAL(5,2),
            "STOCKDATE" DATE,
            "DESCRIPTION" VARCHAR(128));
            CREATE TABLE "BIGDOG"."VENDORS" (
            "ITEMNUMBER" INTEGER NOT NULL,
            "VENDORNUMBER" INTEGER NOT NULL,
            "VENDORNAME" CHAR(64));
            </pre>
            </td>
        </tr>
    </tbody>
</table>
<br />
<p><code>dblook</code> 工具是一个 Java 类，可以用它方便地把数据库的内容输出到控制台。在命令行上运行它，就像运行其他 Java 程序一样；惟一增加的就是使用 <code>-d jdbc:derby:test</code> 参数，这个参数指定 <code>dblook</code> 工具应当查询的数据库。如果能运行 <code>ij</code> 工具，那么 <code>dblook</code> 类文件就已经存在于 <code>CLASSPATH</code> 中了。如果不是这样，请参考这个系列中的 <a href="http://www.ibm.com/developerworks/opensource/library/os-ad-trifecta1/">第一篇文章</a>，获得正确设置 <code>CLASSPATH</code> 的详细说明。正如 <code>dblook</code> 工具的输出所示，<code>test</code> 数据库包含 <code>bigdog</code> 模式，这个模式包含 <code>products</code> 和 <code>vendors</code> 表。另外，对这两个表的列也有详细描述。 </p>
<br />
<table cellspacing="0" cellpadding="0" width="100%" border="0">
    <tbody>
        <tr>
            <td><img height="1" alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" width="100%" /><br />
            <img height="6" alt="" src="http://www.ibm.com/i/c.gif" width="8" border="0" /></td>
        </tr>
    </tbody>
</table>
<table class="no-print" cellspacing="0" cellpadding="0" align="right">
    <tbody>
        <tr align="right">
            <td><img height="4" alt="" src="http://www.ibm.com/i/c.gif" width="100%" /><br />
            <table cellspacing="0" cellpadding="0" border="0">
                <tbody>
                    <tr>
                        <td valign="middle"><img height="16" alt="" src="http://www.ibm.com/i/v14/icons/u_bold.gif" width="16" border="0" /><br />
                        </td>
                        <td valign="top" align="right"><a class="fbox" href="http://www.ibm.com/developerworks/cn/opensource/os-ad-trifecta3/#main"><strong>回页首</strong></a></td>
                    </tr>
                </tbody>
            </table>
            </td>
        </tr>
    </tbody>
</table>
<br />
<br />
<p><a name="N10439"><span class="atitle">删除 Derby 中的表</span></a></p>
<p>没有什么事情是完美的。当错误地创建了表或者表不再需要的时候，该怎么办？简单的答案是从数据库中删除表。而且，如果必要，再创建一个替代表。删除表很容易，当然这意味着，在做这件事的时候应当非常小心 —— 不会弹出对话框要求您确认是否真的想删除！ </p>
<p>从数据库中删除（或者更正式地说，<em>撤下（drop）</em>）一个表的完整语法是： </p>
<code>DROP TABLE [schemaName.]tableName ;</code><br />
<br />
<p>语法很简单：把完全限定名称和分号放在 <code>DROP TABLE</code> SQL 命令后面，就完成了。<a href="http://www.ibm.com/developerworks/cn/opensource/os-ad-trifecta3/#list4">清单 4</a> 中在新创建的临时表上演示了删除表的过程。 </p>
<br />
<a name="list4"><strong>清单 4. 从 Derby 数据库删除表</strong></a><br />
<table cellspacing="0" cellpadding="0" width="100%" border="0">
    <tbody>
        <tr>
            <td class="code-outline">
            <pre class="displaycode">rb$ java org.apache.derby.tools.ij
            ij version 10.1
            ij&gt; connect 'jdbc:derby:test' ;
            ij&gt; CREATE TABLE temp ( aColumn INT ) ;
            0 rows inserted/updated/deleted
            ij&gt; DROP TABLE temp ;
            0 rows inserted/updated/deleted
            ij&gt; exit ;
            </pre>
            </td>
        </tr>
    </tbody>
</table>
<br />
<br />
<table cellspacing="0" cellpadding="0" width="100%" border="0">
    <tbody>
        <tr>
            <td><img height="1" alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" width="100%" /><br />
            <img height="6" alt="" src="http://www.ibm.com/i/c.gif" width="8" border="0" /></td>
        </tr>
    </tbody>
</table>
<table class="no-print" cellspacing="0" cellpadding="0" align="right">
    <tbody>
        <tr align="right">
            <td><img height="4" alt="" src="http://www.ibm.com/i/c.gif" width="100%" /><br />
            <table cellspacing="0" cellpadding="0" border="0">
                <tbody>
                    <tr>
                        <td valign="middle"><img height="16" alt="" src="http://www.ibm.com/i/v14/icons/u_bold.gif" width="16" border="0" /><br />
                        </td>
                        <td valign="top" align="right"><a class="fbox" href="http://www.ibm.com/developerworks/cn/opensource/os-ad-trifecta3/#main"><strong>回页首</strong></a></td>
                    </tr>
                </tbody>
            </table>
            </td>
        </tr>
    </tbody>
</table>
<br />
<br />
<p><a name="N10465"><span class="atitle">结束语</span></a></p>
<p>现在您已经走上了操作 Apache Derby 数据库的道路。目前您已经掌握了基本的数据库概念，包括模式、表和列，还看到了使用名为 Bigdog's Surf Shop 的虚拟公司对这些概念的演示。要操作像 Derby 这样的数据库，需要学习 SQL，它是与数据库进行交互的标准语言。这篇文章还介绍了可以用来在 Derby 数据库中保存数据的基本数据类型。把这些概念融合在一起，您学习了如何用 Derby 创建和删除表，还使用 Derby 的 <code>dblook</code> 工具输出了数据库的模式内容。</p>
 <img src ="http://www.blogjava.net/smildlzj/aggbug/163572.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/smildlzj/" target="_blank">smildlzj</a> 2007-11-27 23:05 <a href="http://www.blogjava.net/smildlzj/articles/163572.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>JPCAP——JAVA中的数据链路层控制之二 </title><link>http://www.blogjava.net/smildlzj/articles/162906.html</link><dc:creator>smildlzj</dc:creator><author>smildlzj</author><pubDate>Sat, 24 Nov 2007 15:41:00 GMT</pubDate><guid>http://www.blogjava.net/smildlzj/articles/162906.html</guid><wfw:comment>http://www.blogjava.net/smildlzj/comments/162906.html</wfw:comment><comments>http://www.blogjava.net/smildlzj/articles/162906.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/smildlzj/comments/commentRss/162906.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/smildlzj/services/trackbacks/162906.html</trackback:ping><description><![CDATA[<div><strong>三．使用JPCAP</strong><strong>实现监听</strong></div>
<div><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <strong>1</strong></span><strong>．监听原理</strong></div>
<div><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>在详细说用JPCAP实现网络监听实现前，先简单介绍下监听的原理。</div>
<div><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>局域网监听利用的是所谓的&#8220;ARP欺骗&#8221;技术。在以前曾经一段阶段，局域网的布局是使用总线式（或集线式）结构，要到达监听只需要将网卡设定为混杂模式即可，但现在的局域网络普遍采用的是交换式网络，所以单纯靠混杂模式来达到监听的方法已经不可行了。所以为了达到监听的目的，我们需要&#8220;欺骗&#8221;路由器、&#8220;欺骗&#8221;交换机，即&#8220;ARP欺骗&#8221;技术。</div>
<div><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>假设本机为A，监听目标为B。</div>
<div>首先，伪造一个ARP REPLY包，数据链路层头及ARP内容部分的源MAC地址填入A的MAC地址，而源IP部分填入网关IP，目的地址填入B的MAC、IP，然后将这个包发送给B，而B接收到这个伪造的ARP REPLY包后，由于源IP为网关IP，于是在它的ARP缓存表里刷新了一项，将（网关IP，网关MAC）刷新成（网关IP，A的MAC）。而B要访问外部的网都需要经过网关，这时候这些要经过网关的包就通通流到A的机器上来了。</div>
<div>接着，再伪造一个ARP REPLY包，数据链路层头及ARP内容部分的源MAC地址填入A的MAC地址，而源IP部分填入B的IP，目的地址填入网关MAC、IP，然后将这个包发给网关，网关接收到这个伪造的ARP REPLY包后，由于源IP为B的IP，于是在它的ARP缓存表里刷新了一项，将（B的IP，B的MAC）刷新成（B的IP，A的MAC）。这时候外部传给B的数据包经过网关时，就通通转发给A。</div>
<div>这样还只是拦截了B的数据包而已，B并不能上网——解决方法是将接收到的包，除了目的地址部分稍做修改，其它原封不动的再转发出去，这样就达到了监听的目的——在B不知不觉中浏览了B所有的对外数据包。</div>
<div>&nbsp;</div>
<div align="center"><span>ARP</span><span>数据包解析</span></div>
<div><span>单元：</span><span>Byte</span></div>
<table style="border-right: medium none; border-top: medium none; border-left: medium none; border-bottom: medium none; border-collapse: collapse" cellspacing="0" cellpadding="0" border="1">
    <tbody>
        <tr style="height: 22.1pt">
            <td style="border-right: windowtext 1pt solid; padding-right: 5.4pt; border-top: windowtext 1pt solid; padding-left: 5.4pt; padding-bottom: 0cm; border-left: windowtext 1pt solid; padding-top: 0cm; border-bottom: windowtext 1pt solid; height: 22.1pt" valign="top" colspan="3">
            <div><span>Ethernet</span><span>头部</span></div>
            </td>
            <td style="border-right: windowtext 1pt solid; padding-right: 5.4pt; border-top: windowtext 1pt solid; padding-left: 5.4pt; padding-bottom: 0cm; border-left: medium none; padding-top: 0cm; border-bottom: windowtext 1pt solid; height: 22.1pt" valign="top" colspan="8">
            <div><span>ARP</span><span>数据部分</span></div>
            </td>
        </tr>
        <tr style="height: 22.1pt">
            <td style="border-right: windowtext 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: windowtext 1pt solid; padding-top: 0cm; border-bottom: windowtext 1pt solid; height: 22.1pt" valign="top">
            <div><span>６</span></div>
            </td>
            <td style="border-right: windowtext 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: medium none; padding-top: 0cm; border-bottom: windowtext 1pt solid; height: 22.1pt" valign="top">
            <div><span>６</span></div>
            </td>
            <td style="border-right: windowtext 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: medium none; padding-top: 0cm; border-bottom: windowtext 1pt solid; height: 22.1pt" valign="top">
            <div><span>２</span></div>
            </td>
            <td style="border-right: windowtext 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: medium none; padding-top: 0cm; border-bottom: windowtext 1pt solid; height: 22.1pt" valign="top">
            <div><span>2</span></div>
            </td>
            <td style="border-right: windowtext 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: medium none; padding-top: 0cm; border-bottom: windowtext 1pt solid; height: 22.1pt" valign="top">
            <div><span>2</span></div>
            </td>
            <td style="border-right: windowtext 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: medium none; padding-top: 0cm; border-bottom: windowtext 1pt solid; height: 22.1pt" valign="top">
            <div><span>2</span></div>
            </td>
            <td style="border-right: windowtext 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: medium none; padding-top: 0cm; border-bottom: windowtext 1pt solid; height: 22.1pt" valign="top">
            <div><span>2</span></div>
            </td>
            <td style="border-right: windowtext 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: medium none; padding-top: 0cm; border-bottom: windowtext 1pt solid; height: 22.1pt" valign="top">
            <div><span>４</span></div>
            </td>
            <td style="border-right: windowtext 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: medium none; padding-top: 0cm; border-bottom: windowtext 1pt solid; height: 22.1pt" valign="top">
            <div><span>６</span></div>
            </td>
            <td style="border-right: windowtext 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: medium none; padding-top: 0cm; border-bottom: windowtext 1pt solid; height: 22.1pt" valign="top">
            <div><span>４</span></div>
            </td>
            <td style="border-right: windowtext 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: medium none; padding-top: 0cm; border-bottom: windowtext 1pt solid; height: 22.1pt" valign="top">
            <div><span>６</span></div>
            </td>
        </tr>
        <tr style="height: 62.45pt">
            <td style="border-right: windowtext 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: windowtext 1pt solid; padding-top: 0cm; border-bottom: windowtext 1pt solid; height: 62.45pt" valign="top">
            <div><span>目标</span><span>MAC</span><span>地址</span></div>
            </td>
            <td style="border-right: windowtext 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: medium none; padding-top: 0cm; border-bottom: windowtext 1pt solid; height: 62.45pt" valign="top">
            <div><span>源地</span><span>MAC</span><span>地址</span></div>
            </td>
            <td style="border-right: windowtext 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: medium none; padding-top: 0cm; border-bottom: windowtext 1pt solid; height: 62.45pt" valign="top">
            <div><span>类型号</span><span>0x0800:ip</span></div>
            <div><span>0x0806:ARP</span></div>
            </td>
            <td style="border-right: windowtext 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: medium none; padding-top: 0cm; border-bottom: windowtext 1pt solid; height: 62.45pt" valign="top">
            <div><span>局域网类型</span></div>
            <div><span>以太网</span><span>0x0001</span></div>
            </td>
            <td style="border-right: windowtext 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: medium none; padding-top: 0cm; border-bottom: windowtext 1pt solid; height: 62.45pt" valign="top">
            <div><span>网络协议类型</span></div>
            <div><span>IP</span><span>网络</span><span>0x0800</span></div>
            </td>
            <td style="border-right: windowtext 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: medium none; padding-top: 0cm; border-bottom: windowtext 1pt solid; height: 62.45pt" valign="top">
            <div><span>MAC/IP</span><span>地址长度，恒为</span><span>0x06/04</span></div>
            </td>
            <td style="border-right: windowtext 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: medium none; padding-top: 0cm; border-bottom: windowtext 1pt solid; height: 62.45pt" valign="top">
            <div><span>ARP</span><span>包类型</span></div>
            <div><span>REPLY</span></div>
            <div><span>0x0002</span></div>
            </td>
            <td style="border-right: windowtext 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: medium none; padding-top: 0cm; border-bottom: windowtext 1pt solid; height: 62.45pt" valign="top">
            <div><span>ARP</span><span>目标</span><span>IP</span><span>地址</span></div>
            </td>
            <td style="border-right: windowtext 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: medium none; padding-top: 0cm; border-bottom: windowtext 1pt solid; height: 62.45pt" valign="top">
            <div><span>ARP</span><span>目标</span><span>MAC </span><span>地址</span></div>
            </td>
            <td style="border-right: windowtext 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: medium none; padding-top: 0cm; border-bottom: windowtext 1pt solid; height: 62.45pt" valign="top">
            <div><span>ARP</span><span>源</span><span>IP</span><span>地址</span></div>
            </td>
            <td style="border-right: windowtext 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: medium none; padding-top: 0cm; border-bottom: windowtext 1pt solid; height: 62.45pt" valign="top">
            <div><span>ARP</span><span>源</span><span>MAC</span><span>地址</span></div>
            </td>
        </tr>
    </tbody>
</table>
<div>&nbsp;</div>
<div><strong>2</strong><strong>．用JPCAP</strong><strong>实现监听</strong></div>
<div><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>就如上面说的，为了实现监听，我们必须做四件事：</div>
<div><span>A．</span>发送ARP包修改B的ARP缓存表；</div>
<div><span>B．</span>发送ARP包修改路由ARP缓存表；</div>
<div><span>C．</span>转发B发过来的数据包；</div>
<div><span>D．</span>转发路由发过来的数据包；</div>
<div>&nbsp;</div>
<div>下面我们给个小小的例子说明怎样实现。</div>
<div>我们假定运行这个程序的机器A只有一个网卡，只接一个网络，所在局域网为Ethernet，并且假定已经通过某种方式获得B和网关的MAC地址（例如ARP解析获得）。我们修改了B和网关的ARP表，并对他们的包进行了转发。</div>
<div><span style="font-size: 9pt">public class changeARP{</span></div>
<div><span style="font-size: 9pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private NetworkInterface[] devices;&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><span>设备列表</span></div>
<div><span style="font-size: 9pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private NetworkInterface device;&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; //</span><span>要使用的设备</span></div>
<div><span style="font-size: 9pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private JpcapCaptor jpcap;&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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //</span><span>与设备的连接</span></div>
<div><span style="font-size: 9pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private JpcapSender sender;&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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //</span><span>用于发送的实例</span></div>
<div><span style="font-size: 9pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private byte[] targetMAC, gateMAC;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //B</span><span>的</span><span>MAC</span><span>地址，网关的</span><span>MAC</span><span>地址</span></div>
<div><span style="font-size: 9pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private byte[] String targetIp, String gateIp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //B</span><span>的</span><span>IP</span><span>地址，网关的</span><span>IP</span><span>地址</span></div>
<div><span style="font-size: 9pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /**</span></div>
<div><span style="font-size: 9pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; *</span><span>初始化设备</span></div>
<div><span style="font-size: 9pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; * JpcapCaptor.getDeviceList()</span><span>得到设备可能会有两个，其中一个必定是&#8220;</span><span>Generic </span></div>
<div><span style="font-size: 9pt; color: blue">*<span>dialup adapter</span></span><span>&#8221;，</span><span>这是</span><span>windows</span><span>系统的虚拟网卡，并非真正的硬件设备。</span></div>
<div><span style="font-size: 9pt">*</span><span>注意：在这里有一个小小的</span><span>BUG</span><span>，如果</span><span>JpcapCaptor.getDeviceList()</span><span>之前有类似</span><span>JFrame jf=new</span></div>
<div><span style="font-size: 9pt">*JFame</span><span>（）这类的语句会影响得到设备个数，只会得到真正的硬件设备，而不会出现虚拟网卡。</span></div>
<div><span style="font-size: 9pt">*</span><span>虚拟网卡只有</span><span>MAC</span><span>地址而没有</span><span>IP</span><span>地址，而且如果出现虚拟网卡，那么实际网卡的</span><span>MAC</span><span>将分</span></div>
<div><span style="font-size: 9pt">*</span><span>配给虚拟网卡，也就是说在程序中调用</span><span>device.</span> <span>mac_address</span><span>时得到的是</span><span>00 00 00 00 00 00</span><span>。</span></div>
<div><span style="font-size: 9pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; */</span></div>
<div><span style="font-size: 9pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private NetworkInterface getDevice() throws IOException {</span></div>
<div><span style="font-size: 9pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; devices = JpcapCaptor.getDeviceList();&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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //</span><span>获得设备列表</span></div>
<div><span style="font-size: 9pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; device = devices[0];&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;&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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //</span><span>只有一个设备</span></div>
<div><span style="font-size: 9pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; jpcap = JpcapCaptor.openDevice(device, 2000, false, 10000);&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //</span><span>打开与设备的连接</span></div>
<div><span style="font-size: 9pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; jpcap.setFilter(&#8220;ip&#8221;,true);&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;&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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //</span><span>只监听</span><span>B</span><span>的</span><span>IP</span><span>数据包</span></div>
<div><span style="font-size: 9pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; sender = captor.getJpcapSenderInstance();</span></div>
<div><span style="font-size: 9pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</span></div>
<div><span style="font-size: 9pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /**</span></div>
<div><span style="font-size: 9pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; *</span><span>修改</span><span>B</span><span>和网关的</span><span>ARP</span><span>表。因为网关会定时发数据包刷新自己和</span><span>B</span><span>的缓存表，所以必须每隔一</span></div>
<div><span style="font-size: 9pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; *</span><span>段时间就发一次包重新更改</span><span>B</span><span>和网关的</span><span>ARP</span><span>表。</span></div>
<div><span style="font-size: 9pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; *@</span><span>参数</span><span> targetMAC &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; B</span><span>的</span><span>MAC</span><span>地址，可通过</span><span>ARP</span><span>解析得到；</span></div>
<div><span style="font-size: 9pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; *@</span><span>参数</span><span> targetIp &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; B</span><span>的</span><span>IP</span><span>地址；</span></div>
<div><span style="font-size: 9pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; *@</span><span>参数</span><span> gateMAC &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span>网关的</span><span>MAC</span><span>地址；</span></div>
<div><span style="font-size: 9pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; *@</span><span>参数</span><span> gateIp&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span>网关的</span><span>IP;</span></div>
<div><span style="font-size: 9pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; */</span></div>
<div><span style="font-size: 9pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public changeARP(byte[] targetMAC, String targetIp,byte[] gateMAC, String gateIp)</span></div>
<div><span style="font-size: 9pt">&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; throws UnknownHostException,InterruptedException {</span></div>
<div><span style="font-size: 9pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this. targetMAC = &nbsp;targetMAC;</span></div>
<div><span style="font-size: 9pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this. targetIp = &nbsp;targetIp;</span></div>
<div><span style="font-size: 9pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this. gateMAC = gateMAC;</span></div>
<div><span style="font-size: 9pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this. gateIp = gateIp;</span></div>
<div><span style="font-size: 9pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; getDevice();</span></div>
<div><span style="font-size: 9pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; arpTarget = new ARPPacket();&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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //</span><span>修改</span><span>B</span><span>的</span><span>ARP</span><span>表的</span><span>ARP</span><span>包</span></div>
<div><span style="font-size: 9pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; arpTarget.hardtype = ARPPacket.HARDTYPE_ETHER;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //</span><span>选择以太网类型</span><span>(Ethernet)</span></div>
<div><span style="font-size: 9pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; arpTarget.prototype = ARPPacket.PROTOTYPE_IP;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //</span><span>选择</span><span>IP</span><span>网络协议类型</span></div>
<div><span style="font-size: 9pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; arpTarget.operation = ARPPacket.ARP_REPLY;&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><span>选择</span><span>REPLY</span><span>类型</span></div>
<div><span style="font-size: 9pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; arpTarget.hlen = 6;&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;&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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //MAC</span><span>地址长度固定</span><span>6</span><span>个字节</span></div>
<div><span style="font-size: 9pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; arpTarget.plen = 4;&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;&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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //IP</span><span>地址长度固定</span><span>4</span><span>个字节</span></div>
<div><span style="font-size: 9pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; arpTarget.sender_hardaddr = device.mac_address;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //A</span><span>的</span><span>MAC</span><span>地址</span></div>
<div><span style="font-size: 9pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; arpTarget.sender_protoaddr = InetAddress.getByName(gateIp).getAddress();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //</span><span>网关</span><span>IP</span></div>
<div><span style="font-size: 9pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; arpTarget.target_hardaddr = targetMAC;&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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //B</span><span>的</span><span>MAC</span><span>地址</span></div>
<div><span style="font-size: 9pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; arpTarget.target_protoaddr = InetAddress.getByName(targetIp).getAddress();&nbsp;&nbsp;&nbsp;&nbsp; //B</span><span>的</span><span>IP</span></div>
<div>&nbsp;</div>
<div><span style="font-size: 9pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; EthernetPacket ethToTarget = new EthernetPacket();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //</span><span>创建一个以太网头</span></div>
<div><span style="font-size: 9pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ethToTarget.frametype = EthernetPacket.ETHERTYPE_ARP;&nbsp;//</span><span>选择以太包类型</span></div>
<div><span style="font-size: 9pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ethToTarget.src_mac = device.mac_address;&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;&nbsp;&nbsp; //A</span><span>的</span><span>MAC</span><span>地址</span></div>
<div><span style="font-size: 9pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ethToTarget.dst_mac = targetMAC;&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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //B</span><span>的</span><span>MAC</span><span>地址</span></div>
<div><span style="font-size: 9pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; arpTarget.datalink = ethToTarget;&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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //</span><span>将以太头添加到</span><span>ARP</span><span>包前</span></div>
<div>&nbsp;</div>
<div><span style="font-size: 9pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; arpGate = new ARPPacket();&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;&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;&nbsp;&nbsp;&nbsp; //</span><span>修改网关</span><span>ARP</span><span>表的包</span></div>
<div><span style="font-size: 9pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; arpGate.hardtype = ARPPacket.HARDTYPE_ETHER;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //</span><span>跟以上相似，不再重复注析</span></div>
<div><span style="font-size: 9pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; arpGate.prototype = ARPPacket.PROTOTYPE_IP;</span></div>
<div><span style="font-size: 9pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; arpGate.operation = ARPPacket.ARP_REPLY;</span></div>
<div><span style="font-size: 9pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; arpGate.hlen = 6;</span></div>
<div><span style="font-size: 9pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; arpGate.plen = 4;</span></div>
<div><span style="font-size: 9pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; arpGate.sender_hardaddr = device.mac_address;</span></div>
<div><span style="font-size: 9pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; arpGate.sender_protoaddr = InetAddress.getByName(targetIp).getAddress();</span></div>
<div><span style="font-size: 9pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; arpGate.target_hardaddr = gateMAC;</span></div>
<div><span style="font-size: 9pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; arpGate.target_protoaddr = InetAddress.getByName(gateIp).getAddress();</span></div>
<div>&nbsp;</div>
<div><span style="font-size: 9pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; EthernetPacket ethToGate = new EthernetPacket();</span></div>
<div><span style="font-size: 9pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ethToGate.frametype = EthernetPacket.ETHERTYPE_ARP;</span></div>
<div><span style="font-size: 9pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ethToGate.src_mac = device.mac_address;</span></div>
<div><span style="font-size: 9pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ethToGate.dst_mac = gateMAC;</span></div>
<div><span style="font-size: 9pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; arpGate.datalink = ethToGate;</span></div>
<div><span style="font-size: 9pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></div>
<div><span style="font-size: 9pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; thread=new Thread(new Runnable(){&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;&nbsp;&nbsp; //</span><span>创建一个进程控制发包速度</span></div>
<div><span style="font-size: 9pt">&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; public void run() {</span></div>
<div><span style="font-size: 9pt">&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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; while (true) {</span></div>
<div><span style="font-size: 9pt">&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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; sender.sendPacket(arpTarget);</span></div>
<div><span style="font-size: 9pt">&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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; sender.sendPacket(arpGate);</span></div>
<div><span style="font-size: 9pt">&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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Thread.sleep(500);</span></div>
<div><span style="font-size: 9pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }).start();</span></div>
<div><span style="font-size: 9pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; recP();&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;&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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //</span><span>接收数据包并转发</span></div>
<div><span style="font-size: 9pt">}</span></div>
<div><span style="font-size: 9pt">/**</span></div>
<div><span style="font-size: 9pt">*</span><span>修改包的以太头，转发数据包</span></div>
<div><span style="font-size: 9pt">*</span><span>参数</span><span> packet&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span>收到的数据包</span></div>
<div><span style="font-size: 9pt">*</span><span>参数</span><span> changeMAC&nbsp;&nbsp;&nbsp;&nbsp; </span><span>要转发出去的目标</span></div>
<div><span style="font-size: 9pt">*/</span></div>
<div><span style="font-size: 9pt">private void send(Packet packet, byte[] changeMAC) {&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></div>
<div><span style="font-size: 9pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; EthernetPacket eth;</span></div>
<div><span style="font-size: 9pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (packet.datalink instanceof EthernetPacket) {</span></div>
<div><span style="font-size: 9pt">&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; eth = (EthernetPacket) packet.datalink;</span></div>
<div><span style="font-size: 9pt">&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; for (int i = 0; i &lt; 6; i++) {</span></div>
<div><span style="font-size: 9pt">&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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; eth.dst_mac[i] = changeMAC[i];&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //</span><span>修改包以太头，改变包的目标</span></div>
<div><span style="font-size: 9pt">&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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; eth.src_mac[i] = device.mac_address[i];&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //</span><span>源发送者为</span><span>A</span></div>
<div><span style="font-size: 9pt">&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; }</span></div>
<div><span style="font-size: 9pt">&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; sender.sendPacket(packet);</span></div>
<div><span style="font-size: 9pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</span></div>
<div><span style="font-size: 9pt">}</span></div>
<div><span style="font-size: 9pt">/**</span></div>
<div><span style="font-size: 9pt">*</span><span>打印接受到的数据包并转发</span></div>
<div><span style="font-size: 9pt">*/</span></div>
<div><span style="font-size: 9pt">public void recP(){</span></div>
<div><span style="font-size: 9pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; IPPacket ipPacket = null;</span></div>
<div><span style="font-size: 9pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; while(true){</span></div>
<div><span style="font-size: 9pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ipPacket = </span><span>（</span><span>IPPacket</span><span>）</span><span>jpcap.getPacket();</span></div>
<div><span style="font-size: 9pt">&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; System.out.println(ipPacket);</span></div>
<div><span style="font-size: 9pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (ipPacket.src_ip.getHostAddress().equals(targetIp))</span></div>
<div><span style="font-size: 9pt">&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;&nbsp;&nbsp;&nbsp;&nbsp; send(packet, gateMAC);</span></div>
<div><span style="font-size: 9pt">&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; else</span></div>
<div><span style="font-size: 9pt">&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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; send(packet, targetMAC);</span></div>
<div><span style="font-size: 9pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</span></div>
<div><span style="font-size: 9pt">}</span></div>
<div>&nbsp;</div>
<div>注意：这个例子只是为了说明问题，并没有考虑到程序的健壮性，所以并不一定能在任何一台机器任何一个系统上运行。</div>
&nbsp;<br />
<br />
<p id="TBPingURL">Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=1370905</p>
<img src ="http://www.blogjava.net/smildlzj/aggbug/162906.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/smildlzj/" target="_blank">smildlzj</a> 2007-11-24 23:41 <a href="http://www.blogjava.net/smildlzj/articles/162906.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>JPCAP——JAVA中的数据链路层控制 之一 </title><link>http://www.blogjava.net/smildlzj/articles/162904.html</link><dc:creator>smildlzj</dc:creator><author>smildlzj</author><pubDate>Sat, 24 Nov 2007 15:39:00 GMT</pubDate><guid>http://www.blogjava.net/smildlzj/articles/162904.html</guid><wfw:comment>http://www.blogjava.net/smildlzj/comments/162904.html</wfw:comment><comments>http://www.blogjava.net/smildlzj/articles/162904.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/smildlzj/comments/commentRss/162904.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/smildlzj/services/trackbacks/162904.html</trackback:ping><description><![CDATA[<p>&nbsp;半年前网络技术课的老师要我们做个ARP查询，老师是教人用winsock的，可我一味钻java，干着急，钻进java世界到处查，终于找到这么一个东西。 </p>
<p>然后做了一个ARP监听器，没想到被老师看上了，说是国内JPCAP研究的人不多，可以考虑写一篇论文，老师给我推荐发表。</p>
<p>于是有了这么一篇东西。不过现在还不知道老师发哪个刊物去了。。。老师说，还没回音。。</p>
<p>&nbsp;注：由于字数限制，分成2部分发。</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<div align="center"><strong><span>JPCAP</span></strong><strong><span>——</span></strong><strong><span>JAVA</span></strong><strong><span>中的数据链路层控制</span></strong></div>
<div align="center"><strong></strong></div>
<div><strong>&nbsp;</strong></div>
<div><strong>一．</strong><strong>JPCAP</strong><strong>简介</strong></div>
<div>众所周知，JAVA语言虽然在TCP/UDP传输方面给予了良好的定义，但对于网络层以下的控制，却是无能为力的。JPCAP扩展包弥补了这一点。</div>
<div>JPCAP实际上并非一个真正去实现对数据链路层的控制，而是一个中间件，JPCAP调用wincap/libpcap，而给JAVA语言提供一个公共的接口，从而实现了平台无关性。在官方网站上声明，JPCAP支持FreeBSD 3.x, Linux RedHat 6.1, Fedora Core 4, Solaris, and Microsoft Windows 2000/XP等系统。</div>
<div><strong>二．</strong><strong>JPCAP</strong><strong>机制</strong></div>
<div><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; JPCAP</span>的整个结构大体上跟wincap/libpcap是很相像的，例如NetworkInterface类对应wincap<span>的</span><span>typedef struct _ADAPTER&nbsp;&nbsp;ADAPTER</span><span>，</span><span>getDeviceList()</span><span>对应</span>pcap_findalldevs()等等。<span> JPCAP有16个类，下面就其中最重要的4个类做说明。</span></div>
<div><strong>&nbsp;</strong></div>
<div><strong><span>1．</span></strong><strong>NetworkInterface</strong></div>
<div>该类的每一个实例代表一个网络设备，一般就是网卡。这个类只有一些数据成员，除了继承自java.lang.Object的基本方法以外，没有定义其它方法。</div>
<div><strong>&nbsp;</strong></div>
<p>
<table style="width: 100%" cellspacing="0" cellpadding="0" width="100%" border="1">
    <tbody>
        <tr>
            <td style="border-right: #aca899 1pt inset; padding-right: 2.25pt; border-top: 1pt inset; padding-left: 2.25pt; background: white; padding-bottom: 2.25pt; border-left: 1pt inset; width: 100%; padding-top: 2.25pt; border-bottom: 1pt inset" width="100%" colspan="2">
            <div><strong><span>数据成员</span></strong></div>
            </td>
        </tr>
        <tr>
            <td style="padding-right: 2.25pt; padding-left: 2.25pt; background: white; padding-bottom: 2.25pt; width: 28.12%; padding-top: 2.25pt" valign="top" width="28%">
            <div align="right"><span>NetworkInterfaceAddress[]</span></div>
            </td>
            <td style="padding-right: 2.25pt; padding-left: 2.25pt; background: white; padding-bottom: 2.25pt; width: 71.88%; padding-top: 2.25pt" width="71%">
            <div align="left"><strong><span>addresses</span></strong></div>
            <div align="left"><span>&nbsp;&nbsp;&nbsp; </span><span>这个接口的网络地址。设定为数组应该是考虑到有些设备同时连接多条线路，例如路由器。但我们的PC机的网卡一般只有一条线路，所以我们一般取addresses[0]就够了。</span></div>
            </td>
        </tr>
        <tr>
            <td style="padding-right: 2.25pt; padding-left: 2.25pt; background: white; padding-bottom: 2.25pt; width: 28.12%; padding-top: 2.25pt" valign="top" width="28%">
            <div align="right"><span>&nbsp;java.lang.String</span></div>
            </td>
            <td style="padding-right: 2.25pt; padding-left: 2.25pt; background: white; padding-bottom: 2.25pt; width: 71.88%; padding-top: 2.25pt" width="71%">
            <div align="left"><strong><span>datalink_description</span></strong><span>.</span></div>
            <div align="left"><span>&nbsp;&nbsp;&nbsp; </span><span>数据链路层的描述。描述所在的局域网是什么网。例如，以太网（Ethernet）、无线LAN网（wireless LAN）、令牌环网(token ring)等等。</span></div>
            </td>
        </tr>
        <tr>
            <td style="padding-right: 2.25pt; padding-left: 2.25pt; background: white; padding-bottom: 2.25pt; width: 28.12%; padding-top: 2.25pt" valign="top" width="28%">
            <div align="right"><span>&nbsp;java.lang.String</span></div>
            </td>
            <td style="padding-right: 2.25pt; padding-left: 2.25pt; background: white; padding-bottom: 2.25pt; width: 71.88%; padding-top: 2.25pt" width="71%">
            <div align="left"><strong><span>datalink_name </span></strong></div>
            <div align="left"><span>&nbsp;&nbsp; </span><span>该网络设备所对应数据链路层的名称。具体来说，例如Ethernet10M、<span>100M、1000M等等。</span></span></div>
            </td>
        </tr>
        <tr>
            <td style="padding-right: 2.25pt; padding-left: 2.25pt; background: white; padding-bottom: 2.25pt; width: 28.12%; padding-top: 2.25pt" valign="top" width="28%">
            <div align="right"><span>&nbsp;java.lang.String</span></div>
            </td>
            <td style="padding-right: 2.25pt; padding-left: 2.25pt; background: white; padding-bottom: 2.25pt; width: 71.88%; padding-top: 2.25pt" width="71%">
            <div align="left"><strong><span>description</span></strong></div>
            <div align="left"><span>&nbsp;&nbsp; </span><span>网卡是XXXX牌子XXXX型号之类的描述。例如我的网卡描述：Realtek RTL8169/8110 Family Gigabit Ethernet NIC </span></div>
            </td>
        </tr>
        <tr>
            <td style="padding-right: 2.25pt; padding-left: 2.25pt; background: white; padding-bottom: 2.25pt; width: 28.12%; padding-top: 2.25pt" valign="top" width="28%">
            <div align="right"><span>&nbsp;boolean</span></div>
            </td>
            <td style="padding-right: 2.25pt; padding-left: 2.25pt; background: white; padding-bottom: 2.25pt; width: 71.88%; padding-top: 2.25pt" width="71%">
            <div align="left"><strong><span>Loopback</span></strong></div>
            <div align="left"><span>&nbsp;&nbsp;&nbsp; </span><span>标志这个设备是否loopback设备。</span></div>
            </td>
        </tr>
        <tr>
            <td style="padding-right: 2.25pt; padding-left: 2.25pt; background: white; padding-bottom: 2.25pt; width: 28.12%; padding-top: 2.25pt" valign="top" width="28%">
            <div align="right"><span>&nbsp;byte[]</span></div>
            </td>
            <td style="padding-right: 2.25pt; padding-left: 2.25pt; background: white; padding-bottom: 2.25pt; width: 71.88%; padding-top: 2.25pt" width="71%">
            <div align="left"><strong><span>mac_address</span></strong></div>
            <div align="left"><span>&nbsp;&nbsp;&nbsp;</span><span>网卡的MAC地址，6个字节。</span></div>
            </td>
        </tr>
        <tr>
            <td style="padding-right: 2.25pt; padding-left: 2.25pt; background: white; padding-bottom: 2.25pt; width: 28.12%; padding-top: 2.25pt" valign="top" width="28%">
            <div align="right"><span>&nbsp;java.lang.String</span></div>
            </td>
            <td style="padding-right: 2.25pt; padding-left: 2.25pt; background: white; padding-bottom: 2.25pt; width: 71.88%; padding-top: 2.25pt" width="71%">
            <div align="left"><strong><span>Name</span></strong></div>
            <div align="left"><span>&nbsp;&nbsp;&nbsp; </span><span>这个设备的名称。例如我的网卡名称：\Device\NPF_{3CE5FDA5-E15D-4F87-B217-255BCB351CD5}</span></div>
            </td>
        </tr>
    </tbody>
</table>
</p>
<div><strong>&nbsp;</strong></div>
<div><strong><span>2．</span></strong><strong>JpcapCaptor</strong></div>
<div>该类提供了一系列静态方法实现一些基本的功能。该类一个实例代表建立了一个与指定设备的链接，可以通过该类的实例来控制设备，例如设定网卡模式、设定过滤关键字等等。</div>
<div>&nbsp;</div>
<p>
<table style="width: 100%" cellspacing="0" cellpadding="0" width="100%" border="1">
    <tbody>
        <tr>
            <td style="border-right: #aca899 1pt inset; padding-right: 2.25pt; border-top: 1pt inset; padding-left: 2.25pt; background: white; padding-bottom: 2.25pt; border-left: 1pt inset; width: 100%; padding-top: 2.25pt; border-bottom: 1pt inset" valign="top" width="100%" colspan="2">
            <div><code><strong><span>数据成员</span></strong></code></div>
            </td>
        </tr>
        <tr>
            <td style="padding-right: 2.25pt; padding-left: 2.25pt; background: white; padding-bottom: 2.25pt; width: 28.48%; padding-top: 2.25pt" valign="top" width="28%">
            <div align="right"><code><span>&nbsp;int</span></code></div>
            </td>
            <td style="padding-right: 2.25pt; padding-left: 2.25pt; background: white; padding-bottom: 2.25pt; width: 71.52%; padding-top: 2.25pt" width="71%">
            <div><code><strong><span>dropped_packets&nbsp;</span></strong></code></div>
            <div><span style="font-size: 9pt">抛弃的包的数目。</span></div>
            </td>
        </tr>
        <tr>
            <td style="padding-right: 2.25pt; padding-left: 2.25pt; background: white; padding-bottom: 2.25pt; width: 28.48%; padding-top: 2.25pt" valign="top" width="28%">
            <div align="right"><code><span>protected &nbsp;int</span></code></div>
            </td>
            <td style="padding-right: 2.25pt; padding-left: 2.25pt; background: white; padding-bottom: 2.25pt; width: 71.52%; padding-top: 2.25pt" width="71%">
            <div><code><strong><span>ID</span></strong></code></div>
            <div><code><strong><span>&nbsp;&nbsp;&nbsp; </span></strong></code><span>这个数据成员在官方文档中并没有做任何说明，查看</span><span>JPCAP</span><span>源代码可以发现这个</span><span>ID</span><span>实际上在其</span><span>JNI</span><span>的</span><span>C</span><span>代码部分传进来的，这类本身并没有做出定义，所以是供其内部使用的。实际上在对</span><span>JpcapCator</span><span>实例的使用中也没有办法调用此数据成员。</span></div>
            </td>
        </tr>
        <tr>
            <td style="padding-right: 2.25pt; padding-left: 2.25pt; background: white; padding-bottom: 2.25pt; width: 28.48%; padding-top: 2.25pt" valign="top" width="28%">
            <div align="right"><code><span>protected static&nbsp;boolean[]</span></code></div>
            </td>
            <td style="padding-right: 2.25pt; padding-left: 2.25pt; background: white; padding-bottom: 2.25pt; width: 71.52%; padding-top: 2.25pt" width="71%">
            <div><code><strong><span>instanciatedFlag</span></strong></code></div>
            <div><span>&nbsp;&nbsp; </span><span>同样在官方文档中没有做任何说明，估计其为供内部使用。</span></div>
            </td>
        </tr>
        <tr>
            <td style="padding-right: 2.25pt; padding-left: 2.25pt; background: white; padding-bottom: 2.25pt; width: 28.48%; padding-top: 2.25pt" valign="top" width="28%">
            <div align="right"><code><span>protected static&nbsp;int</span></code></div>
            </td>
            <td style="padding-right: 2.25pt; padding-left: 2.25pt; background: white; padding-bottom: 2.25pt; width: 71.52%; padding-top: 2.25pt" width="71%">
            <div><code><strong><span>MAX_NUMBER_OF_INSTANCE</span></strong></code></div>
            <div><span style="font-size: 9pt">同样在官方文档中没有做任何说明，估计其为供内部使用。</span></div>
            </td>
        </tr>
        <tr>
            <td style="padding-right: 2.25pt; padding-left: 2.25pt; background: white; padding-bottom: 2.25pt; width: 28.48%; padding-top: 2.25pt" valign="top" width="28%">
            <div align="right"><code><span>int</span></code></div>
            </td>
            <td style="padding-right: 2.25pt; padding-left: 2.25pt; background: white; padding-bottom: 2.25pt; width: 71.52%; padding-top: 2.25pt" width="71%">
            <div><code><strong><span>received_packets</span></strong></code><span><br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span>收到的包的数目</span></div>
            </td>
        </tr>
        <tr>
            <td style="border-right: #aca899 1pt inset; padding-right: 2.25pt; border-top: 1pt inset; padding-left: 2.25pt; background: white; padding-bottom: 2.25pt; border-left: 1pt inset; width: 100%; padding-top: 2.25pt; border-bottom: 1pt inset" valign="top" width="100%" colspan="2">
            <div><code><strong><span>方法成员</span></strong></code></div>
            </td>
        </tr>
        <tr>
            <td style="padding-right: 2.25pt; padding-left: 2.25pt; background: white; padding-bottom: 2.25pt; width: 28.48%; padding-top: 2.25pt" valign="top" width="28%">
            <div align="right"><code><span>static&nbsp;NetworkInterface[]</span></code></div>
            </td>
            <td style="padding-right: 2.25pt; padding-left: 2.25pt; background: white; padding-bottom: 2.25pt; width: 71.52%; padding-top: 2.25pt" width="71%">
            <div><code><strong><span>getDeviceList</span></strong></code><code><span>()</span></code><span> <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span>返回一个网络设备列表。</span></div>
            </td>
        </tr>
        <tr>
            <td style="padding-right: 2.25pt; padding-left: 2.25pt; background: white; padding-bottom: 2.25pt; width: 28.48%; padding-top: 2.25pt" valign="top" width="28%">
            <div align="right"><code><span>static&nbsp;JpcapCaptor</span></code></div>
            </td>
            <td style="padding-right: 2.25pt; padding-left: 2.25pt; background: white; padding-bottom: 2.25pt; width: 71.52%; padding-top: 2.25pt" width="71%">
            <div><code><strong><span>openDevice</span></strong></code><code><span>(NetworkInterface interface, int&nbsp;snaplen, boolean&nbsp;promisc, int&nbsp;to_ms)</span></code><span> <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span>创建一个与指定设备的连接并返回该连接。注意，以上两个方法都是静态方法。</span></div>
            <div><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Interface</span><span>：要打开连接的设备的实例；</span></div>
            <div><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Snaplen</span><span>：这个是比较容易搞混的一个参数。其实这个参数不是限制只能捕捉多少数据包，而是限制每一次收到一个数据包，只提取该数据包中前多少字节；</span></div>
            <div><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Promisc</span><span>：设置是否混杂模式。处于混杂模式将接收所有数据包，若之后又调用了包过滤函数</span><span>setFilter()</span><span>将不起任何作用；</span></div>
            <div><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; To_ms</span><span>：这个参数主要用于</span><span>processPacket()</span><span>方法，指定超时的时间；</span></div>
            </td>
        </tr>
        <tr>
            <td style="padding-right: 2.25pt; padding-left: 2.25pt; background: white; padding-bottom: 2.25pt; width: 28.48%; padding-top: 2.25pt" valign="top" width="28%">
            <div align="right"><code><span>&nbsp;void</span></code></div>
            </td>
            <td style="padding-right: 2.25pt; padding-left: 2.25pt; background: white; padding-bottom: 2.25pt; width: 71.52%; padding-top: 2.25pt" width="71%">
            <div><code><strong><span>Close</span></strong></code>()<span><br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span>关闭调用该方法的设备的连接，相对于</span><span>openDivece()</span><span>打开连接。</span></div>
            </td>
        </tr>
        <tr>
            <td style="padding-right: 2.25pt; padding-left: 2.25pt; background: white; padding-bottom: 2.25pt; width: 28.48%; padding-top: 2.25pt" valign="top" width="28%">
            <div align="right"><code><span>&nbsp;JpcapSender</span></code></div>
            </td>
            <td style="padding-right: 2.25pt; padding-left: 2.25pt; background: white; padding-bottom: 2.25pt; width: 71.52%; padding-top: 2.25pt" width="71%">
            <div><code><strong><span>getJpcapSenderInstance</span></strong></code><code><span>()</span></code><span> <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span>该返回一个</span><span>JpcapSender</span><span>实例，</span><span>JpcapSender</span><span>类是专门用于控制设备的发送数据包的功能的类。</span></div>
            </td>
        </tr>
        <tr>
            <td style="padding-right: 2.25pt; padding-left: 2.25pt; background: white; padding-bottom: 2.25pt; width: 28.48%; padding-top: 2.25pt" valign="top" width="28%">
            <div align="right"><code><span>&nbsp;Packet</span></code></div>
            </td>
            <td style="padding-right: 2.25pt; padding-left: 2.25pt; background: white; padding-bottom: 2.25pt; width: 71.52%; padding-top: 2.25pt" width="71%">
            <div><code><strong><span>getPacket</span></strong></code><code><span>()</span></code><span> <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span>捕捉并返回一个数据包。这是</span><span>JpcapCaptor</span><span>实例中四种捕捉包的方法之一。</span></div>
            </td>
        </tr>
        <tr>
            <td style="padding-right: 2.25pt; padding-left: 2.25pt; background: white; padding-bottom: 2.25pt; width: 28.48%; padding-top: 2.25pt" valign="top" width="28%">
            <div align="right"><code><span>&nbsp;int</span></code></div>
            </td>
            <td style="padding-right: 2.25pt; padding-left: 2.25pt; background: white; padding-bottom: 2.25pt; width: 71.52%; padding-top: 2.25pt" width="71%">
            <div><code><strong><span>loopPacket</span></strong></code><code><span>(int&nbsp;count, PacketReceiver handler)</span></code><span> <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span>捕捉指定数目的数据包，并交由实现了</span><span>PacketReceiver</span><span>接口的类的实例处理，并返回捕捉到的数据包数目。如果</span><span>count</span><span>参数设为－</span><span>1</span><span>，那么无限循环地捕捉数据。</span></div>
            <div><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span>这个方法不受超时的影响。还记得</span><span>openDivice()</span><span>中的</span><span>to_ms</span><span>参数么？那个参数对这个方法没有影响，如果没有捕捉到指定数目数据包，那么这个方法将一直阻塞等待。</span></div>
            <div><span style="font-size: 9pt">PacketReceiver</span><span>中只有一个抽象方法</span><span>void receive(Packet p)</span><span>。</span></div>
            </td>
        </tr>
        <tr>
            <td style="padding-right: 2.25pt; padding-left: 2.25pt; background: white; padding-bottom: 2.25pt; width: 28.48%; padding-top: 2.25pt" valign="top" width="28%">
            <div align="right"><code><span>&nbsp;int</span></code></div>
            </td>
            <td style="padding-right: 2.25pt; padding-left: 2.25pt; background: white; padding-bottom: 2.25pt; width: 71.52%; padding-top: 2.25pt" width="71%">
            <div><code><strong><span>processPacket</span></strong></code><code><span>(int&nbsp;count, PacketReceiver handler)</span></code><span> <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span>跟</span><code><strong><span>loopPacket</span></strong></code><code><span>()</span></code><code><span>功能一样，唯一的区别是这个方法受超时的影响，超过指定时间自动返回捕捉到数据包的数目。</span></code></div>
            </td>
        </tr>
        <tr>
            <td style="padding-right: 2.25pt; padding-left: 2.25pt; background: white; padding-bottom: 2.25pt; width: 28.48%; padding-top: 2.25pt" valign="top" width="28%">
            <div align="right"><code><span>&nbsp;int</span></code></div>
            </td>
            <td style="padding-right: 2.25pt; padding-left: 2.25pt; background: white; padding-bottom: 2.25pt; width: 71.52%; padding-top: 2.25pt" width="71%">
            <div><code><strong><span>dispatchPacket</span></strong></code><code><span>(int&nbsp;count, PacketReceiver&nbsp;handler)</span></code><span><br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span>跟</span><code><strong><span>processPacket</span></strong></code><code><span>()</span></code><code><span>功能一样，区别是这个方法可以处于&#8220;non-blocking&#8221;模式工作，在这种模式下dispatchPacket()可能立即返回，即使没有捕捉到任何数据包。</span></code></div>
            </td>
        </tr>
        <tr>
            <td style="padding-right: 2.25pt; padding-left: 2.25pt; background: white; padding-bottom: 2.25pt; width: 28.48%; padding-top: 2.25pt" valign="top" width="28%">
            <div align="right"><code><span>&nbsp;void</span></code></div>
            </td>
            <td style="padding-right: 2.25pt; padding-left: 2.25pt; background: white; padding-bottom: 2.25pt; width: 71.52%; padding-top: 2.25pt" width="71%">
            <div><code><strong><span>setFilter</span></strong></code><code><span>(java.lang.String&nbsp;condition, boolean&nbsp;optimize)</span></code><span> <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.</span><code><span>condition</span></code><code><span>：</span></code><span>设定要提取的包的关键字。</span></div>
            <div><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><code><span>Optimize</span></code><code><span>：这个参数在说明文档以及源代码中都没有说明，只是说这个参数如果为真，那么过滤器将处于优化模式。</span></code></div>
            </td>
        </tr>
        <tr>
            <td style="padding-right: 2.25pt; padding-left: 2.25pt; background: white; padding-bottom: 2.25pt; width: 28.48%; padding-top: 2.25pt" valign="top" width="28%">
            <div align="right"><code><span>&nbsp;void</span></code></div>
            </td>
            <td style="padding-right: 2.25pt; padding-left: 2.25pt; background: white; padding-bottom: 2.25pt; width: 71.52%; padding-top: 2.25pt" width="71%">
            <div><code><strong><span>setNonBlockingMode</span></strong></code><code><span>(boolean&nbsp;nonblocking)</span></code></div>
            <div><span>&nbsp;&nbsp;&nbsp;&nbsp; </span><span>如果值为&#8220;</span><span>true</span><span>&#8221;，那么设定为&#8220;</span><span>non-blocking</span><span>&#8221;模式。</span></div>
            </td>
        </tr>
        <tr>
            <td style="padding-right: 2.25pt; padding-left: 2.25pt; background: white; padding-bottom: 2.25pt; width: 28.48%; padding-top: 2.25pt" valign="top" width="28%">
            <div align="right"><code><span>&nbsp;void</span></code></div>
            </td>
            <td style="padding-right: 2.25pt; padding-left: 2.25pt; background: white; padding-bottom: 2.25pt; width: 71.52%; padding-top: 2.25pt" width="71%">
            <div><code><strong><span>breakLoop</span></strong></code>()</div>
            <div><span>&nbsp;&nbsp;&nbsp;&nbsp; </span><span>当调用</span><span>processPacket()</span><span>和</span><span>loopPacket()</span><span>后，再调用这个方法可以强制让</span><span>processPacket()</span><span>和</span><span>loopPacket()</span><span>停止。</span></div>
            </td>
        </tr>
    </tbody>
</table>
</p>
<div><strong>&nbsp;</strong></div>
<div><strong><span>3．</span></strong><strong>JpcapSender</strong></div>
<div>该类专门用于控制数据包的发送。</div>
<div>&nbsp;</div>
<p>
<table style="width: 100%" cellspacing="0" cellpadding="0" width="100%" border="1">
    <tbody>
        <tr>
            <td style="border-right: #aca899 1pt inset; padding-right: 2.25pt; border-top: 1pt inset; padding-left: 2.25pt; background: white; padding-bottom: 2.25pt; border-left: 1pt inset; width: 100%; padding-top: 2.25pt; border-bottom: 1pt inset" valign="top" width="100%" colspan="2">
            <div><code><strong><span>方法成员</span></strong></code></div>
            </td>
        </tr>
        <tr>
            <td style="padding-right: 2.25pt; padding-left: 2.25pt; background: white; padding-bottom: 2.25pt; width: 19.7%; padding-top: 2.25pt" valign="top" width="19%">
            <div align="right"><code><span>&nbsp;void</span></code></div>
            </td>
            <td style="padding-right: 2.25pt; padding-left: 2.25pt; background: white; padding-bottom: 2.25pt; padding-top: 2.25pt">
            <div><code><strong><span>close</span></strong></code><code><span>()</span></code><span> <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span>强制关闭这个连接。</span></div>
            </td>
        </tr>
        <tr>
            <td style="padding-right: 2.25pt; padding-left: 2.25pt; background: white; padding-bottom: 2.25pt; width: 19.7%; padding-top: 2.25pt" valign="top" width="19%">
            <div align="right"><code><span>static&nbsp;JpcapSender</span></code></div>
            </td>
            <td style="padding-right: 2.25pt; padding-left: 2.25pt; background: white; padding-bottom: 2.25pt; padding-top: 2.25pt">
            <div><code><strong><span>openRawSocket</span></strong></code><code><span>()</span></code></div>
            <div><span>&nbsp;&nbsp;&nbsp;&nbsp; </span><span>这个方法返回的</span><span>JpcapSender</span><span>实例发送数据包时将自动填写数据链路层头部分。</span></div>
            </td>
        </tr>
        <tr>
            <td style="padding-right: 2.25pt; padding-left: 2.25pt; background: white; padding-bottom: 2.25pt; width: 19.7%; padding-top: 2.25pt" valign="top" width="19%">
            <div align="right"><code><span>&nbsp;void</span></code></div>
            </td>
            <td style="padding-right: 2.25pt; padding-left: 2.25pt; background: white; padding-bottom: 2.25pt; padding-top: 2.25pt">
            <div><code><strong><span>sendPacket</span></strong></code><code><span>(Packet packet)</span></code><span> <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;JpcapSender</span><span>最重要的功能，发送数据包。需要注意的是，如果调用这个方法的实例是由</span><strong><span>JpcapCaptor</span></strong><span>的</span><code><strong><span>getJpcapSenderInstance</span></strong></code><code><span>()</span></code><code><span>得到的话，需要自己设定数据链路层的头，而如果是由上面的<strong>openRawSocket</strong>()</span></code><span>得到的话，那么无需也不能设置，数据链路层的头部将由系统自动生成。</span></div>
            </td>
        </tr>
    </tbody>
</table>
</p>
<div><strong>&nbsp;</strong></div>
<div><strong><span>4．</span></strong><strong>Packet</strong></div>
<div>这个是所有其它数据包类的父类。Jpcap所支持的数据包有：<br />
<span>ARPPacket</span><span>、</span><span>DatalinkPacket</span><span>、</span><span>EthernetPacket</span><span>、</span><span>ICMPPacket</span><span>、</span><span>IPPacket</span><span>、</span><span>TCPPacket</span><span>、</span><span>UDPPacket<br />
<br />
自:http://hzxdark.javaeye.com/blog/35956<br />
</span></div>
<img src ="http://www.blogjava.net/smildlzj/aggbug/162904.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/smildlzj/" target="_blank">smildlzj</a> 2007-11-24 23:39 <a href="http://www.blogjava.net/smildlzj/articles/162904.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>用HttpClient来模拟浏览器GET POST</title><link>http://www.blogjava.net/smildlzj/articles/161977.html</link><dc:creator>smildlzj</dc:creator><author>smildlzj</author><pubDate>Tue, 20 Nov 2007 15:52:00 GMT</pubDate><guid>http://www.blogjava.net/smildlzj/articles/161977.html</guid><wfw:comment>http://www.blogjava.net/smildlzj/comments/161977.html</wfw:comment><comments>http://www.blogjava.net/smildlzj/articles/161977.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/smildlzj/comments/commentRss/161977.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/smildlzj/services/trackbacks/161977.html</trackback:ping><description><![CDATA[<p><font size="4">一般的情况下我们都是使用IE或者Navigator浏览器来访问一个WEB服务器，用来浏览页面查看信息或者提交一些数据等等。所访问的这些页面有的仅仅是一些普通的页面，有的需要用户登录后方可使用，或者需要认证以及是一些通过加密方式传输，例如HTTPS。目前我们使用的浏览器处理这些情况都不会构成问题。不过你可能在某些时候需要通过程序来访问这样的一些页面，比如从别人的网页中&#8220;偷&#8221;一些数据；利用某些站点提供的页面来完成某种功能，例如说我们想知道某个手机号码的归属地而我们自己又没有这样的数据，因此只好借助其他公司已有的网站来完成这个功能，这个时候我们需要向网页提交手机号码并从返回的页面中解析出我们想要的数据来。如果对方仅仅是一个很简单的页面，那我们的程序会很简单，本文也就没有必要大张旗鼓的在这里浪费口舌。但是考虑到一些服务授权的问题，很多公司提供的页面往往并不是可以通过一个简单的URL就可以访问的，而必须经过注册然后登录后方可使用提供服务的页面，这个时候就涉及到COOKIE问题的处理。我们知道目前流行的***页技术例如ASP、JSP无不是通过COOKIE来处理会话信息的。为了使我们的程序能使用别人所提供的服务页面，就要求程序首先登录后再访问服务页面，这过程就需要自行处理cookie，想想当你用java.net.HttpURLConnection来完成这些功能时是多么恐怖的事情啊！况且这仅仅是我们所说的顽固的WEB服务器中的一个很常见的&#8220;顽固&#8221;！再有如通过HTTP来上传文件呢？不需要头疼，这些问题有了&#8220;它&#8221;就很容易解决了！ </font></p>
<p><font size="4">我们不可能列举所有可能的顽固，我们会针对几种最常见的问题进行处理。当然了，正如前面说到的，如果我们自己使用java.net.HttpURLConnection来搞定这些问题是很恐怖的事情，因此在开始之前我们先要介绍一下一个开放源码的项目，这个项目就是Apache开源组织中的httpclient，它隶属于Jakarta的commons项目，目前的版本是2.0RC2。commons下本来已经有一个net的子项目，但是又把httpclient单独提出来，可见http服务器的访问绝非易事。</font></p>
<p><font size="4">Commons-httpclient项目就是专门设计来简化HTTP客户端与服务器进行各种通讯编程。通过它可以让原来很头疼的事情现在轻松的解决，例如你不再管是HTTP或者HTTPS的通讯方式，告诉它你想使用HTTPS方式，剩下的事情交给httpclient替你完成。本文会针对我们在编写HTTP客户端程序时经常碰到的几个问题进行分别介绍如何使用httpclient来解决它们，为了让读者更快的熟悉这个项目我们最开始先给出一个简单的例子来读取一个网页的内容，然后循序渐进解决掉前进中的所形侍狻?/font&gt;
<p><font size="4">1． 读取网页(HTTP/HTTPS)内容</font></p>
<p><font size="4">下面是我们给出的一个简单的例子用来访问某个页面</font></p>
<p><font size="4">/*</font></p>
<p><font size="4">&nbsp;* Created on 2003-12-14 by Liudong</font></p>
<p><font size="4">&nbsp;*/</font></p>
<p><font size="4">package http.demo;</font></p>
<p><font size="4">&nbsp;</font></p>
<p><font size="4">import java.io.IOException;</font></p>
<p><font size="4">&nbsp;</font></p>
<p><font size="4">import org.apache.commons.httpclient.*;</font></p>
<p><font size="4">import org.apache.commons.httpclient.methods.*;</font></p>
<p><font size="4">/**</font></p>
<p><font size="4">&nbsp;* 最简单的HTTP客户端,用来演示通过GET或者POST方式访问某个页面</font></p>
<p><font size="4">&nbsp;* @author Liudong</font></p>
<p><font size="4">&nbsp;*/</font></p>
<p><font size="4">public class SimpleClient {</font></p>
<p><font size="4">&nbsp;</font></p>
<p><font size="4">&nbsp;&nbsp;&nbsp; public static void main(String[] args) throws IOException</font></p>
<p><font size="4">&nbsp;&nbsp;&nbsp; {</font></p>
<p><font size="4">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; HttpClient client = new HttpClient();&nbsp;&nbsp;&nbsp; </font></p>
<p><font size="4">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //设置代理服务器地址和端口&nbsp;&nbsp;&nbsp;&nbsp; </font></p>
<p><font size="4">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //client.getHostConfiguration().setProxy("proxy_host_addr",proxy_port);</font></p>
<p><font size="4">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //使用GET方法，如果服务器需要通过HTTPS连接，那只需要将下面URL中的http换成https</font></p>
<p><font size="4">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; HttpMethod method = new GetMethod("</font><a href="http://java.sun.com/"><font size="4">http://java.sun.com</font></a><font size="4">"); </font></p>
<p><font size="4">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //使用POST方法</font></p>
<p><font size="4">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //HttpMethod method = new PostMethod("</font><a href="http://java.sun.com/"><font size="4">http://java.sun.com</font></a><font size="4">"); </font></p>
<p><font size="4">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; client.executeMethod(method);</font></p>
<p><font size="4">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //打印服务器返回的状态</font></p>
<p><font size="4">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println(method.getStatusLine());</font></p>
<p><font size="4">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //打印返回的信息</font></p>
<p><font size="4">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println(method.getResponseBodyAsString());</font></p>
<p><font size="4">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //释放连接</font></p>
<p><font size="4">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; method.releaseConnection();</font></p>
<p><font size="4">&nbsp;&nbsp;&nbsp; }<br />
}</font></p>
<p><font size="4">&nbsp;</font></p>
<p><font size="4">在这个例子中首先创建一个HTTP客户端(HttpClient)的实例，然后选择提交的方法是GET或者POST，最后在HttpClient实例上执行提交的方法，最后从所选择的提交方法中读取服务器反馈回来的结果。这就是使用HttpClient的基本流程。其实用一行代码也就可以搞定整个请求的过程，非常的简单！</font></p>
<p><br />
<font size="4">2． 以GET或者POST方式向网页提交参数</font></p>
<p><font size="4">其实前面一个最简单的示例中我们已经介绍了如何使用GET或者POST方式来请求一个页面，本小节与之不同的是多了提交时设定页面所需的参数，我们知道如果是GET的请求方式，那么所有参数都直接放到页面的URL后面用问号与页面地址隔开，每个参数用&amp;隔开，例如：</font><a href="http://java.sun.com/?name=liudong&amp;mobile=123456"><font size="4">http://java.sun.com?name=liudong&amp;mobile=123456</font></a><font size="4">，但是当使用POST方法时就会稍微有一点点麻烦。本小节的例子演示向如何查询手机号码所在的城市，代码如下：</font></p>
<p><font size="4">&nbsp;</font></p>
<p><font size="4">/*</font></p>
<p><font size="4">&nbsp;* Created on 2003-12-7 by Liudong</font></p>
<p><font size="4">&nbsp;*/</font></p>
<p><font size="4">package http.demo;</font></p>
<p><font size="4">&nbsp;</font></p>
<p><font size="4">import java.io.IOException;</font></p>
<p><font size="4">&nbsp;</font></p>
<p><font size="4">import org.apache.commons.httpclient.*;</font></p>
<p><font size="4">import org.apache.commons.httpclient.methods.*;</font></p>
<p><font size="4">/**</font></p>
<p><font size="4">&nbsp;* 提交参数演示</font></p>
<p><font size="4">&nbsp;* 该程序连接到一个用于查询手机号码所属地的页面</font></p>
<p><font size="4">&nbsp;* 以便查询号码段1330227所在的省份以及城市</font></p>
<p><font size="4">&nbsp;* @author Liudong</font></p>
<p><font size="4">&nbsp;*/</font></p>
<p><font size="4">public class SimpleHttpClient {</font></p>
<p><font size="4">&nbsp;</font></p>
<p><font size="4">&nbsp;&nbsp;&nbsp; public static void main(String[] args) throws IOException</font></p>
<p><font size="4">&nbsp;&nbsp;&nbsp; {</font></p>
<p><font size="4">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; HttpClient client = new HttpClient();</font></p>
<p><font size="4">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; client.getHostConfiguration().setHost("</font><a href="http://www.imobile.com.cn/"><font size="4">www.imobile.com.cn</font></a><font size="4">", 80, "http");</font></p>
<p><font size="4">&nbsp;</font></p>
<p><font size="4">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; HttpMethod method = getPostMethod();//使用POST方式提交数据</font></p>
<p><font size="4">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; client.executeMethod(method);</font></p>
<p><font size="4">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //打印服务器返回的状态</font></p>
<p><font size="4">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println(method.getStatusLine());</font></p>
<p><font size="4">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //打印结果页面</font></p>
<p><font size="4">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; String response =</font></p>
<p><font size="4">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; new String(method.getResponseBodyAsString().getBytes("8859_1"));</font></p>
<p><font size="4">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //打印返回的信息</font></p>
<p><font size="4">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println(response);</font></p>
<p><font size="4">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; method.releaseConnection();</font></p>
<p><font size="4">&nbsp;&nbsp;&nbsp; }</font></p>
<p><font size="4">&nbsp;&nbsp;&nbsp; /**</font></p>
<p><font size="4">&nbsp;&nbsp;&nbsp;&nbsp; * 使用GET方式提交数据</font></p>
<p><font size="4">&nbsp;&nbsp;&nbsp;&nbsp; * @return</font></p>
<p><font size="4">&nbsp;&nbsp;&nbsp;&nbsp; */</font></p>
<p><font size="4">&nbsp;&nbsp;&nbsp; private static HttpMethod getGetMethod(){</font></p>
<p><font size="4">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return new GetMethod("/simcard.php?simcard=1330227");</font></p>
<p><font size="4">&nbsp;&nbsp;&nbsp; }</font></p>
<p><font size="4">&nbsp;&nbsp;&nbsp; /**</font></p>
<p><font size="4">&nbsp;&nbsp;&nbsp;&nbsp; * 使用POST方式提交数据</font></p>
<p><font size="4">&nbsp;&nbsp;&nbsp;&nbsp; * @return</font></p>
<p><font size="4">&nbsp;&nbsp;&nbsp;&nbsp; */</font></p>
<p><font size="4">&nbsp;&nbsp;&nbsp; private static HttpMethod getPostMethod(){</font></p>
<p><font size="4">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; PostMethod post = new PostMethod("/simcard.php");</font></p>
<p><font size="4">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; NameValuePair simcard = new NameValuePair("simcard","1330227");</font></p>
<p><font size="4">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; post.setRequestBody(new NameValuePair[] { simcard});</font></p>
<p><font size="4">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return post;</font></p>
<p><font size="4">&nbsp;&nbsp;&nbsp; }</font></p>
<p><font size="4">}</font></p>
<p><font size="4">在上面的例子中页面</font><a href="http://www.imobile.com.cn/simcard.php"><font size="4">http://www.imobile.com.cn/simcard.php</font></a><font size="4">需要一个参数是simcard，这个参数值为手机号码段，即手机号码的前七位，服务器会返回提交的手机号码对应的省份、城市以及其他详细信息。GET的提交方法只需要在URL后加入参数信息，而POST则需要通过NameValuePair类来设置参数名称和它所对应的值</font></p>
<p><font size="4">3． 处理页面重定向</font></p>
<p><font size="4">在JSP/Servlet编程中response.sendRedirect方法就是使用HTTP协议中的重定向机制。它与JSP中的&lt;jsp:forward &#8230;&gt;的区别在于后者是在服务器中实现页面的跳转，也就是说应用容器加载了所要跳转的页面的内容并返回给客户端；而前者是返回一个状态码，这些状态码的可能值见下表，然后客户端读取需要跳转到的页面的URL并重新加载新的页面。就是这样一个过程，所以我们编程的时候就要通过HttpMethod.getStatusCode()方法判断返回值是否为下表中的某个值来判断是否需要跳转。如果已经确认需要进行页面跳转了，那么可以通过读取HTTP头中的location属性来获取新的地址。</font></p>
<p><font size="4">状态码<br />
&nbsp;对应HttpServletResponse的常量<br />
&nbsp;详细描述<br />
&nbsp;<br />
301<br />
&nbsp;SC_MOVED_PERMANENTLY<br />
&nbsp;页面已经永久移到另外一个新地址<br />
&nbsp;<br />
302<br />
&nbsp;SC_MOVED_TEMPORARILY<br />
&nbsp;页面暂时移动到另外一个新的地址<br />
&nbsp;<br />
303<br />
&nbsp;SC_SEE_OTHER<br />
&nbsp;客户端请求的地址必须通过另外的URL来访问<br />
&nbsp;<br />
307<br />
&nbsp;SC_TEMPORARY_REDIRECT<br />
&nbsp;同SC_MOVED_TEMPORARILY<br />
&nbsp;</font></p>
<p><br />
<font size="4">下面的代码片段演示如何处理页面的重定向</font></p>
<p><font size="4">client.executeMethod(post);</font></p>
<p><font size="4">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println(post.getStatusLine().toString()); </font></p>
<p><font size="4">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; post.releaseConnection();</font></p>
<p><font size="4">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </font></p>
<p><font size="4">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //检查是否重定向</font></p>
<p><font size="4">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int statuscode = post.getStatusCode();</font></p>
<p><font size="4">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if ((statuscode == HttpStatus.SC_MOVED_TEMPORARILY) ||</font></p>
<p><font size="4">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (statuscode == HttpStatus.SC_MOVED_PERMANENTLY) ||</font></p>
<p><font size="4">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (statuscode == HttpStatus.SC_SEE_OTHER) ||</font></p>
<p><font size="4">(statuscode == HttpStatus.SC_TEMPORARY_REDIRECT)) {</font></p>
<p><font size="4">//读取新的URL地址</font></p>
<p><font size="4">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Header header = post.getResponseHeader("location");</font></p>
<p><font size="4">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (header != null) {</font></p>
<p><font size="4">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; String newuri = header.getValue();</font></p>
<p><font size="4">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if ((newuri == null) || (newuri.equals("")))</font></p>
<p><font size="4">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; newuri = "/"; </font></p>
<p><font size="4">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; GetMethod redirect = new GetMethod(newuri);</font></p>
<p><font size="4">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; client.executeMethod(redirect);</font></p>
<p><font size="4">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println("Redirect:"+ redirect.getStatusLine().toString()); </font></p>
<p><font size="4">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; redirect.releaseConnection();</font></p>
<p><font size="4">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } else </font></p>
<p><font size="4">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println("Invalid redirect");</font></p>
<p><font size="4">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</font></p>
<p><font size="4">我们可以自行编写两个JSP页面，其中一个页面用response.sendRedirect方法重定向到另外一个页面用来测试上面的例子。</font></p>
<p><font size="4">4． 模拟输入用户名和口令进行登录</font></p>
<p><font size="4">本小节应该说是HTTP客户端编程中最常碰见的问题，很多网站的内容都只是对注册用户可见的，这种情况下就必须要求使用正确的用户名和口令登录成功后，方可浏览到想要的页面。因为HTTP协议是无状态的，也就是连接的有效期只限于当前请求，请求内容结束后连接就关闭了。在这种情况下为了保存用户的登录信息必须使用到Cookie机制。以JSP/Servlet为例，当浏览器请求一个JSP或者是Servlet的页面时，应用服务器会返回一个参数，名为jsessionid（因不同应用服务器而异），值是一个较长的唯一字符串的Cookie，这个字符串值也就是当前访问该站点的会话标识。浏览器在每访问该站点的其他页面时候都要带上jsessionid这样的Cookie信息，应用服务器根据读取这个会话标识来获取对应的会话信息。</font></p>
<p><font size="4">对于需要用户登录的网站，一般在用户登录成功后会将用户资料保存在服务器的会话中，这样当访问到其他的页面时候，应用服务器根据浏览器送上的Cookie中读取当前请求对应的会话标识以获得对应的会话信息，然后就可以判断用户资料是否存在于会话信息中，如果存在则允许访问页面，否则跳转到登录页面中要求用户输入帐号和口令进行登录。这就是一般使用JSP开发网站在处理用户登录的比较通用的方法。</font></p>
<p><font size="4">这样一来，对于HTTP的客户端来讲，如果要访问一个受保护的页面时就必须模拟浏览器所做的工作，首先就是请求登录页面，然后读取Cookie值；再次请求登录页面并加入登录页所需的每个参数；最后就是请求最终所需的页面。当然在除第一次请求外其他的请求都需要附带上Cookie信息以便服务器能判断当前请求是否已经通过验证。说了这么多，可是如果你使用httpclient的话，你甚至连一行代码都无需增加，你只需要先传递登录信息执行登录过程，然后直接访问想要的页面，跟访问一个普通的页面没有任何区别，因为类HttpClient已经帮你做了所有该做的事情了，太棒了！下面的例子实现了这样一个访问的过程。</font></p>
<p><br />
<font size="4">/*</font></p>
<p><font size="4">&nbsp;* Created on 2003-12-7 by Liudong</font></p>
<p><font size="4">&nbsp;*/</font></p>
<p><font size="4">package http.demo;</font></p>
<p><font size="4">&nbsp;</font></p>
<p><font size="4">import org.apache.commons.httpclient.*;</font></p>
<p><font size="4">import org.apache.commons.httpclient.cookie.*;</font></p>
<p><font size="4">import org.apache.commons.httpclient.methods.*;</font></p>
<p><font size="4">&nbsp;</font></p>
<p><font size="4">/**</font></p>
<p><font size="4">&nbsp;* 用来演示登录表单的示例</font></p>
<p><font size="4">&nbsp;* @author Liudong</font></p>
<p><font size="4">&nbsp;*/</font></p>
<p><font size="4">public class FormLoginDemo {</font></p>
<p><font size="4">&nbsp;</font></p>
<p><font size="4">&nbsp;&nbsp;&nbsp; static final String LOGON_SITE = "localhost";</font></p>
<p><font size="4">&nbsp;&nbsp;&nbsp; static final int&nbsp;&nbsp;&nbsp; LOGON_PORT = 8080;</font></p>
<p><font size="4">&nbsp;&nbsp;&nbsp; </font></p>
<p><font size="4">&nbsp;&nbsp;&nbsp; public static void main(String[] args) throws Exception{</font></p>
<p><font size="4">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; HttpClient client = new HttpClient();</font></p>
<p><font size="4">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; client.getHostConfiguration().setHost(LOGON_SITE, LOGON_PORT);</font></p>
<p><font size="4">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </font></p>
<p><font size="4">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //模拟登录页面login.jsp-&gt;main.jsp</font></p>
<p><font size="4">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; PostMethod post = new PostMethod("/main.jsp");</font></p>
<p><font size="4">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; NameValuePair name = new NameValuePair("name", "ld");&nbsp;&nbsp;&nbsp;&nbsp; </font></p>
<p><font size="4">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; NameValuePair pass = new NameValuePair("password", "ld");&nbsp;&nbsp;&nbsp;&nbsp; </font></p>
<p><font size="4">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; post.setRequestBody(new NameValuePair[]{name,pass});</font></p>
<p><font size="4">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int status = client.executeMethod(post);</font></p>
<p><font size="4">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println(post.getResponseBodyAsString());</font></p>
<p><font size="4">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; post.releaseConnection();&nbsp; </font></p>
<p><font size="4">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </font></p>
<p><font size="4">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //查看cookie信息</font></p>
<p><font size="4">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; CookieSpec cookiespec = CookiePolicy.getDefaultSpec();</font></p>
<p><font size="4">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Cookie[] cookies = cookiespec.match(LOGON_SITE, LOGON_PORT, "/", false, client.getState().getCookies());</font></p>
<p><font size="4">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (cookies.length == 0) {</font></p>
<p><font size="4">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println("None");&nbsp;&nbsp;&nbsp; </font></p>
<p><font size="4">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } else {</font></p>
<p><font size="4">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for (int i = 0; i &lt; cookies.length; i++) {</font></p>
<p><font size="4">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println(cookies[i].toString());&nbsp;&nbsp;&nbsp; </font></p>
<p><font size="4">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</font></p>
<p><font size="4">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</font></p>
<p><font size="4">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //访问所需的页面main2.jsp</font></p>
<p><font size="4">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; GetMethod get = new GetMethod("/main2.jsp");</font></p>
<p><font size="4">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; client.executeMethod(get);</font></p>
<p><font size="4">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println(get.getResponseBodyAsString());</font></p>
<p><font size="4">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; get.releaseConnection();</font></p>
<p><font size="4">&nbsp;&nbsp;&nbsp; }</font></p>
<p><font size="4">}</font></p>
<p><font size="4">5． 提交XML格式参数</font></p>
<p><font size="4">提交XML格式的参数很简单，仅仅是一个提交时候的ContentType问题，下面的例子演示从文件文件中读取XML信息并提交给服务器的过程，该过程可以用来测试Web服务。</font></p>
<p><font size="4">import java.io.File;</font></p>
<p><font size="4">import java.io.FileInputStream;</font></p>
<p><font size="4">&nbsp;</font></p>
<p><font size="4">import org.apache.commons.httpclient.HttpClient;</font></p>
<p><font size="4">import org.apache.commons.httpclient.methods.EntityEnclosingMethod;</font></p>
<p><font size="4">import org.apache.commons.httpclient.methods.PostMethod;</font></p>
<p><font size="4">&nbsp;</font></p>
<p><font size="4">/**</font></p>
<p><font size="4">&nbsp;* 用来演示提交XML格式数据的例子</font></p>
<p><font size="4">&nbsp;*/</font></p>
<p><font size="4">public class PostXMLClient {</font></p>
<p><font size="4">&nbsp;</font></p>
<p><font size="4">&nbsp;&nbsp;&nbsp; public static void main(String[] args) throws Exception {</font></p>
<p><font size="4">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; File input = new File(&#8220;test.xml&#8221;);</font></p>
<p><font size="4">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; PostMethod post = new PostMethod(&#8220;http://localhost:8080/httpclient/xml.jsp&#8221;);</font></p>
<p><font size="4">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 设置请求的内容直接从文件中读取</font></p>
<p><font size="4">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; post.setRequestBody(new FileInputStream(input));</font></p>
<p><font size="4">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </font></p>
<p><font size="4">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (input.length() &lt; Integer.MAX_VALUE) </font></p>
<p><font size="4">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; post.setRequestContentLength(input.length());</font></p>
<p><font size="4">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; else&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; post.setRequestContentLength(EntityEnclosingMethod.CONTENT_LENGTH_CHUNKED);</font></p>
<p><font size="4">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </font></p>
<p><font size="4">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 指定请求内容的类型</font></p>
<p><font size="4">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; post.setRequestHeader("Content-type", "text/xml; charset=GBK");</font></p>
<p><font size="4">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </font></p>
<p><font size="4">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; HttpClient httpclient = new HttpClient(); </font></p>
<p><font size="4">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int result = httpclient.executeMethod(post); </font></p>
<p><font size="4">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println("Response status code: " + result);</font></p>
<p><font size="4">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println("Response body: ");</font></p>
<p><font size="4">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println(post.getResponseBodyAsString());</font></p>
<p><font size="4">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; post.releaseConnection();</font></p>
<p><font size="4">&nbsp;&nbsp;&nbsp; }</font></p>
<p><font size="4">}</font></p>
<p><font size="4">6． 通过HTTP上传文件</font></p>
<p><font size="4">httpclient使用了单独的一个HttpMethod子类来处理文件的上传，这个类就是MultipartPostMethod，该类已经封装了文件上传的细节，我们要做的仅仅是告诉它我们要上传文件的全路径即可，下面的代码片段演示如何使用这个类。</font></p>
<p><font size="4">MultipartPostMethod filePost = new MultipartPostMethod(targetURL);</font></p>
<p><font size="4">filePost.addParameter("fileName", targetFilePath);</font></p>
<p><font size="4">HttpClient client = new HttpClient();</font></p>
<p><font size="4">//由于要上传的文件可能比较大,因此在此设置最大的连接超时时间</font></p>
<p><font size="4">client.getHttpConnectionManager().getParams().setConnectionTimeout(5000);</font></p>
<p><font size="4">int status = client.executeMethod(filePost);</font></p>
<p><br />
<font size="4">上面代码中，targetFilePath即为要上传的文件所在的路径。</font></p>
<p><font size="4">7． 访问启用认证的页面</font></p>
<p><font size="4">我们经常会碰到这样的页面，当访问它的时候会弹出一个浏览器的对话框要求输入用户名和密码后方可，这种用户认证的方式不同于我们在前面介绍的基于表单的用户身份验证。这是HTTP的认证策略，httpclient支持三种认证方式包括：基本、摘要以及NTLM认证。其中基本认证最简单、通用但也最不安全；摘要认证是在HTTP 1.1中加入的认证方式，而NTLM则是微软公司定义的而不是通用的规范，最新版本的NTLM是比摘要认证还要安全的一种方式。</font></p>
<p><font size="4">下面例子是从httpclient的CVS服务器中下载的，它简单演示如何访问一个认证保护的页面：</font></p>
<p><br />
<font size="4">import org.apache.commons.httpclient.HttpClient;</font></p>
<p><font size="4">import org.apache.commons.httpclient.UsernamePasswordCredentials;</font></p>
<p><font size="4">import org.apache.commons.httpclient.methods.GetMethod;</font></p>
<p><font size="4">&nbsp;</font></p>
<p><font size="4">public class BasicAuthenticationExample {</font></p>
<p><font size="4">&nbsp;&nbsp;&nbsp; public BasicAuthenticationExample() {</font></p>
<p><font size="4">&nbsp;&nbsp;&nbsp; }</font></p>
<p><font size="4">&nbsp;&nbsp;&nbsp; public static void main(String[] args) throws Exception {</font></p>
<p><font size="4">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; HttpClient client = new HttpClient();</font></p>
<p><font size="4">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; client.getState().setCredentials(</font></p>
<p><font size="4">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "</font><a href="http://www.verisign.com/"><font size="4">www.verisign.com</font></a><font size="4">",</font></p>
<p><font size="4">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "realm",</font></p>
<p><font size="4">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; new UsernamePasswordCredentials("username", "password")</font></p>
<p><font size="4">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; );</font></p>
<p><font size="4">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; GetMethod get = new GetMethod("</font><a href="https://www.verisign.com/products/index.html"><font size="4">https://www.verisign.com/products/index.html</font></a><font size="4">");</font></p>
<p><font size="4">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; get.setDoAuthentication( true );</font></p>
<p><font size="4">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int status = client.executeMethod( get );</font></p>
<p><font size="4">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println(status+""+ get.getResponseBodyAsString());</font></p>
<p><font size="4">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; get.releaseConnection();</font></p>
<p><font size="4">&nbsp;&nbsp;&nbsp; }</font></p>
<p><font size="4">}</font></p>
<p><font size="4">8． 多线程模式下使用httpclient</font></p>
<p><font size="4">多线程同时访问httpclient，例如同时从一个站点上下载多个文件。对于同一个HttpConnection同一个时间只能有一个线程访问，为了保证多线程工作环境下不产生冲突，httpclient使用了一个多线程连接管理器的类：MultiThreadedHttpConnectionManager，要使用这个类很简单，只需要在构造HttpClient实例的时候传入即可，代码如下：</font></p>
<p><font size="4">MultiThreadedHttpConnectionManager connectionManager = </font></p>
<p><font size="4">&nbsp;&nbsp; new MultiThreadedHttpConnectionManager();</font></p>
<p><font size="4">HttpClient client = new HttpClient(connectionManager);</font></p>
<p><font size="4">以后尽管访问client实例即可。</font></p>
<p><font size="4">参考资料：</font></p>
<p><font size="4">httpclient首页：&nbsp;&nbsp;&nbsp; </font><a href="http://jakarta.apache.org/commons/httpclient/"><font size="4">http://jakarta.apache.org/commons/httpclient/</font></a><br />
<font size="4">关于NTLM是如何工作：&nbsp; </font><a href="http://davenport.sourceforge.net/ntlm.html"><font size="4">http://davenport.sourceforge.net/ntlm.html</font></a><br />
</p>
</font>
<img src ="http://www.blogjava.net/smildlzj/aggbug/161977.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/smildlzj/" target="_blank">smildlzj</a> 2007-11-20 23:52 <a href="http://www.blogjava.net/smildlzj/articles/161977.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>数据库对象的缓存策略</title><link>http://www.blogjava.net/smildlzj/articles/161464.html</link><dc:creator>smildlzj</dc:creator><author>smildlzj</author><pubDate>Sun, 18 Nov 2007 14:23:00 GMT</pubDate><guid>http://www.blogjava.net/smildlzj/articles/161464.html</guid><wfw:comment>http://www.blogjava.net/smildlzj/comments/161464.html</wfw:comment><comments>http://www.blogjava.net/smildlzj/articles/161464.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/smildlzj/comments/commentRss/161464.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/smildlzj/services/trackbacks/161464.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 前言本文探讨Jive(曾经开源的Java论坛)和Hibernate（Java开源持久层）的数据库对象的缓存策略，并阐述作者本人的Lightor（Java开源持久层）采用的数据库对象缓存策略。本文的探讨基于以前开源的Jive代码，Hibernate2.1.7源码，和作者本人的Lightor代码。本文用ID (Identifier的缩写)来代表数据记录的关键字。数据对象查询一般分为两种...&nbsp;&nbsp;<a href='http://www.blogjava.net/smildlzj/articles/161464.html'>阅读全文</a><img src ="http://www.blogjava.net/smildlzj/aggbug/161464.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/smildlzj/" target="_blank">smildlzj</a> 2007-11-18 22:23 <a href="http://www.blogjava.net/smildlzj/articles/161464.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>用Java向IPMSG发送消息</title><link>http://www.blogjava.net/smildlzj/articles/161008.html</link><dc:creator>smildlzj</dc:creator><author>smildlzj</author><pubDate>Fri, 16 Nov 2007 06:17:00 GMT</pubDate><guid>http://www.blogjava.net/smildlzj/articles/161008.html</guid><wfw:comment>http://www.blogjava.net/smildlzj/comments/161008.html</wfw:comment><comments>http://www.blogjava.net/smildlzj/articles/161008.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/smildlzj/comments/commentRss/161008.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/smildlzj/services/trackbacks/161008.html</trackback:ping><description><![CDATA[飞鸽传书（IP Messenger,简为IPMsg）是一个小巧方便的即时通信软件，它适合用于局域网内甚至广域网间进行实时通信和文档共享。特别是在局域网内传送文件/文件夹的速度非常快！<br />
<ul>
    <li>IPMsg 是一款局域网内即时通信软件, 基于 TCP/IP(UDP).
    <li>可运行于多种操作平台(Win/Mac/UNIX/Java), 并实现跨平台信息交流.
    <li>不需要服务器支持.
    <li>支持文件/文件夹的传送 (2.00版以上)
    <li>通讯数据采用 RSA/Blofish 加密 (2.00版以上)
    <li>十分小巧, 简单易用, 而且你可以完全免费使用它
    <li>目前已有的版本包括: Win32, Win16, MacOS, MacOSX, X11, GTK, GNOME,Java 等, 并且公开源代码。</li>
</ul>
<br />
本文演示了如何使用Java的net包，向IPMSG客户端发送消息。<br />
<br />
IPMSG Command 常量定义如下：<br />
<br />
<div style="border-right: rgb(204,204,204) 1px solid; padding-right: 5px; border-top: rgb(204,204,204) 1px solid; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left: rgb(204,204,204) 1px solid; width: 98%; padding-top: 4px; border-bottom: rgb(204,204,204) 1px solid; background-color: rgb(238,238,238)"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: rgb(0,128,128)">&nbsp;<font face="Courier New">1</font></span><font face="Courier New">&nbsp;<span style="color: rgb(0,128,0)">/*</span><span style="color: rgb(0,128,0)">==========&nbsp;Constant&nbsp;Value&nbsp;==========</span><span style="color: rgb(0,128,0)">*/</span><span style="color: rgb(0,0,0)"><br />
</span><span style="color: rgb(0,128,128)">&nbsp;2</span>&nbsp;<span style="color: rgb(0,0,255)">public</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">static</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">final</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">long</span><span style="color: rgb(0,0,0)">&nbsp;IPMSG_COMMASK&nbsp;</span><span style="color: rgb(0,0,0)">=</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,0)">0x000000ff</span><span style="color: rgb(0,0,0)">;<br />
</span><span style="color: rgb(0,128,128)">&nbsp;3</span>&nbsp;<span style="color: rgb(0,0,255)">public</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">static</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">final</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">long</span><span style="color: rgb(0,0,0)">&nbsp;IPMSG_OPTMASK&nbsp;</span><span style="color: rgb(0,0,0)">=</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,0)">0xffffff00</span><span style="color: rgb(0,0,0)">;<br />
</span><span style="color: rgb(0,128,128)">&nbsp;4</span>&nbsp;<span style="color: rgb(0,0,255)">public</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">static</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">final</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">long</span><span style="color: rgb(0,0,0)">&nbsp;IPMSG_NOOPERATION&nbsp;</span><span style="color: rgb(0,0,0)">=</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,0)">0x00000000</span><span style="color: rgb(0,0,0)">;<br />
</span><span style="color: rgb(0,128,128)">&nbsp;5</span>&nbsp;<span style="color: rgb(0,0,255)">public</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">static</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">final</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">long</span><span style="color: rgb(0,0,0)">&nbsp;IPMSG_BR_ENTRY&nbsp;</span><span style="color: rgb(0,0,0)">=</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,0)">0x00000001</span><span style="color: rgb(0,0,0)">;<br />
</span><span style="color: rgb(0,128,128)">&nbsp;6</span>&nbsp;<span style="color: rgb(0,0,255)">public</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">static</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">final</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">long</span><span style="color: rgb(0,0,0)">&nbsp;IPMSG_BR_EXIT&nbsp;</span><span style="color: rgb(0,0,0)">=</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,0)">0x00000002</span><span style="color: rgb(0,0,0)">;<br />
</span><span style="color: rgb(0,128,128)">&nbsp;7</span>&nbsp;<span style="color: rgb(0,0,255)">public</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">static</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">final</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">long</span><span style="color: rgb(0,0,0)">&nbsp;IPMSG_ANSENTRY&nbsp;</span><span style="color: rgb(0,0,0)">=</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,0)">0x00000003</span><span style="color: rgb(0,0,0)">;<br />
</span><span style="color: rgb(0,128,128)">&nbsp;8</span>&nbsp;<span style="color: rgb(0,0,255)">public</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">static</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">final</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">long</span><span style="color: rgb(0,0,0)">&nbsp;IPMSG_BR_ABSENCE&nbsp;</span><span style="color: rgb(0,0,0)">=</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,0)">0x00000004</span><span style="color: rgb(0,0,0)">;<br />
</span><span style="color: rgb(0,128,128)">&nbsp;9</span>&nbsp;<span style="color: rgb(0,0,0)"><br />
</span><span style="color: rgb(0,128,128)">10</span>&nbsp;<span style="color: rgb(0,0,0)">&nbsp;<br />
</span><span style="color: rgb(0,128,128)">11</span>&nbsp;<span style="color: rgb(0,0,0)"><br />
</span><span style="color: rgb(0,128,128)">12</span>&nbsp;<span style="color: rgb(0,0,255)">public</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">static</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">final</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">long</span><span style="color: rgb(0,0,0)">&nbsp;IPMSG_BR_ISGETLIST&nbsp;</span><span style="color: rgb(0,0,0)">=</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,0)">0x00000018</span><span style="color: rgb(0,0,0)">;<br />
</span><span style="color: rgb(0,128,128)">13</span>&nbsp;<span style="color: rgb(0,0,255)">public</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">static</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">final</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">long</span><span style="color: rgb(0,0,0)">&nbsp;IPMSG_OKGETLIST&nbsp;</span><span style="color: rgb(0,0,0)">=</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,0)">0x00000015</span><span style="color: rgb(0,0,0)">;<br />
</span><span style="color: rgb(0,128,128)">14</span>&nbsp;<span style="color: rgb(0,0,255)">public</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">static</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">final</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">long</span><span style="color: rgb(0,0,0)">&nbsp;IPMSG_GETLIST&nbsp;</span><span style="color: rgb(0,0,0)">=</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,0)">0x00000016</span><span style="color: rgb(0,0,0)">;<br />
</span><span style="color: rgb(0,128,128)">15</span>&nbsp;<span style="color: rgb(0,0,255)">public</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">static</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">final</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">long</span><span style="color: rgb(0,0,0)">&nbsp;IPMSG_ANSLIST&nbsp;</span><span style="color: rgb(0,0,0)">=</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,0)">0x00000017</span><span style="color: rgb(0,0,0)">;<br />
</span><span style="color: rgb(0,128,128)">16</span>&nbsp;<span style="color: rgb(0,0,0)"><br />
</span><span style="color: rgb(0,128,128)">17</span>&nbsp;<span style="color: rgb(0,0,255)">public</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">static</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">final</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">long</span><span style="color: rgb(0,0,0)">&nbsp;IPMSG_SENDMSG&nbsp;</span><span style="color: rgb(0,0,0)">=</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,0)">0x00000020</span><span style="color: rgb(0,0,0)">;<br />
</span><span style="color: rgb(0,128,128)">18</span>&nbsp;<span style="color: rgb(0,0,255)">public</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">static</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">final</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">long</span><span style="color: rgb(0,0,0)">&nbsp;IPMSG_RECVMSG&nbsp;</span><span style="color: rgb(0,0,0)">=</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,0)">0x00000021</span><span style="color: rgb(0,0,0)">;<br />
</span><span style="color: rgb(0,128,128)">19</span>&nbsp;<span style="color: rgb(0,0,0)"><br />
</span><span style="color: rgb(0,128,128)">20</span>&nbsp;<span style="color: rgb(0,0,255)">public</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">static</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">final</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">long</span><span style="color: rgb(0,0,0)">&nbsp;IPMSG_READMSG&nbsp;</span><span style="color: rgb(0,0,0)">=</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,0)">0x00000030</span><span style="color: rgb(0,0,0)">;<br />
</span><span style="color: rgb(0,128,128)">21</span>&nbsp;<span style="color: rgb(0,0,255)">public</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">static</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">final</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">long</span><span style="color: rgb(0,0,0)">&nbsp;IPMSG_DELMSG&nbsp;</span><span style="color: rgb(0,0,0)">=</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,0)">0x00000031</span><span style="color: rgb(0,0,0)">;<br />
</span><span style="color: rgb(0,128,128)">22</span>&nbsp;<span style="color: rgb(0,0,0)"><br />
</span><span style="color: rgb(0,128,128)">23</span>&nbsp;<span style="color: rgb(0,0,255)">public</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">static</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">final</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">long</span><span style="color: rgb(0,0,0)">&nbsp;IPMSG_GETINFO&nbsp;</span><span style="color: rgb(0,0,0)">=</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,0)">0x00000040</span><span style="color: rgb(0,0,0)">;<br />
</span><span style="color: rgb(0,128,128)">24</span>&nbsp;<span style="color: rgb(0,0,255)">public</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">static</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">final</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">long</span><span style="color: rgb(0,0,0)">&nbsp;IPMSG_SENDINFO&nbsp;</span><span style="color: rgb(0,0,0)">=</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,0)">0x00000041</span><span style="color: rgb(0,0,0)">;<br />
</span><span style="color: rgb(0,128,128)">25</span>&nbsp;<span style="color: rgb(0,0,0)"><br />
</span><span style="color: rgb(0,128,128)">26</span>&nbsp;<span style="color: rgb(0,128,0)">//</span><span style="color: rgb(0,128,0)">&nbsp;other&nbsp;opt</span><span style="color: rgb(0,128,0)"><br />
</span><span style="color: rgb(0,128,128)">27</span>&nbsp;<span style="color: rgb(0,0,255)">public</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">static</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">final</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">long</span><span style="color: rgb(0,0,0)">&nbsp;IPMSG_ABSENCEOPT&nbsp;</span><span style="color: rgb(0,0,0)">=</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,0)">0x00000100</span><span style="color: rgb(0,0,0)">;<br />
</span><span style="color: rgb(0,128,128)">28</span>&nbsp;<span style="color: rgb(0,0,255)">public</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">static</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">final</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">long</span><span style="color: rgb(0,0,0)">&nbsp;IPMSG_SERVEROPT&nbsp;</span><span style="color: rgb(0,0,0)">=</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,0)">0x00000200</span><span style="color: rgb(0,0,0)">;<br />
</span><span style="color: rgb(0,128,128)">29</span>&nbsp;<span style="color: rgb(0,0,255)">public</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">static</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">final</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">long</span><span style="color: rgb(0,0,0)">&nbsp;IPMSG_DIALUPOPT&nbsp;</span><span style="color: rgb(0,0,0)">=</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,0)">0x00010000</span><span style="color: rgb(0,0,0)">;<br />
</span><span style="color: rgb(0,128,128)">30</span>&nbsp;<span style="color: rgb(0,0,0)"><br />
</span><span style="color: rgb(0,128,128)">31</span>&nbsp;<span style="color: rgb(0,128,0)">//</span><span style="color: rgb(0,128,0)">&nbsp;send&nbsp;opt</span><span style="color: rgb(0,128,0)"><br />
</span><span style="color: rgb(0,128,128)">32</span>&nbsp;<span style="color: rgb(0,0,255)">public</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">static</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">final</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">long</span><span style="color: rgb(0,0,0)">&nbsp;IPMSG_SENDCHECKOPT&nbsp;</span><span style="color: rgb(0,0,0)">=</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,0)">0x00000100</span><span style="color: rgb(0,0,0)">;<br />
</span><span style="color: rgb(0,128,128)">33</span>&nbsp;<span style="color: rgb(0,0,255)">public</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">static</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">final</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">long</span><span style="color: rgb(0,0,0)">&nbsp;IPMSG_SECRETOPT&nbsp;</span><span style="color: rgb(0,0,0)">=</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,0)">0x00000200</span><span style="color: rgb(0,0,0)">;<br />
</span><span style="color: rgb(0,128,128)">34</span>&nbsp;<span style="color: rgb(0,0,255)">public</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">static</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">final</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">long</span><span style="color: rgb(0,0,0)">&nbsp;IPMSG_BROADCASTOPT&nbsp;</span><span style="color: rgb(0,0,0)">=</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,0)">0x00000400</span><span style="color: rgb(0,0,0)">;<br />
</span><span style="color: rgb(0,128,128)">35</span>&nbsp;<span style="color: rgb(0,0,255)">public</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">static</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">final</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">long</span><span style="color: rgb(0,0,0)">&nbsp;IPMSG_MULTICASTOPT&nbsp;</span><span style="color: rgb(0,0,0)">=</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,0)">0x00000800</span><span style="color: rgb(0,0,0)">;<br />
</span><span style="color: rgb(0,128,128)">36</span>&nbsp;<span style="color: rgb(0,0,255)">public</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">static</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">final</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">long</span><span style="color: rgb(0,0,0)">&nbsp;IPMSG_NOPOPUPOPT&nbsp;</span><span style="color: rgb(0,0,0)">=</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,0)">0x00001000</span><span style="color: rgb(0,0,0)">;<br />
</span><span style="color: rgb(0,128,128)">37</span>&nbsp;<span style="color: rgb(0,0,255)">public</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">static</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">final</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">long</span><span style="color: rgb(0,0,0)">&nbsp;IPMSG_AUTORETOPT&nbsp;</span><span style="color: rgb(0,0,0)">=</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,0)">0x00002000</span><span style="color: rgb(0,0,0)">;<br />
</span><span style="color: rgb(0,128,128)">38</span>&nbsp;<span style="color: rgb(0,0,255)">public</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">static</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">final</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">long</span><span style="color: rgb(0,0,0)">&nbsp;IPMSG_RETRYOPT&nbsp;</span><span style="color: rgb(0,0,0)">=</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,0)">0x00004000</span><span style="color: rgb(0,0,0)">;<br />
</span><span style="color: rgb(0,128,128)">39</span>&nbsp;<span style="color: rgb(0,0,255)">public</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">static</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">final</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">long</span><span style="color: rgb(0,0,0)">&nbsp;IPMSG_PASSWORDOPT&nbsp;</span><span style="color: rgb(0,0,0)">=</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,0)">0x00008000</span><span style="color: rgb(0,0,0)">;<br />
</span><span style="color: rgb(0,128,128)">40</span>&nbsp;<span style="color: rgb(0,0,255)">public</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">static</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">final</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">long</span><span style="color: rgb(0,0,0)">&nbsp;IPMSG_NOLOGOPT&nbsp;</span><span style="color: rgb(0,0,0)">=</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,0)">0x00020000</span><span style="color: rgb(0,0,0)">;<br />
</span><span style="color: rgb(0,128,128)">41</span>&nbsp;<span style="color: rgb(0,0,255)">public</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">static</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">final</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">long</span><span style="color: rgb(0,0,0)">&nbsp;IPMSG_NEWMUTIOPT&nbsp;</span><span style="color: rgb(0,0,0)">=</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,0)">0x00040000</span><span style="color: rgb(0,0,0)">;<br />
</span><span style="color: rgb(0,128,128)">42</span>&nbsp;<span style="color: rgb(0,0,0)"><br />
</span><span style="color: rgb(0,128,128)">43</span>&nbsp;<span style="color: rgb(0,0,255)">public</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">static</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">final</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">int</span><span style="color: rgb(0,0,0)">&nbsp;MAXBUF&nbsp;</span><span style="color: rgb(0,0,0)">=</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,0)">8192</span><span style="color: rgb(0,0,0)">;<br />
</span><span style="color: rgb(0,128,128)">44</span>&nbsp;<span style="color: rgb(0,128,0)">/*</span><span style="color: rgb(0,128,0)">==========&nbsp;end&nbsp;==========</span><span style="color: rgb(0,128,0)">*/</span></font></div>
<br />
IPMSG收发数据包的格式（一行）：<br />
<div style="border-right: rgb(204,204,204) 1px solid; padding-right: 5px; border-top: rgb(204,204,204) 1px solid; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left: rgb(204,204,204) 1px solid; width: 98%; padding-top: 4px; border-bottom: rgb(204,204,204) 1px solid; background-color: rgb(238,238,238)"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><font face="Courier New"><span style="color: rgb(0,128,128)">1</span>&nbsp;<span style="color: rgb(0,0,0)"><font color="#99cc00">version</font>(IPMSG版本):<font color="#99cc00">no</font>(消息编号，可以用系统时间):<font color="#99cc00">user</font>(发送消息的用户名):<font color="#99cc00">host</font>(发送消息的主机名):<font color="#99cc00">command</font>(上述&nbsp;Command&nbsp;常量，可以用&nbsp;|&nbsp;组合多个值):<font color="#99cc00">msg</font>(消息内容)</span></font></div>
<br />
示例(向IPMSG发送消息，需要先打开对方的IPMSG)：<br />
<div style="border-right: rgb(204,204,204) 1px solid; padding-right: 5px; border-top: rgb(204,204,204) 1px solid; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left: rgb(204,204,204) 1px solid; width: 98%; padding-top: 4px; border-bottom: rgb(204,204,204) 1px solid; background-color: rgb(238,238,238)"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: rgb(0,128,128)">&nbsp;<font face="Courier New">1</font></span><font face="Courier New">&nbsp;<span style="color: rgb(0,0,255)">import</span><span style="color: rgb(0,0,0)">&nbsp;java.io.IOException;<br />
</span><span style="color: rgb(0,128,128)">&nbsp;2</span>&nbsp;<span style="color: rgb(0,0,255)">import</span><span style="color: rgb(0,0,0)">&nbsp;java.net.DatagramPacket;<br />
</span><span style="color: rgb(0,128,128)">&nbsp;3</span>&nbsp;<span style="color: rgb(0,0,255)">import</span><span style="color: rgb(0,0,0)">&nbsp;java.net.DatagramSocket;<br />
</span><span style="color: rgb(0,128,128)">&nbsp;4</span>&nbsp;<span style="color: rgb(0,0,255)">import</span><span style="color: rgb(0,0,0)">&nbsp;java.net.InetAddress;<br />
</span><span style="color: rgb(0,128,128)">&nbsp;5</span>&nbsp;<span style="color: rgb(0,0,255)">import</span><span style="color: rgb(0,0,0)">&nbsp;java.net.SocketException;<br />
</span><span style="color: rgb(0,128,128)">&nbsp;6</span>&nbsp;<span style="color: rgb(0,0,255)">import</span><span style="color: rgb(0,0,0)">&nbsp;java.net.UnknownHostException;<br />
</span><span style="color: rgb(0,128,128)">&nbsp;7</span>&nbsp;<span style="color: rgb(0,0,255)">import</span><span style="color: rgb(0,0,0)">&nbsp;java.util.Date;<br />
</span><span style="color: rgb(0,128,128)">&nbsp;8</span>&nbsp;<span style="color: rgb(0,0,0)"><br />
</span><span style="color: rgb(0,128,128)">&nbsp;9</span>&nbsp;<span style="color: rgb(0,128,0)">/**</span><span style="color: rgb(0,128,0)"><br />
</span><span style="color: rgb(0,128,128)">10</span>&nbsp;<span style="color: rgb(0,128,0)">&nbsp;*&nbsp;</span><span style="color: rgb(128,128,128)">@author</span><span style="color: rgb(0,128,0)">&nbsp;乱&nbsp;7&nbsp;8&nbsp;糟&nbsp;</span><span style="color: rgb(0,128,0); text-decoration: underline">http://www.fadesky.com</span><span style="color: rgb(0,128,0)"><br />
</span><span style="color: rgb(0,128,128)">11</span>&nbsp;<span style="color: rgb(0,128,0)">&nbsp;</span><span style="color: rgb(0,128,0)">*/</span><span style="color: rgb(0,0,0)"><br />
</span><span style="color: rgb(0,128,128)">12</span>&nbsp;<span style="color: rgb(0,0,255)">public</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">class</span><span style="color: rgb(0,0,0)">&nbsp;TestIPMSG<br />
</span><span style="color: rgb(0,128,128)">13</span>&nbsp;<span style="color: rgb(0,0,0)">{<br />
</span><span style="color: rgb(0,128,128)">14</span>&nbsp;<span style="color: rgb(0,0,0)">&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">public</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">static</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">void</span><span style="color: rgb(0,0,0)">&nbsp;main(String[]&nbsp;args)<br />
</span><span style="color: rgb(0,128,128)">15</span>&nbsp;<span style="color: rgb(0,0,0)">&nbsp;&nbsp;{<br />
</span><span style="color: rgb(0,128,128)">16</span>&nbsp;<span style="color: rgb(0,0,0)">&nbsp;&nbsp;&nbsp;&nbsp;DatagramSocket&nbsp;socket;<br />
</span><span style="color: rgb(0,128,128)">17</span>&nbsp;<span style="color: rgb(0,0,0)">&nbsp;&nbsp;&nbsp;&nbsp;InetAddress&nbsp;address;<br />
</span><span style="color: rgb(0,128,128)">18</span>&nbsp;<span style="color: rgb(0,0,0)"><br />
</span><span style="color: rgb(0,128,128)">19</span>&nbsp;<span style="color: rgb(0,0,0)">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">long</span><span style="color: rgb(0,0,0)">&nbsp;IPMSG_SENDMSG&nbsp;</span><span style="color: rgb(0,0,0)">=</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,0)">0x00000020</span><span style="color: rgb(0,0,0)">;<br />
</span><span style="color: rgb(0,128,128)">20</span>&nbsp;<span style="color: rgb(0,0,0)"><br />
</span><span style="color: rgb(0,128,128)">21</span>&nbsp;<span style="color: rgb(0,0,0)">&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;SENDER&nbsp;</span><span style="color: rgb(0,0,0)">=</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,0)">"</span><span style="color: rgb(0,0,0)">乱&nbsp;7&nbsp;8&nbsp;糟</span><span style="color: rgb(0,0,0)">"</span><span style="color: rgb(0,0,0)">;<br />
</span><span style="color: rgb(0,128,128)">22</span>&nbsp;<span style="color: rgb(0,0,0)">&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;HOST&nbsp;</span><span style="color: rgb(0,0,0)">=</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,0)">"</span><span style="color: rgb(0,0,0)">Localhost</span><span style="color: rgb(0,0,0)">"</span><span style="color: rgb(0,0,0)">;<br />
</span><span style="color: rgb(0,128,128)">23</span>&nbsp;<span style="color: rgb(0,0,0)">&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;MSG_CONTENT&nbsp;</span><span style="color: rgb(0,0,0)">=</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,0)">"</span><span style="color: rgb(0,0,0)">Hello&nbsp;World!</span><span style="color: rgb(0,0,0)">"</span><span style="color: rgb(0,0,0)">;<br />
</span><span style="color: rgb(0,128,128)">24</span>&nbsp;<span style="color: rgb(0,0,0)"><br />
</span><span style="color: rgb(0,128,128)">25</span>&nbsp;<span style="color: rgb(0,0,0)">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">try</span><span style="color: rgb(0,0,0)"><br />
</span><span style="color: rgb(0,128,128)">26</span>&nbsp;<span style="color: rgb(0,0,0)">&nbsp;&nbsp;&nbsp;&nbsp;{<br />
</span><span style="color: rgb(0,128,128)">27</span>&nbsp;<span style="color: rgb(0,0,0)">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;socket&nbsp;</span><span style="color: rgb(0,0,0)">=</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">new</span><span style="color: rgb(0,0,0)">&nbsp;DatagramSocket();<br />
</span><span style="color: rgb(0,128,128)">28</span>&nbsp;<span style="color: rgb(0,0,0)">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;address&nbsp;</span><span style="color: rgb(0,0,0)">=</span><span style="color: rgb(0,0,0)">&nbsp;InetAddress.getByName(</span><span style="color: rgb(0,0,0)">"</span><span style="color: rgb(0,0,0)">192.168.1.20</span><span style="color: rgb(0,0,0)">"</span><span style="color: rgb(0,0,0)">);</span><span style="color: rgb(0,128,0)">//</span><span style="color: rgb(0,128,0)"> 发送给消息的地址</span><span style="color: rgb(0,128,0)"><br />
</span><span style="color: rgb(0,128,128)">29</span>&nbsp;<span style="color: rgb(0,0,0)"><br />
</span><span style="color: rgb(0,128,128)">30</span>&nbsp;<span style="color: rgb(0,0,0)">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,128,0)">/**</span><span style="color: rgb(0,128,0)"><br />
</span><span style="color: rgb(0,128,128)">31</span>&nbsp;<span style="color: rgb(0,128,0)">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;IPMSG收发数据包的格式（一行）：<br />
</span><span style="color: rgb(0,128,128)">32</span>&nbsp;<span style="color: rgb(0,128,0)">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;<br />
</span><span style="color: rgb(0,128,128)">33</span>&nbsp;<span style="color: rgb(0,128,0)">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;version(IPMSG版本):no(消息编号，可以用系统时间):user(发送消息的用户名):<br />
</span><span style="color: rgb(0,128,128)">34</span>&nbsp;<span style="color: rgb(0,128,0)">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;host(发送消息的主机名):command(上述&nbsp;Command&nbsp;常量，可以用&nbsp;|&nbsp;组合多个值):<br />
</span><span style="color: rgb(0,128,128)">35</span>&nbsp;<span style="color: rgb(0,128,0)">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;msg(消息内容)<br />
</span><span style="color: rgb(0,128,128)">36</span>&nbsp;<span style="color: rgb(0,128,0)">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;<br />
</span><span style="color: rgb(0,128,128)">37</span>&nbsp;<span style="color: rgb(0,128,0)">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,128,0)">*/</span><span style="color: rgb(0,0,0)"><br />
</span><span style="color: rgb(0,128,128)">38</span>&nbsp;<span style="color: rgb(0,0,0)">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">byte</span><span style="color: rgb(0,0,0)">[]&nbsp;buffer&nbsp;</span><span style="color: rgb(0,0,0)">=</span><span style="color: rgb(0,0,0)">&nbsp;(</span><span style="color: rgb(0,0,0)">"</span><span style="color: rgb(0,0,0)">1:</span><span style="color: rgb(0,0,0)">"</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,0)">+</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">new</span><span style="color: rgb(0,0,0)">&nbsp;Date().getTime()&nbsp;</span><span style="color: rgb(0,0,0)">+</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,0)">"</span><span style="color: rgb(0,0,0)">:</span><span style="color: rgb(0,0,0)">"</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,0)">+</span><span style="color: rgb(0,0,0)">&nbsp;SENDER&nbsp;</span><span style="color: rgb(0,0,0)">+</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,0)">"</span><span style="color: rgb(0,0,0)">:</span><span style="color: rgb(0,0,0)">"</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,0)">+</span><span style="color: rgb(0,0,0)">&nbsp;HOST<br />
</span><span style="color: rgb(0,128,128)">39</span>&nbsp;<span style="color: rgb(0,0,0)">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,0)">+</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,0)">"</span><span style="color: rgb(0,0,0)">:</span><span style="color: rgb(0,0,0)">"</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,0)">+</span><span style="color: rgb(0,0,0)">&nbsp;IPMSG_SENDMSG&nbsp;</span><span style="color: rgb(0,0,0)">+</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,0)">"</span><span style="color: rgb(0,0,0)">:</span><span style="color: rgb(0,0,0)">"</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,0)">+</span><span style="color: rgb(0,0,0)">&nbsp;MSG_CONTENT).getBytes();<br />
</span><span style="color: rgb(0,128,128)">40</span>&nbsp;<span style="color: rgb(0,0,0)"><br />
</span><span style="color: rgb(0,128,128)">41</span>&nbsp;<span style="color: rgb(0,0,0)">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DatagramPacket&nbsp;packet&nbsp;</span><span style="color: rgb(0,0,0)">=</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">new</span><span style="color: rgb(0,0,0)">&nbsp;DatagramPacket(buffer,&nbsp;buffer.length,<br />
</span><span style="color: rgb(0,128,128)">42</span>&nbsp;<span style="color: rgb(0,0,0)">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;address,&nbsp;</span><span style="color: rgb(0,0,0)">2425</span><span style="color: rgb(0,0,0)">);<br />
</span><span style="color: rgb(0,128,128)">43</span>&nbsp;<span style="color: rgb(0,0,0)">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;socket.send(packet);&nbsp;</span><span style="color: rgb(0,128,0)">//</span><span style="color: rgb(0,128,0)">&nbsp;发送报文</span><span style="color: rgb(0,128,0)"><br />
</span><span style="color: rgb(0,128,128)">44</span>&nbsp;<span style="color: rgb(0,0,0)"><br />
</span><span style="color: rgb(0,128,128)">45</span>&nbsp;<span style="color: rgb(0,0,0)">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;packet&nbsp;</span><span style="color: rgb(0,0,0)">=</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">new</span><span style="color: rgb(0,0,0)">&nbsp;DatagramPacket(buffer,&nbsp;buffer.length);<br />
</span><span style="color: rgb(0,128,128)">46</span>&nbsp;<span style="color: rgb(0,0,0)">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;socket.receive(packet);</span><span style="color: rgb(0,128,0)">//</span><span style="color: rgb(0,128,0)">&nbsp;接收回应</span><span style="color: rgb(0,128,0)"><br />
</span><span style="color: rgb(0,128,128)">47</span>&nbsp;<span style="color: rgb(0,0,0)"><br />
</span><span style="color: rgb(0,128,128)">48</span>&nbsp;<span style="color: rgb(0,0,0)">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;message&nbsp;</span><span style="color: rgb(0,0,0)">=</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">new</span><span style="color: rgb(0,0,0)">&nbsp;String(packet.getData());&nbsp;</span><span style="color: rgb(0,128,0)">//</span><span style="color: rgb(0,128,0)">&nbsp;得到报文信息</span><span style="color: rgb(0,128,0)"><br />
</span><span style="color: rgb(0,128,128)">49</span>&nbsp;<span style="color: rgb(0,0,0)"><br />
</span><span style="color: rgb(0,128,128)">50</span>&nbsp;<span style="color: rgb(0,0,0)">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(message);&nbsp;</span><span style="color: rgb(0,128,0)">//</span><span style="color: rgb(0,128,0)">&nbsp;显示对方返回的信息</span><span style="color: rgb(0,128,0)"><br />
</span><span style="color: rgb(0,128,128)">51</span>&nbsp;<span style="color: rgb(0,0,0)">&nbsp;&nbsp;&nbsp;&nbsp;}<br />
</span><span style="color: rgb(0,128,128)">52</span>&nbsp;<span style="color: rgb(0,0,0)">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">catch</span><span style="color: rgb(0,0,0)">&nbsp;(UnknownHostException&nbsp;e)<br />
</span><span style="color: rgb(0,128,128)">53</span>&nbsp;<span style="color: rgb(0,0,0)">&nbsp;&nbsp;&nbsp;&nbsp;{<br />
</span><span style="color: rgb(0,128,128)">54</span>&nbsp;<span style="color: rgb(0,0,0)">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;e.printStackTrace();<br />
</span><span style="color: rgb(0,128,128)">55</span>&nbsp;<span style="color: rgb(0,0,0)">&nbsp;&nbsp;&nbsp;&nbsp;}<br />
</span><span style="color: rgb(0,128,128)">56</span>&nbsp;<span style="color: rgb(0,0,0)">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">catch</span><span style="color: rgb(0,0,0)">&nbsp;(SocketException&nbsp;e)<br />
</span><span style="color: rgb(0,128,128)">57</span>&nbsp;<span style="color: rgb(0,0,0)">&nbsp;&nbsp;&nbsp;&nbsp;{<br />
</span><span style="color: rgb(0,128,128)">58</span>&nbsp;<span style="color: rgb(0,0,0)">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;e.printStackTrace();<br />
</span><span style="color: rgb(0,128,128)">59</span>&nbsp;<span style="color: rgb(0,0,0)">&nbsp;&nbsp;&nbsp;&nbsp;}<br />
</span><span style="color: rgb(0,128,128)">60</span>&nbsp;<span style="color: rgb(0,0,0)"><br />
</span><span style="color: rgb(0,128,128)">61</span>&nbsp;<span style="color: rgb(0,0,0)">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">catch</span><span style="color: rgb(0,0,0)">&nbsp;(IOException&nbsp;e)<br />
</span><span style="color: rgb(0,128,128)">62</span>&nbsp;<span style="color: rgb(0,0,0)">&nbsp;&nbsp;&nbsp;&nbsp;{<br />
</span><span style="color: rgb(0,128,128)">63</span>&nbsp;<span style="color: rgb(0,0,0)">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;e.printStackTrace();<br />
</span><span style="color: rgb(0,128,128)">64</span>&nbsp;<span style="color: rgb(0,0,0)">&nbsp;&nbsp;&nbsp;&nbsp;}<br />
</span><span style="color: rgb(0,128,128)">65</span>&nbsp;<span style="color: rgb(0,0,0)"><br />
</span><span style="color: rgb(0,128,128)">66</span>&nbsp;<span style="color: rgb(0,0,0)">&nbsp;&nbsp;}<br />
</span><span style="color: rgb(0,128,128)">67</span>&nbsp;<span style="color: rgb(0,0,0)"><br />
</span><span style="color: rgb(0,128,128)">68</span>&nbsp;<span style="color: rgb(0,0,0)">}<br />
</span><span style="color: rgb(0,128,128)">69</span>&nbsp;</font></div>
<br />
你可以在 SourceForge 找到开源的 <a title="IP MSG for Java" href="http://sourceforge.net/projects/ipmsg/" target="_blank">IP MSG for Java</a><br />
<br />
从本Blog <a title="IPMSG for Java" href="http://www.blogjava.net/Files/tripper/ipmsg.zip" target="_blank">下载</a><br />
<br />
<a title="http://www.blogjava.net/tripper" href="http://www.blogjava.net/tripper">http://www.blogjava.net/tripper</a><br />
<br />
 <img src ="http://www.blogjava.net/smildlzj/aggbug/161008.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/smildlzj/" target="_blank">smildlzj</a> 2007-11-16 14:17 <a href="http://www.blogjava.net/smildlzj/articles/161008.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>