<?xml version="1.0" encoding="UTF-8" ?>















<rss version="2.0" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">

<channel>
<title><![CDATA[网络安全]]> </title>
<description>
<![CDATA[/]]>
</description>
<link>http://amxiaomao.blog.bokee.net/</link>
<language>zh-cn</language>
<creator>amxiaomao</creator>
<pubDate>Sun, 09 Apr 2006 13:35:35 CST </pubDate>
<generatorAgent rdf:resource="http://www.bokee.net"/>
<ttl>5</ttl>

<item>
<title>fork ???</title>
<link>http://www.bokee.net/blogmodule/weblogcomment_viewEntry/2048520.html</link>
<description>
<![CDATA[<p>&nbsp;&nbsp;&nbsp;&nbsp; 终于,有时间.学习LINUX编程了.!!!</p>
<p>&nbsp;&nbsp; 当新建一个进程时,打印进程ID,为什么会打印2个ID, (一个ID=0,一个ID=真实ID);</p>
<p>#include &lt;stdio.h&gt;</p>
<p>#include &lt;unistd.h&gt;</p>
<p>main()</p>
<p>{ int pid ;</p>
<p>&nbsp; pid=fork;</p>
<p>printf(&quot;ID=%d&quot;,pid);</p>
<p><strong>.</strong></p>
<p><strong>.</strong></p>
<p><strong>.</strong></p>
<p>&nbsp;</p>
<p>}</p>
<p>ID=0</p>
<p>ID=某一个ID</p>
<p>man fork</p>
<p>看不懂!</p>
<p>明天,买个字典去!</p>]]>
</description>
<guid isPermaLink="false">http://www.bokee.net/blogmodule/weblogcomment_viewEntry/2048520.html</guid>
<subject>????</subject>
<author>amxiaomao</author>
<category>????</category>
<pubDate>Sun, 10 Aug 2008 08:05:55 CST </pubDate>
</item>

<item>
<title>用C语言实现Ping程序功能 </title>
<link>http://www.bokee.net/blogmodule/weblogcomment_viewEntry/1987586.html</link>
<description>
<![CDATA[<table cellspacing="0" cellpadding="0" width="100%" border="0">
    <tbody>
        <tr valign="top">
            <td width="100%">
            <h1>&nbsp;</h1>
            <img class="display-img" height="6" alt="" src="http://www.ibm.com/i/c.gif" width="1" /></td>
            <td class="no-print" width="192">&nbsp;</td>
        </tr>
    </tbody>
</table>
<table cellspacing="0" cellpadding="0" width="100%" border="0">
    <tbody>
        <tr valign="top">
            <td width="10"><img height="1" alt="" src="http://www.ibm.com/i/c.gif" width="10" /></td>
            <td width="100%">
            <table cellspacing="0" cellpadding="0" width="160" align="right" border="0" class="no-print">
                <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="0" width="150" border="0">
                            <tbody>
                                <tr>
                                    <td class="v14-header-1-small">文档选项</td>
                                </tr>
                            </tbody>
                        </table>
                        <table cellspacing="0" cellpadding="0" border="0" class="v14-gray-table-border">
                            <tbody>
                                <tr>
                                    <td class="no-padding" width="150">
                                    <table cellspacing="0" cellpadding="0" width="143" border="0">
                                         language="JavaScript" type="text/javascript">
<!--
document.write('<tr valign="top"><td width="8"><img src="//www.ibm.com/i/c.gif" width="8" height="1" alt=""/></td><td width="16"><img alt="将打印机的版面设置成横向打印模式" height="16" src="//www.ibm.com/i/v14/icons/printer.gif" width="16" vspace="3" /></td><td width="122"><p><b><a class="smallplainlink" href="javascript:print()">打印本页</a></b></p></td></tr>');
//-->
</script>
                                        <tbody>
                                            <tr valign="top">
                                                <td width="8"><img height="1" alt="" src="http://www.ibm.com/i/c.gif" width="8" /></td>
                                                <td width="16"><img height="16" alt="将打印机的版面设置成横向打印模式" src="http://www.ibm.com/i/v14/icons/printer.gif" width="16" vspace="3" /></td>
                                                <td width="122">
                                                <p><strong><a class="smallplainlink" href="javascript:print()" cmimpressionsent="1">打印本页</a></strong></p>
                                                </td>
                                            </tr>
                                            <noscript></noscript>
                                            <form action="https://www.ibm.com/developerworks/secure/email-it.jsp" cm1="1" name="email">
                                                <tr valign="top">
                                                    <td width="8"><img height="1" alt="" src="http://www.ibm.com/i/c.gif" width="8" /></td>
                                                    <td width="16"><img height="16" alt="将此页作为电子邮件发送" src="http://www.ibm.com/i/v14/icons/em.gif" width="16" vspace="3" /></td>
                                                    <td width="122">
                                                    <p><a class="smallplainlink" href="javascript:document.email.submit();" cmimpressionsent="1"><strong><font color="#5c81a7" size="2">将此页作为电子邮件发送</font></strong></a></p>
                                                    </td>
                                                </tr>
                                                <noscript></noscript>
                                            </form>
                                        </tbody>
                                    </table>
                                    </td>
                                </tr>
                            </tbody>
                        </table>
                        <!--START RESERVED FOR FUTURE USE INCLUDE FILES--><!-- this content will be automatically generated across all content areas --><!--END RESERVED FOR FUTURE USE INCLUDE FILES--><br /></td>
                    </tr>
                </tbody>
            </table>
            <p>级别： 初级</p>
            <p><a href="http://www.ibm.com/developerworks/cn/linux/network/ping/index.html#author" cmimpressionsent="1"><font color="#996699">梁俊辉</font></a> (<a href="mailto:zeusliang@21cn.com?subject=用C语言实现Ping程序功能&amp;cc=zeusliang@21cn.com" cmimpressionsent="1"><font color="#5c81a7">zeusliang@21cn.com</font></a>)<br /><br />
            <table border="1">
                <tbody>
                    <tr>
                        <td style="COLOR: #ff0000">XML error: Please enter a value for the author element's jobtitle attribute, or the company-name element, or both.</td>
                    </tr>
                </tbody>
            </table>
            <br /><br /><br /></p>
            <p>2001 年 10 月 01 日</p>
            <blockquote>大部分人用ping命令只是作为查看另一个系统的网络连接是否正常的一种简单方法。在这篇文章中，作者将介绍如何用C语言编写一个模拟ping命令功能的程序。</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>ping命令是用来查看网络上另一个主机系统的网络连接是否正常的一个工具。ping命令的工作原理是：向网络上的另一个主机系统发送ICMP报文，如果指定系统得到了报文，它将把报文一模一样地传回给发送者，这有点象潜水艇声纳系统中使用的发声装置。</p>
            <p>例如，在Linux终端上执行ping　localhost命令将会看到以下结果:
            <table cellspacing="0" cellpadding="0" width="550" border="0">
                <tbody>
                    <tr>
                        <td class="code-outline">
                        <pre class="displaycode">PING localhost.localdomain (127.0.0.1) from 127.0.0.1 : 56(84) bytes of data.
64 bytes from localhost.localdomain (127.0.0.1): icmp_seq=0 ttl=255 time=112 usec
64 bytes from localhost.localdomain (127.0.0.1): icmp_seq=1 ttl=255 time=79 usec
64 bytes from localhost.localdomain (127.0.0.1): icmp_seq=2 ttl=255 time=78 usec
64 bytes from localhost.localdomain (127.0.0.1): icmp_seq=3 ttl=255 time=82 usec
--- localhost.localdomain ping statistics ---
4 packets transmitted, 4 packets received, 0% packet loss
round-trip min/avg/max/mdev = 0.078/0.087/0.112/0.018 ms
</pre>
                        </td>
                    </tr>
                </tbody>
            </table>
            <br /></p>
            <p>由上面的执行结果可以看到，ping命令执行后显示出被测试系统主机名和相应IP地址、返回给当前主机的ICMP报文顺序号、ttl生存时间和往返时间rtt（单位是毫秒，即千分之一秒）。要写一个模拟ping命令，这些信息有启示作用。</p>
            <p>要真正了解ping命令实现原理，就要了解ping命令所使用到的TCP/IP协议。</p>
            <p>ICMP(Internet Control Message,网际控制报文协议)是为网关和目标主机而提供的一种差错控制机制，使它们在遇到差错时能把错误报告给报文源发方。ICMP协议是IP层的一个协议，但是由于差错报告在发送给报文源发方时可能也要经过若干子网，因此牵涉到路由选择等问题，所以ICMP报文需通过IP协议来发送。ICMP数据报的数据发送前需要两级封装：首先添加ICMP报头形成ICMP报文，再添加IP报头形成IP数据报。如下图所示</p>
            <table cellspacing="0" cellpadding="5" width="100%" border="1">
                <tbody>
                    <tr>
                        <td align="center">IP报头</td>
                    </tr>
                    <tr>
                        <td align="center">ICMP报头</td>
                    </tr>
                    <tr>
                        <td align="center">ICMP数据报</td>
                    </tr>
                </tbody>
            </table>
            <p><a name="1"><span class="atitle">IP报头格式</span></a></p>
            <p>由于IP层协议是一种点对点的协议，而非端对端的协议，它提供无连接的数据报服务，没有端口的概念，因此很少使用bind()和connect()函数，若有使用也只是用于设置IP地址。发送数据使用sendto()函数，接收数据使用recvfrom()函数。IP报头格式如下图： </p>
            <br /><img height="140" alt="" src="http://www.ibm.com/developerworks/cn/linux/network/ping/fig1.gif" width="542" /> <br />
            <p>在Linux中，IP报头格式数据结构(&lt;netinet/ip.h&gt;)定义如下：
            <table cellspacing="0" cellpadding="0" width="100%" border="0">
                <tbody>
                    <tr>
                        <td class="code-outline">
                        <pre class="displaycode">struct ip
  {
#if __BYTE_ORDER == __LITTLE_ENDIAN
    unsigned int ip_hl:4;       /* header length */
    unsigned int ip_v:4;        /* version */
#endif
#if __BYTE_ORDER == __BIG_ENDIAN
    unsigned int ip_v:4;        /* version */
    unsigned int ip_hl:4;       /* header length */
#endif
    u_int8_t ip_tos;            /* type of service */
    u_short ip_len;         /* total length */
    u_short ip_id;          /* identification */
    u_short ip_off;         /* fragment offset field */
#define IP_RF 0x8000            /* reserved fragment flag */
#define IP_DF 0x4000            /* dont fragment flag */
#define IP_MF 0x2000            /* more fragments flag */
#define IP_OFFMASK 0x1fff       /* mask for fragmenting bits */
    u_int8_t ip_ttl;            /* time to live */
    u_int8_t ip_p;          /* protocol */
    u_short ip_sum;         /* checksum */
    struct in_addr ip_src, ip_dst;  /* source and dest address */
  };</pre>
                        </td>
                    </tr>
                </tbody>
            </table>
            <br /></p>
            <p>其中ping程序只使用以下数据： </p>
            <ul>
                <li>IP报头长度IHL（Internet Header Length）�D�D以４字节为一个单位来记录IP报头的长度，是上述IP数据结构的ip_hl变量。 </li>
                <li>生存时间TTL（Time To Live）�D�D以秒为单位，指出IP数据报能在网络上停留的最长时间，其值由发送方设定，并在经过路由的每一个节点时减一，当该值为０时，数据报将被丢弃，是上述IP数据结构的ip_ttl变量。 </li>
            </ul>
            <p>&nbsp;</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 cellspacing="0" cellpadding="0" align="right" class="no-print">
                <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/linux/network/ping/index.html#main" cmimpressionsent="1"><strong><font color="#996699">回页首</font></strong></a></td>
                                </tr>
                            </tbody>
                        </table>
                        </td>
                    </tr>
                </tbody>
            </table>
            <br /><br />
            <p><a name="2"><span class="atitle">ICMP报头格式</span></a></p>
            <p>ICMP报文分为两种，一是错误报告报文，二是查询报文。每个ICMP报头均包含类型、编码和校验和这三项内容，长度为８位，８位和１６位，其余选项则随ICMP的功能不同而不同。</p>
            <p>Ping命令只使用众多ICMP报文中的两种：&quot;请求回送'(ICMP_ECHO)和&quot;请求回应'(ICMP_ECHOREPLY)。在Linux中定义如下：
            <table cellspacing="0" cellpadding="0" width="100%" border="0">
                <tbody>
                    <tr>
                        <td class="code-outline">
                        <pre class="displaycode">#define ICMP_ECHO   0
#define ICMP_ECHOREPLY  8</pre>
                        </td>
                    </tr>
                </tbody>
            </table>
            <br /></p>
            <p>这两种ICMP类型报头格式如下：</p>
            <br /><img height="50" alt="" src="http://www.ibm.com/developerworks/cn/linux/network/ping/fig2.gif" width="503" /> <br />
            <p>在Linux中ICMP数据结构(&lt;netinet/ip_icmp.h&gt;)定义如下：
            <table cellspacing="0" cellpadding="0" width="100%" border="0">
                <tbody>
                    <tr>
                        <td class="code-outline">
                        <pre class="displaycode">struct icmp
{
  u_int8_t  icmp_type;  /* type of message, see below */
  u_int8_t  icmp_code;  /* type sub code */
  u_int16_t icmp_cksum; /* ones complement checksum of struct */
  union
  {
    u_char ih_pptr;     /* ICMP_PARAMPROB */
    struct in_addr ih_gwaddr;   /* gateway address */
    struct ih_idseq     /* echo datagram */
    {
      u_int16_t icd_id;
      u_int16_t icd_seq;
    } ih_idseq;
    u_int32_t ih_void;
    /* ICMP_UNREACH_NEEDFRAG -- Path MTU Discovery (RFC1191) */
    struct ih_pmtu
    {
      u_int16_t ipm_void;
      u_int16_t ipm_nextmtu;
    } ih_pmtu;
    struct ih_rtradv
    {
      u_int8_t irt_num_addrs;
      u_int8_t irt_wpa;
      u_int16_t irt_lifetime;
    } ih_rtradv;
  } icmp_hun;
#define icmp_pptr   icmp_hun.ih_pptr
#define icmp_gwaddr icmp_hun.ih_gwaddr
#define icmp_id     icmp_hun.ih_idseq.icd_id
#define icmp_seq        icmp_hun.ih_idseq.icd_seq
#define icmp_void   icmp_hun.ih_void
#define icmp_pmvoid icmp_hun.ih_pmtu.ipm_void
#define icmp_nextmtu    icmp_hun.ih_pmtu.ipm_nextmtu
#define icmp_num_addrs  icmp_hun.ih_rtradv.irt_num_addrs
#define icmp_wpa    icmp_hun.ih_rtradv.irt_wpa
#define icmp_lifetime   icmp_hun.ih_rtradv.irt_lifetime
  union
  {
    struct
    {
      u_int32_t its_otime;
      u_int32_t its_rtime;
      u_int32_t its_ttime;
    } id_ts;
    struct
    {
      struct ip idi_ip;
      /* options and then 64 bits of data */
    } id_ip;
    struct icmp_ra_addr id_radv;
    u_int32_t   id_mask;
    u_int8_t    id_data[1];
  } icmp_dun;
#define icmp_otime  icmp_dun.id_ts.its_otime
#define icmp_rtime  icmp_dun.id_ts.its_rtime
#define icmp_ttime  icmp_dun.id_ts.its_ttime
#define icmp_ip     icmp_dun.id_ip.idi_ip
#define icmp_radv   icmp_dun.id_radv
#define icmp_mask   icmp_dun.id_mask
#define icmp_data   icmp_dun.id_data
};
</pre>
                        </td>
                    </tr>
                </tbody>
            </table>
            <br /></p>
            <p>使用宏定义令表达更简洁,其中ICMP报头为８字节,数据报长度最大为64K字节。 </p>
            <ol>
                <li>校验和算法�D�D这一算法称为网际校验和算法，把被校验的数据１６位进行累加，然后取反码，若数据字节长度为奇数，则数据尾部补一个字节的０以凑成偶数。此算法适用于IPv4、ICMPv4、IGMPV4、ICMPv6、UDP和TCP校验和，更详细的信息请参考RFC1071，校验和字段为上述ICMP数据结构的icmp_cksum变量。 </li>
                <li>标识符�D�D用于唯一标识ICMP报文, 为上述ICMP数据结构的icmp_id宏所指的变量。 </li>
                <li>顺序号�D�Dping命令的icmp_seq便由这里读出，代表ICMP报文的发送顺序，为上述ICMP数据结构的icmp_seq宏所指的变量。 </li>
            </ol>
            <p>&nbsp;</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 cellspacing="0" cellpadding="0" align="right" class="no-print">
                <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/linux/network/ping/index.html#main" cmimpressionsent="1"><strong><font color="#996699">回页首</font></strong></a></td>
                                </tr>
                            </tbody>
                        </table>
                        </td>
                    </tr>
                </tbody>
            </table>
            <br /><br />
            <p><a name="3"><span class="atitle">ICMP数据报</span></a></p>
            <p>Ping命令中需要显示的信息，包括icmp_seq和ttl都已有实现的办法，但还缺rtt往返时间。为了实现这一功能，可利用ICMP数据报携带一个时间戳。使用以下函数生成时间戳：
            <table cellspacing="0" cellpadding="0" width="100%" border="0">
                <tbody>
                    <tr>
                        <td class="code-outline">
                        <pre class="displaycode">#include 
int gettimeofday(struct timeval *tp,void *tzp)
其中timeval结构如下：
		struct timeval{
			long tv_sec;
			long tv_usec;
		}</pre>
                        </td>
                    </tr>
                </tbody>
            </table>
            <br /></p>
            <p>其中tv_sec为秒数，tv_usec微秒数。在发送和接收报文时由gettimeofday分别生成两个timeval结构，两者之差即为往返时间,即ICMP报文发送与接收的时间差，而timeval结构由ICMP数据报携带,tzp指针表示时区，一般都不使用，赋NULL值。</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 cellspacing="0" cellpadding="0" align="right" class="no-print">
                <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/linux/network/ping/index.html#main" cmimpressionsent="1"><strong><font color="#996699">回页首</font></strong></a></td>
                                </tr>
                            </tbody>
                        </table>
                        </td>
                    </tr>
                </tbody>
            </table>
            <br /><br />
            <p><a name="4"><span class="atitle">数据统计</span></a></p>
            <p>系统自带的ping命令当它接送完所有ICMP报文后，会对所有发送和所有接收的ICMP报文进行统计，从而计算ICMP报文丢失的比率。为达此目的，定义两个全局变量：接收计数器和发送计数器，用于记录ICMP报文接受和发送数目。丢失数目=发送总数-接收总数，丢失比率=丢失数目/发送总数。</p>
            <p>现给出模拟Ping程序功能的代码如下：
            <table cellspacing="0" cellpadding="0" width="100%" border="0">
                <tbody>
                    <tr>
                        <td class="code-outline">
                        <pre class="displaycode">/***********************************************************
 * 作者:梁俊辉                                             *
 * 时间:2001年10月                                         *
 * 名称：myping.c                                          *
 * 说明:本程序用于演示ping命令的实现原理                   *
 ***********************************************************/
#include &lt;stdio.h&gt;
#include &lt;signal.h&gt;
#include &lt;arpa/inet.h&gt;
#include &lt;sys/types.h&gt;
#include &lt;sys/socket.h&gt;
#include &lt;unistd.h&gt;
#include &lt;netinet/in.h&gt;
#include &lt;netinet/ip.h&gt;
#include &lt;netinet/ip_icmp.h&gt;
#include &lt;netdb.h&gt;
#include &lt;setjmp.h&gt;
#include &lt;errno.h&gt;
#define PACKET_SIZE     4096
#define MAX_WAIT_TIME   5
#define MAX_NO_PACKETS  3
char sendpacket[PACKET_SIZE];
char recvpacket[PACKET_SIZE];
int sockfd,datalen=56;
int nsend=0,nreceived=0;
struct sockaddr_in dest_addr;
pid_t pid;
struct sockaddr_in from;
struct timeval tvrecv;
void statistics(int signo);
unsigned short cal_chksum(unsigned short *addr,int len);
int pack(int pack_no);
void send_packet(void);
void recv_packet(void);
int unpack(char *buf,int len);
void tv_sub(struct timeval *out,struct timeval *in);
void statistics(int signo)
{       printf(&quot;\n--------------------PING statistics-------------------\n&quot;);
        printf(&quot;%d packets transmitted, %d received , %%%d lost\n&quot;,nsend,nreceived,
                        (nsend-nreceived)/nsend*100);
        close(sockfd);
        exit(1);
}
/*校验和算法*/
unsigned short cal_chksum(unsigned short *addr,int len)
{       int nleft=len;
        int sum=0;
        unsigned short *w=addr;
        unsigned short answer=0;
		
/*把ICMP报头二进制数据以2字节为单位累加起来*/
        while(nleft&gt;1)
        {       sum+=*w++;
                nleft-=2;
        }
		/*若ICMP报头为奇数个字节，会剩下最后一字节。把最后一个字节视为一个2字节数据的高字节，这个2字节数据的低字节为0，继续累加*/
        if( nleft==1)
        {       *(unsigned char *)(&amp;answer)=*(unsigned char *)w;
                sum+=answer;
        }
        sum=(sum&gt;&gt;16)+(sum&amp;0xffff);
        sum+=(sum&gt;&gt;16);
        answer=~sum;
        return answer;
}
/*设置ICMP报头*/
int pack(int pack_no)
{       int i,packsize;
        struct icmp *icmp;
        struct timeval *tval;
        icmp=(struct icmp*)sendpacket;
        icmp-&gt;icmp_type=ICMP_ECHO;
        icmp-&gt;icmp_code=0;
        icmp-&gt;icmp_cksum=0;
        icmp-&gt;icmp_seq=pack_no;
        icmp-&gt;icmp_id=pid;
        packsize=8+datalen;
        tval= (struct timeval *)icmp-&gt;icmp_data;
        gettimeofday(tval,NULL);    /*记录发送时间*/
        icmp-&gt;icmp_cksum=cal_chksum( (unsigned short *)icmp,packsize); /*校验算法*/
        return packsize;
}
/*发送三个ICMP报文*/
void send_packet()
{       int packetsize;
        while( nsend&lt;MAX_NO_PACKETS)
        {       nsend++;
                packetsize=pack(nsend); /*设置ICMP报头*/
                if( sendto(sockfd,sendpacket,packetsize,0,
                          (struct sockaddr *)&amp;dest_addr,sizeof(dest_addr) )&lt;0  )
                {       perror(&quot;sendto error&quot;);
                        continue;
                }
                sleep(1); /*每隔一秒发送一个ICMP报文*/
        }
}
/*接收所有ICMP报文*/
void recv_packet()
{       int n,fromlen;
        extern int errno;
        signal(SIGALRM,statistics);
        fromlen=sizeof(from);
        while( nreceived&lt;nsend)
        {       alarm(MAX_WAIT_TIME);
                if( (n=recvfrom(sockfd,recvpacket,sizeof(recvpacket),0,
                                (struct sockaddr *)&amp;from,&amp;fromlen)) &lt;0)
                {       if(errno==EINTR)continue;
                        perror(&quot;recvfrom error&quot;);
                        continue;
                }
                gettimeofday(&amp;tvrecv,NULL);  /*记录接收时间*/
                if(unpack(recvpacket,n)==-1)continue;
                nreceived++;
        }
}
/*剥去ICMP报头*/
int unpack(char *buf,int len)
{       int i,iphdrlen;
        struct ip *ip;
        struct icmp *icmp;
        struct timeval *tvsend;
        double rtt;
        ip=(struct ip *)buf;
        iphdrlen=ip-&gt;ip_hl&lt;&lt;2;    /*求ip报头长度,即ip报头的长度标志乘4*/
        icmp=(struct icmp *)(buf+iphdrlen);  /*越过ip报头,指向ICMP报头*/
        len-=iphdrlen;            /*ICMP报头及ICMP数据报的总长度*/
        if( len&lt;8)                /*小于ICMP报头长度则不合理*/
        {       printf(&quot;ICMP packets\'s length is less than 8\n&quot;);
                return -1;
        }
        /*确保所接收的是我所发的的ICMP的回应*/
        if( (icmp-&gt;icmp_type==ICMP_ECHOREPLY) &amp;&amp; (icmp-&gt;icmp_id==pid) )
        {       tvsend=(struct timeval *)icmp-&gt;icmp_data;
                tv_sub(&amp;tvrecv,tvsend);  /*接收和发送的时间差*/
                rtt=tvrecv.tv_sec*1000+tvrecv.tv_usec/1000;  /*以毫秒为单位计算rtt*/
                /*显示相关信息*/
                printf(&quot;%d byte from %s: icmp_seq=%u ttl=%d rtt=%.3f ms\n&quot;,
                        len,
                        inet_ntoa(from.sin_addr),
                        icmp-&gt;icmp_seq,
                        ip-&gt;ip_ttl,
                        rtt);
        }
        else    return -1;
}
main(int argc,char *argv[])
{       struct hostent *host;
        struct protoent *protocol;
        unsigned long inaddr=0l;
        int waittime=MAX_WAIT_TIME;
        int size=50*1024;
        if(argc&lt;2)
        {       printf(&quot;usage:%s hostname/IP address\n&quot;,argv[0]);
                exit(1);
        }
        if( (protocol=getprotobyname(&quot;icmp&quot;) )==NULL)
        {       perror(&quot;getprotobyname&quot;);
                exit(1);
        }
        /*生成使用ICMP的原始套接字,这种套接字只有root才能生成*/
        if( (sockfd=socket(AF_INET,SOCK_RAW,protocol-&gt;p_proto) )&lt;0)
        {       perror(&quot;socket error&quot;);
                exit(1);
        }
        /* 回收root权限,设置当前用户权限*/
        setuid(getuid());
        /*扩大套接字接收缓冲区到50K这样做主要为了减小接收缓冲区溢出的
          的可能性,若无意中ping一个广播地址或多播地址,将会引来大量应答*/
        setsockopt(sockfd,SOL_SOCKET,SO_RCVBUF,&amp;size,sizeof(size) );
        bzero(&amp;dest_addr,sizeof(dest_addr));
        dest_addr.sin_family=AF_INET;
        /*判断是主机名还是ip地址*/
        if( inaddr=inet_addr(argv[1])==INADDR_NONE)
        {       if((host=gethostbyname(argv[1]) )==NULL) /*是主机名*/
                {       perror(&quot;gethostbyname error&quot;);
                        exit(1);
                }
                memcpy( (char *)&amp;dest_addr.sin_addr,host-&gt;h_addr,host-&gt;h_length);
        }
        else    /*是ip地址*/
                memcpy( (char *)&amp;dest_addr,(char *)&amp;inaddr,host-&gt;h_length);
        /*获取main的进程id,用于设置ICMP的标志符*/
        pid=getpid();
        printf(&quot;PING %s(%s): %d bytes data in ICMP packets.\n&quot;,argv[1],
                        inet_ntoa(dest_addr.sin_addr),datalen);
        send_packet();  /*发送所有ICMP报文*/
        recv_packet();  /*接收所有ICMP报文*/
        statistics(SIGALRM); /*进行统计*/
        return 0;
}
/*两个timeval结构相减*/
void tv_sub(struct timeval *out,struct timeval *in)
{       if( (out-&gt;tv_usec-=in-&gt;tv_usec)&lt;0)
        {       --out-&gt;tv_sec;
                out-&gt;tv_usec+=1000000;
        }
        out-&gt;tv_sec-=in-&gt;tv_sec;
}
/*------------- The End -----------*/
</pre>
                        </td>
                    </tr>
                </tbody>
            </table>
            <br /></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 cellspacing="0" cellpadding="0" align="right" class="no-print">
                <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/linux/network/ping/index.html#main" cmimpressionsent="1"><strong><font color="#996699">回页首</font></strong></a></td>
                                </tr>
                            </tbody>
                        </table>
                        </td>
                    </tr>
                </tbody>
            </table>
            <br /><br />
            <p><a name="5"><span class="atitle">特别注意</span></a></p>
            <p>只有root用户才能利用socket()函数生成原始套接字，要让Linux的一般用户能执行以上程序，需进行如下的特别操作：</p>
            <p>用root登陆，编译以上程序：gcc -o myping myping.c，其目的有二：一是编译，二是让myping属于root用户。</p>
            <p>再执行chmod u+s myping，目的是把myping程序设成SUID的属性。</p>
            <p>退出root，用一般用户登陆，执行./myping www.cn.ibm.com，有以下执行结果：
            <table cellspacing="0" cellpadding="0" width="100%" border="0">
                <tbody>
                    <tr>
                        <td class="code-outline">
                        <pre class="displaycode">PING www.cn.ibm.com(202.95.2.148): 56 bytes data in ICMP packets.
64 byte from 202.95.2.148: icmp_seq=1 ttl=242 rtt=3029.000 ms
64 byte from 202.95.2.148: icmp_seq=2 ttl=242 rtt=2020.000 ms
64 byte from 202.95.2.148: icmp_seq=3 ttl=242 rtt=1010.000 ms
--------------------PING statistics-------------------
3 packets transmitted, 3 received , %0 lost
</pre>
                        </td>
                    </tr>
                </tbody>
            </table>
            <br /></p>
            <p>由于myping.c是发送完所有的ICMP报文才去接收，因此第一、第二和第三个ICMP报文的往返时间依此是3秒，２秒，１秒，上述结果中rtt信息正反映这一事实。</p>
            <br /><br />
            <p><a name="author"><span class="atitle">关于作者</span></a></p>
            <table cellspacing="0" cellpadding="0" width="100%" border="0">
                <tbody>
                    <tr>
                        <td colspan="3"><img height="5" alt="" src="http://www.ibm.com/i/c.gif" width="100%" /></td>
                    </tr>
                    <tr valign="top" align="left">
                        <td>
                        <p>&nbsp;</p>
                        </td>
                        <td><img height="5" alt="" src="http://www.ibm.com/i/c.gif" width="4" /></td>
                        <td width="100%">
                        <p>梁俊辉,对Linux的网络应用和程序设计有浓厚兴趣,并且专注于这一方面研究，在IBM developerWorks�D�DLinux专区上发表过《NEWT程序设计指南》一文。</p>
                        </td>
                    </tr>
                </tbody>
            </table>
            </td>
        </tr>
    </tbody>
</table>]]>
</description>
<guid isPermaLink="false">http://www.bokee.net/blogmodule/weblogcomment_viewEntry/1987586.html</guid>
<subject>C/C++</subject>
<author>amxiaomao</author>
<category>C/C++</category>
<pubDate>Wed, 16 Jul 2008 16:08:06 CST </pubDate>
</item>

<item>
<title>  void及void指针类型</title>
<link>http://www.bokee.net/blogmodule/weblogcomment_viewEntry/1929465.html</link>
<description>
<![CDATA[<p><br />void真正发挥的作用在于：<br />&nbsp;（1） 对函数返回的限定；<br />　　&nbsp;（2） 对函数参数的限定。<br />&nbsp;<br />有类型可赋值于无类型。<br />但无类型不可赋值于有类型。<br />ps:<br />&nbsp;void *i;<br />&nbsp;int&nbsp;&nbsp; *p;<br />&nbsp;i=p; //正确<br />&nbsp;p=i; //错误<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />规则一 如果函数没有返回值，那么应声明为void类型<br />&nbsp;在C语言中，凡不加返回值类型限定的函数，就会被编译器作为返回整型值处理。<br />规则二如果函数无参数,那么应声明其参数为void<br />&nbsp;int function(void)<br />&nbsp;在C语言中，可以给无参数的函数传送任意类型的参数，但是在C++编译器中编译同样的代码则会出错。<br />&nbsp;因为在C++中，函数参数为void的意思是这个函数不接受任何参数。</p>
<p>规则三 小心使用void 指针类型<br />&nbsp;不能对void指针进行算法操作，即下列操作都是不合法的：<br />&nbsp;void * pvoid;<br />&nbsp;pvoid++; //ANSI：错误<br />&nbsp;pvoid += 1; //ANSI：错误<br />&nbsp;//ANSI标准之所以这样认定，是因为它坚持：进行算法操作的指针必须是确定知道其指向数据类型大小的。</p>
<p>规则四如果函数的参数可以是任意类型指针，那么应声明其参数为 void *<br />&nbsp;这个就不说了，好处大的有。试试就知道了！<br />规则五 void不能代表一个真实的变量<br />&nbsp;能改一下真实的变量？不能。</p>
<p><br /></p>]]>
</description>
<guid isPermaLink="false">http://www.bokee.net/blogmodule/weblogcomment_viewEntry/1929465.html</guid>
<subject>C/C++</subject>
<author>amxiaomao</author>
<category>C/C++</category>
<pubDate>Tue, 24 Jun 2008 09:13:21 CST </pubDate>
</item>

<item>
<title>Flash调用HTML </title>
<link>http://www.bokee.net/blogmodule/weblogcomment_viewEntry/1898891.html</link>
<description>
<![CDATA[<p>/* 版权所有 2003 Macromedia, Inc. 保留所有权利。<br />下列示例代码受最终用户许可协议（随产品附带）中对类似代码限制条款的约束。<br />*/</p>
<p>var ss:TextField.StyleSheet = new TextField.StyleSheet();<br />ss.load(&quot;sample.css&quot;);<br />content.styleSheet = ss;&nbsp; //&nbsp; 调用CSS去悼也行</p>
<p>content.multiline= true;<br />content.wordWrap = true;<br />content.html = true;<br />System.useCodepage =true;<br />story = new XML();<br />story.ignoreWhite = true;<br />story.load(&quot;sample.html&quot;);<br />story.onLoad = function () {&nbsp;<br />&nbsp;content.htmlText = story;<br />}</p>
<p>//以上代码在加入动作中</p>
<p>调用html,与调用text相同</p>
<p>先新建个文本，属性设置为动态文本。</p>]]>
</description>
<guid isPermaLink="false">http://www.bokee.net/blogmodule/weblogcomment_viewEntry/1898891.html</guid>
<subject></subject>
<author>amxiaomao</author>
<category></category>
<pubDate>Mon, 16 Jun 2008 06:29:40 CST </pubDate>
</item>

<item>
<title>SQL查询语句精华文章</title>
<link>http://www.bokee.net/blogmodule/weblogcomment_viewEntry/1892545.html</link>
<description>
<![CDATA[<p>一、 简单查询 <br />简单的Transact-SQL查询只包括选择列表、FROM子句和WHERE子句。它们分别说明所查询列、查询的<br />表或视图、以及搜索条件等。<br />例如，下面的语句查询testtable表中姓名为&ldquo;张三&rdquo;的nickname字段和email字段。 <br />&nbsp;<br />代码:<br />SELECT `nickname`,`email`FROM `testtable`WHERE `name`='张三'<br />(一) 选择列表<br />选择列表(select_list)指出所查询列，它可以是一组列名列表、星号、表达式、变量(包括局部变<br />量和全局变量)等构成。</p>
<p>1、选择所有列<br />例如，下面语句显示testtable表中所有列的数据： <br />&nbsp;<br />代码:<br />SELECT * FROM testtable<br />2、选择部分列并指定它们的显示次序<br />查询结果集合中数据的排列顺序与选择列表中所指定的列名排列顺序相同。<br />例如： <br />&nbsp;<br />代码:<br />SELECT nickname,email FROM testtable<br />3、更改列标题<br />在选择列表中，可重新指定列标题。定义格式为：<br />列标题=列名<br />列名 列标题<br />如果指定的列标题不是标准的标识符格式时，应使用引号定界符，例如，下列语句使用汉字显示列<br />标题： <br />&nbsp;<br />代码:<br />SELECT 昵称=nickname,电子邮件=email&nbsp; FROM testtable <br />4、删除重复行<br />SELECT语句中使用ALL或DISTINCT选项来显示表中符合条件的所有行或删除其中重复的数据行，默认<br />为ALL。使用DISTINCT选项时，对于所有重复的数据行在SELECT返回的结果集合中只保留一行。</p>
<p>5、限制返回的行数<br />使用TOP n [PERCENT]选项限制返回的数据行数，TOP n说明返回n行，而TOP n PERCENT时，说明n是<br />表示一百分数，指定返回的行数等于总行数的百分之几。<br />例如： <br />&nbsp;<br />代码:<br />SELECT TOP 2 * FROM `testtable` <br />&nbsp;<br />代码:<br />SELECT TOP 20 PERCENT * FROM `testtable`<br />(二)FROM子句 <br />FROM子句指定SELECT语句查询及与查询相关的表或视图。在FROM子句中最多可指定256个表或视图，<br />它们之间用逗号分隔。<br />在FROM子句同时指定多个表或视图时，如果选择列表中存在同名列，这时应使用对象名限定这些列<br />所属的表或视图。例如在usertable和citytable表中同时存在cityid列，在查询两个表中的cityid时应<br />使用下面语句格式加以限定： <br />&nbsp;<br />代码:<br />SELECT `username`,citytable.cityid<br />FROM `usertable`,`citytable`<br />WHERE usertable.cityid=citytable.cityid<br />在FROM子句中可用以下两种格式为表或视图指定别名：<br />表名 as 别名<br />表名 别名</p>
<p>(二) FROM子句<br />FROM子句指定SELECT语句查询及与查询相关的表或视图。在FROM子句中最多可指定256个表或视图，<br />它们之间用逗号分隔。<br />在FROM子句同时指定多个表或视图时，如果选择列表中存在同名列，这时应使用对象名限定这些列<br />所属的表或视图。例如在usertable和citytable表中同时存在cityid列，在查询两个表中的cityid时应<br />使用下面语句格式加以限定： <br />&nbsp;<br />代码:<br />SELECT `username`,citytable.cityid<br />FROM `usertable`,`citytable`<br />WHERE usertable.cityid=citytable.cityid<br />在FROM子句中可用以下两种格式为表或视图指定别名： <br />&nbsp;<br />代码:<br />表名 as 别名<br />表名 别名<br />例如上面语句可用表的别名格式表示为： <br />&nbsp;<br />代码:<br />SELECT `username`,b.cityid<br />FROM usertable a,citytable b<br />WHERE a.cityid=b.cityid<br />SELECT不仅能从表或视图中检索数据，它还能够从其它查询语句所返回的结果集合中查询数据。<br />例如： <br />&nbsp;<br />代码:<br />SELECT a.au_fname+a.au_lname<br />FROM authors a,titleauthor ta<br />(SELECT `title_id`,`title`<br />FROM `titles`<br />WHERE ` ytd_sales`&gt;10000<br />) AS t<br />WHERE a.au_id=ta.au_id<br />AND ta.title_id=t.title_id<br />此例中，将SELECT返回的结果集合给予一别名t，然后再从中检索数据。</p>
<p>(三) 使用WHERE子句设置查询条件<br />WHERE子句设置查询条件，过滤掉不需要的数据行。例如下面语句查询年龄大于20的数据： <br />&nbsp;<br />代码:<br />SELECT * FROM usertable WHERE age&gt;20 <br />WHERE子句可包括各种条件运算符：<br />比较运算符(大小比较)：&gt;、&gt;=、=、&lt;、&lt;=、&lt;&gt;、!&gt;、!&lt;<br />范围运算符(表达式值是否在指定的范围)：BETWEEN&hellip;AND&hellip;<br />NOT BETWEEN&hellip;AND&hellip;<br />列表运算符(判断表达式是否为列表中的指定项)：IN (项1,项2&hellip;&hellip;)<br />NOT IN (项1,项2&hellip;&hellip;)<br />模式匹配符(判断值是否与指定的字符通配格式相符)LIKE、NOT LIKE<br />空值判断符(判断表达式是否为空)：IS NULL、NOT IS NULL<br />逻辑运算符(用于多条件的逻辑连接)：NOT、AND、OR<br />1、范围运算符例：age BETWEEN 10 AND 30相当于age&gt;=10 AND age&lt;=30<br />2、列表运算符例：country IN ('Germany','China')<br />3、模式匹配符例：常用于模糊查找，它判断列值是否与指定的字符串格式相匹配。可用于char、<br />varchar、text、ntext、datetime和smalldatetime等类型查询。<br />可使用以下通配字符：<br />百分号%：可匹配任意类型和长度的字符，如果是中文，请使用两个百分号即%%。<br />下划线_：匹配单个任意字符，它常用来限制表达式的字符长度。<br />方括号[]：指定一个字符、字符串或范围，要求所匹配对象为它们中的任一个。<br />[^]：其取值也[] 相同，但它要求所匹配对象为指定字符以外的任一个字符。<br />例如：<br />限制以Publishing结尾，使用LIKE '%Publishing'<br />限制以A开头：LIKE '[A]%'<br />限制以A开头外：LIKE '[^A]%'<br />4、空值判断符例WHERE age IS NULL<br />5、逻辑运算符：优先级为NOT、AND、OR<br />(四)查询结果排序 <br />使用ORDER BY子句对查询返回的结果按一列或多列排序。ORDER BY子句的语法格式为：<br />ORDER BY {column_name [ASC|DESC]} [,&hellip;n]<br />其中ASC表示升序，为默认值，DESC为降序。ORDER BY不能按ntext、text和image数据类型进行排<br />序。<br />例如： <br />&nbsp;<br />代码:<br />SELECT * FROM `usertable` ORDER BY `age` DESC,`userid` ASC<br />另外，可以根据表达式进行排序。</p>
<p>二、 联合查询<br />UNION运算符可以将两个或两个以上上SELECT语句的查询结果集合合并成一个结果集合显示，即执行联<br />合查询。UNION的语法格式为： <br />&nbsp;<br />代码:<br />select_statement<br />UNION [ALL] selectstatement<br />[UNION [ALL] selectstatement][&hellip;n]<br />其中selectstatement为待联合的SELECT查询语句。<br />ALL选项表示将所有行合并到结果集合中。不指定该项时，被联合查询结果集合中的重复行将只保留一<br />行。<br />联合查询时，查询结果的列标题为第一个查询语句的列标题。因此，要定义列标题必须在第一个查询语<br />句中定义。要对联合查询结果排序时，也必须使用第一查询语句中的列名、列标题或者列序号。<br />在使用UNION 运算符时，应保证每个联合查询语句的选择列表中有相同数量的表达式，并且每个查询选<br />择表达式应具有相同的数据类型，或是可以自动将它们转换为相同的数据类型。在自动转换时，对于数值类<br />型，系统将低精度的数据类型转换为高精度的数据类型。<br />在包括多个查询的UNION语句中，其执行顺序是自左至右，使用括号可以改变这一执行顺序。例如：<br />查询1 UNION (查询2 UNION 查询3)</p>
<p>三、连接查询 <br />通过连接运算符可以实现多个表查询。连接是关系数据库模型的主要特点，也是它区别于其它类型<br />数据库管理系统的一个标志。<br />在关系数据库管理系统中，表建立时各数据之间的关系不必确定，常把一个实体的所有信息存放在<br />一个表中。当检索数据时，通过连接操作查询出存放在多个表中的不同实体的信息。连接操作给用户带<br />来很大的灵活性，他们可以在任何时候增加新的数据类型。为不同实体创建新的表，尔后通过连接进行<br />查询。<br />连接可以在SELECT 语句的FROM子句或WHERE子句中建立，似是而非在FROM子句中指出连接时有助于<br />将连接操作与WHERE子句中的搜索条件区分开来。所以，在Transact-SQL中推荐使用这种方法。<br />SQL-92标准所定义的FROM子句的连接语法格式为： <br />&nbsp;<br />代码:<br />FROM join_table join_type join_table [ON (join_condition)]<br />其中join_table指出参与连接操作的表名，连接可以对同一个表操作，也可以对多表操作，对同一<br />个表操作的连接又称做自连接。<br />join_type 指出连接类型，可分为三种：内连接、外连接和交叉连接。内连接(INNER JOIN)使用比<br />较运算符进行表间某(些)列数据的比较操作，并列出这些表中与连接条件相匹配的数据行。根据所使用<br />的比较方式不同，内连接又分为等值连接、自然连接和不等连接三种。<br />外连接分为左外连接(LEFT OUTER JOIN或LEFT JOIN)、右外连接(RIGHT OUTER JOIN或RIGHT JOIN)<br />和全外连接(FULL OUTER JOIN或FULL JOIN)三种。与内连接不同的是，外连接不只列出与连接条件相匹<br />配的行，而是列出左表(左外连接时)、右表(右外连接时)或两个表(全外连接时)中所有符合搜索条件的<br />数据行。<br />交叉连接(CROSS JOIN)没有WHERE 子句，它返回连接表中所有数据行的笛卡尔积，其结果集合中的<br />数据行数等于第一个表中符合查询条件的数据行数乘以第二个表中符合查询条件的数据行数。<br />连接操作中的ON (join_condition) 子句指出连接条件，它由被连接表中的列和比较运算符、逻辑<br />运算符等构成。<br />无论哪种连接都不能对text、ntext和image数据类型列进行直接连接，但可以对这三种列进行间接<br />连接。例如： <br />&nbsp;<br />代码:<br />SELECT p1.pub_id,p2.pub_id,p1.pr_info<br />FROM pub_info AS p1 INNER JOIN pub_info AS p2<br />ON DATALENGTH(p1.pr_info)=DATALENGTH(p2.pr_info)<br />(一)内连接<br />内连接查询操作列出与连接条件匹配的数据行，它使用比较运算符比较被连接列的列值。内连接分<br />三种：<br />1、等值连接：在连接条件中使用等于号(=)运算符比较被连接列的列值，其查询结果中列出被连接<br />表中的所有列，包括其中的重复列。<br />2、不等连接： 在连接条件使用除等于运算符以外的其它比较运算符比较被连接的列的列值。这些<br />运算符包括&gt;、&gt;=、&lt;=、&lt;、!&gt;、!&lt;和&lt;&gt;。<br />3、自然连接：在连接条件中使用等于(=)运算符比较被连接列的列值，但它使用选择列表指出查询<br />结果集合中所包括的列，并删除连接表中的重复列。<br />例，下面使用等值连接列出authors和publishers表中位于同一城市的作者和出版社： <br />&nbsp;<br />代码:<br />SELECT *<br />FROM authors AS a INNER JOIN publishers AS p<br />ON a.city=p.city<br />又如使用自然连接，在选择列表中删除authors 和publishers 表中重复列(city和state)： <br />&nbsp;<br />代码:<br />SELECT a.*,p.pub_id,p.pub_name,p.country<br />FROM authors AS a INNER JOIN publishers AS p<br />ON a.city=p.city<br />(二)外连接<br />内连接时，返回查询结果集合中的仅是符合查询条件( WHERE 搜索条件或 HAVING 条件)和连接条件<br />的行。而采用外连接时，它返回到查询结果集合中的不仅包含符合连接条件的行，而且还包括左表(左外<br />连接时)、右表(右外连接时)或两个边接表(全外连接)中的所有数据行。<br />如下面使用左外连接将论坛内容和作者信息连接起来： <br />&nbsp;<br />代码:<br />SELECT a.*,b.* FROM `luntan` LEFT JOIN usertable as b<br />ON a.username=b.username<br />下面使用全外连接将city表中的所有作者以及user表中的所有作者，以及他们所在的城市： <br />&nbsp;<br />代码:<br />SELECT a.*,b.*<br />FROM city as a FULL OUTER JOIN user as b<br />ON a.username=b.username<br />(三)交叉连接<br />交叉连接不带WHERE 子句，它返回被连接的两个表所有数据行的笛卡尔积，返回到结果集合中的数<br />据行数等于第一个表中符合查询条件的数据行数乘以第二个表中符合查询条件的数据行数。<br />例，titles表中有6类图书，而publishers表中有8家出版社，则下列交叉连接检索到的记录数将等<br />于6*8=48行。 <br />&nbsp;<br />代码:<br />SELECT `type`,`pub_name`<br />FROM `titles` CROSS JOIN `publishers`<br />ORDER BY `type`<br />SQL核心语句(非常实用的几个技巧) </p>
<p>&nbsp; </p>
<p>_ArticleContent1_lblContent&gt;插入数据 </p>
<p>向表中添加一个新记录，你要使用SQL INSERT 语句。这里有一个如何使用这种语句的例子： <br />&nbsp;<br />代码:<br />INSERT mytable (mycolumn) VALUES (&lsquo;some data&rsquo;) <br />这个语句把字符串&rsquo;some data&rsquo;插入表mytable的mycolumn字段中。将要被插入数据的字段的名字在第一个括号中指定，实际的数据在第二个括号中给出。 </p>
<p>INSERT 语句的完整句法如下： <br />&nbsp;<br />代码:<br />INSERT [INTO] {table_name|view_name} [(column_list)] {DEFAULT VALUES | </p>
<p>Values_list | select_statement} <br />如果一个表有多个字段，通过把字段名和字段值用逗号隔开，你可以向所有的字段中插入数据。假设表mytable有三个字段first_column,second_column,和third_column。下面的INSERT语句添加了一条三个字段都有值的完整记录： <br />&nbsp;<br />代码:<br />INSERT mytable (first_column,second_column,third_column) </p>
<p>VALUES (&lsquo;some data&rsquo;,&rsquo;some more data&rsquo;,&rsquo;yet more data&rsquo;) <br />注意 </p>
<p>你可以使用INSERT语句向文本型字段中插入数据。但是，如果你需要输入很长的字符串，你应该使用WRITETEXT语句。这部分内容对本书来说太高级了，因此不加讨论。要了解更多的信息，请参考Microsoft SQL Sever 的文档。 </p>
<p>如果你在INSERT 语句中只指定两个字段和数据会怎么样呢？换句话说，你向一个表中插入一条新记录，但有一个字段没有提供数据。在这种情况下，有下面的四种可能： </p>
<p>如果该字段有一个缺省值，该值会被使用。例如，假设你插入新记录时没有给字段third_column提供数据，而这个字段有一个缺省值&rsquo;some value&rsquo;。在这种情况下，当新记录建立时会插入值&rsquo;some value&rsquo;。 </p>
<p>如果该字段可以接受空值，而且没有缺省值，则会被插入空值。 </p>
<p>如果该字段不能接受空值，而且没有缺省值，就会出现错误。你会收到错误信息： </p>
<p>The column in table mytable may not be null. </p>
<p>最后，如果该字段是一个标识字段，那么它会自动产生一个新值。当你向一个有标识字段的表中插入新记录时，只要忽略该字段，标识字段会给自己赋一个新值。 </p>
<p>注意 </p>
<p>向一个有标识字段的表中插入新记录后，你可以用SQL变量@@identity来访问新记录 </p>
<p>的标识字段的值。考虑如下的SQL语句： <br />&nbsp;<br />代码:<br />INSERT mytable (first_column) VALUES(&lsquo;some value&rsquo;) [code]</p>
<p>[code]INSERT anothertable(another_first,another_second) </p>
<p>VALUES(@@identity,&rsquo;some value&rsquo;) <br />如果表mytable有一个标识字段，该字段的值会被插入表anothertable的another_first字段。这是因为变量@@identity总是保存最后一次插入标识字段的值。 </p>
<p>字段another_first应该与字段first_column有相同的数据类型。但是，字段another_first不能是应该标识字段。Another_first字段用来保存字段first_column的值。 </p>
<p>删除记录 </p>
<p>要从表中删除一个或多个记录，需要使用SQL DELETE语句。你可以给DELETE 语句提供WHERE 子句。WHERE子句用来选择要删除的记录。例如，下面的这个DELETE语句只删除字段first_column的值等于&rsquo;Delete Me&rsquo;的记录： <br />&nbsp;<br />代码:<br />DELETE mytable WHERE first_column=&rsquo;Deltet Me&rsquo; <br />DELETE 语句的完整句法如下： <br />&nbsp;<br />代码:<br />DELETE [FROM] {table_name|view_name} [WHERE clause] <br />在SQL SELECT 语句中可以使用的任何条件都可以在DELECT 语句的WHERE子句 中使用。例如，下面的这个DELETE语句只删除那些first_column字段的值为&rsquo;goodbye&rsquo;或second_column字段的值为&rsquo;so long&rsquo;的记录： <br />&nbsp;<br />代码:<br />DELETE mytable WHERE first_column=&rsquo;goodby&rsquo; OR second_column=&rsquo;so long&rsquo; <br />如果你不给DELETE 语句提供WHERE 子句，表中的所有记录都将被删除。你不应该有这种想法。如果你想删除应该表中的所有记录，应使用第十章所讲的TRUNCATE TABLE语句。 </p>
<p>注意 </p>
<p>为什么要用TRUNCATE TABLE 语句代替DELETE语句？当你使用TRUNCATE TABLE语句时，记录的删除是不作记录的。也就是说，这意味着TRUNCATE TABLE 要比DELETE快得多。 </p>
<p>更新记录 </p>
<p>要修改表中已经存在的一条或多条记录，应使用SQL UPDATE语句。同DELETE语句一样，UPDATE语句可以使用WHERE子句来选择更新特定的记录。请看这个例子： <br />&nbsp;<br />代码:<br />UPDATE mytable SET first_column=&rsquo;Updated!&rsquo; WHERE second_column=&rsquo;Update Me!&rsquo; <br />这个UPDATE 语句更新所有second_column字段的值为&rsquo;Update Me!&rsquo;的记录。对所有被选中的记录，字段first_column的值被置为&rsquo;Updated!&rsquo;。 </p>
<p>下面是UPDATE语句的完整句法： <br />&nbsp;<br />代码:<br />UPDATE {table_name|view_name} SET [{table_name|view_name}] <br />{column_list|variable_list|variable_and_column_list} <br />[,{column_list2|variable_list2|variable_and_column_list2}&hellip; <br />[,{column_listN|variable_listN|variable_and_column_listN}]] <br />[WHERE clause] <br />注意 </p>
<p>你可以对文本型字段使用UPDATE语句。但是，如果你需要更新很长的字符串，应使用UPDATETEXT语句。这部分内容对本书来说太高级了，因此不加讨论。要了解更多的信息，请参考Microsoft SQL Sever 的文档。 </p>
<p>如果你不提供WHERE子句，表中的所有记录都将被更新。有时这是有用的。例如，如果你想把表titles中的所有书的价格加倍，你可以使用如下的UPDATE 语句： </p>
<p>你也可以同时更新多个字段。例如，下面的UPDATE语句同时更新first_column,second_column,和third_column这三个字段： <br />&nbsp;<br />代码:<br />UPDATE mytable SET first_column=&rsquo;Updated!&rsquo; <br />Second_column=&rsquo;Updated!&rsquo; <br />Third_column=&rsquo;Updated!&rsquo; <br />WHERE first_column=&rsquo;Update Me1&rsquo; <br />技巧 </p>
<p>SQL忽略语句中多余的空格。你可以把SQL语句写成任何你最容易读的格式。 </p>
<p>用SELECT 创建记录和表 </p>
<p>你也许已经注意到，INSERT 语句与DELETE语句和UPDATE语句有一点不同，它一次只操作一个记录。然而，有一个方法可以使INSERT 语句一次添加多个记录。要作到这一点，你需要把INSERT 语句与SELECT 语句结合起来，象这样： <br />&nbsp;<br />代码:<br />INSERT mytable (first_column,second_column) <br />SELECT another_first,another_second <br />FROM anothertable <br />WHERE another_first=&rsquo;Copy Me!&rsquo; <br />这个语句从anothertable拷贝记录到mytable.只有表anothertable中字段another_first的值为&rsquo;Copy Me！&rsquo;的记录才被拷贝。 </p>
<p>当为一个表中的记录建立备份时，这种形式的INSERT 语句是非常有用的。在删除一个表中的记录之前，你可以先用这种方法把它们拷贝到另一个表中。 </p>
<p>如果你需要拷贝整个表，你可以使用SELECT INTO 语句。例如，下面的语句创建了一个名为newtable的新表，该表包含表mytable的所有数据： <br />&nbsp;<br />代码:<br />SELECT * INTO newtable FROM mytable <br />你也可以指定只有特定的字段被用来创建这个新表。要做到这一点，只需在字段列表中指定你想要拷贝的字段。另外，你可以使用WHERE 子句来限制拷贝到新表中的记录。下面的例子只拷贝字段second_columnd的值等于&rsquo;Copy Me!&rsquo;的记录的first_column字段。 <br />&nbsp;<br />代码:<br />SELECT first_column INTO newtable <br />FROM mytable <br />WHERE second_column=&rsquo;Copy Me!&rsquo; <br />使用SQL修改已经建立的表是很困难的。例如，如果你向一个表中添加了一个字段，没有容易的办法来去除它。另外，如果你不小心把一个字段的数据类型给错了，你将没有办法改变它。但是，使用本节中讲述的SQL语句，你可以绕过这两个问题。 </p>
<p>例如，假设你想从一个表中删除一个字段。使用SELECT INTO 语句，你可以创建该表的一个拷贝，但不包含要删除的字段。这使你既删除了该字段，又保留了不想删除的数据。 </p>
<p>如果你想改变一个字段的数据类型，你可以创建一个包含正确数据类型字段的新表。创建好该表后，你就可以结合使用UPDATE语句和SELECT 语句，把原来表中的所有数据拷贝到新表中。通过这种方法，你既可以修改表的结构，又能保存原有的数据。 </p>
<p>&nbsp; </p>
<p>_ArticleContent1_lblContent&gt;插入数据 </p>
<p>向表中添加一个新记录，你要使用SQL INSERT 语句。这里有一个如何使用这种语句的例子： <br />&nbsp;<br />代码:<br />INSERT mytable (mycolumn) VALUES (&lsquo;some data&rsquo;) <br />这个语句把字符串&rsquo;some data&rsquo;插入表mytable的mycolumn字段中。将要被插入数据的字段的名字在第一个括号中指定，实际的数据在第二个括号中给出。 </p>
<p>INSERT 语句的完整句法如下： <br />&nbsp;<br />代码:<br />INSERT [INTO] {table_name|view_name} [(column_list)] {DEFAULT VALUES | Values_list | select_statement} <br />如果一个表有多个字段，通过把字段名和字段值用逗号隔开，你可以向所有的字段中插入数据。假设表mytable有三个字段first_column,second_column,和third_column。下面的INSERT语句添加了一条三个字段都有值的完整记录： <br />&nbsp;<br />代码:<br />INSERT mytable (first_column,second_column,third_column) VALUES (&lsquo;some data&rsquo;,&rsquo;some more data&rsquo;,&rsquo;yet more data&rsquo;) <br />[code]<br />注意 </p>
<p>你可以使用INSERT语句向文本型字段中插入数据。但是，如果你需要输入很长的字符串，你应该使用WRITETEXT语句。这部分内容对本书来说太高级了，因此不加讨论。要了解更多的信息，请参考Microsoft SQL Sever 的文档。 </p>
<p>如果你在INSERT 语句中只指定两个字段和数据会怎么样呢？换句话说，你向一个表中插入一条新记录，但有一个字段没有提供数据。在这种情况下，有下面的四种可能： </p>
<p>如果该字段有一个缺省值，该值会被使用。例如，假设你插入新记录时没有给字段third_column提供数据，而这个字段有一个缺省值&rsquo;some value&rsquo;。在这种情况下，当新记录建立时会插入值&rsquo;some value&rsquo;。 </p>
<p>如果该字段可以接受空值，而且没有缺省值，则会被插入空值。 </p>
<p>如果该字段不能接受空值，而且没有缺省值，就会出现错误。你会收到错误信息： </p>
<p>The column in table mytable may not be null. </p>
<p>最后，如果该字段是一个标识字段，那么它会自动产生一个新值。当你向一个有标识字段的表中插入新记录时，只要忽略该字段，标识字段会给自己赋一个新值。 </p>
<p>注意 </p>
<p>向一个有标识字段的表中插入新记录后，你可以用SQL变量@@identity来访问新记录 </p>
<p>的标识字段的值。考虑如下的SQL语句： <br />[code]INSERT mytable (first_column) VALUES(&lsquo;some value&rsquo;) <br />&nbsp;<br />代码:<br />INSERT anothertable(another_first,another_second) VALUES(@@identity,&rsquo;some value&rsquo;) <br />如果表mytable有一个标识字段，该字段的值会被插入表anothertable的another_first字段。这是因为变量@@identity总是保存最后一次插入标识字段的值。 </p>
<p>字段another_first应该与字段first_column有相同的数据类型。但是，字段another_first不能是应该标识字段。Another_first字段用来保存字段first_column的值。 </p>
<p>删除记录 </p>
<p>要从表中删除一个或多个记录，需要使用SQL DELETE语句。你可以给DELETE 语句提供WHERE 子句。WHERE子句用来选择要删除的记录。例如，下面的这个DELETE语句只删除字段first_column的值等于&rsquo;Delete Me&rsquo;的记录： <br />&nbsp;<br />代码:<br />DELETE mytable WHERE first_column=&rsquo;Deltet Me&rsquo; <br />DELETE 语句的完整句法如下： <br />&nbsp;<br />代码:<br />DELETE [FROM] {table_name|view_name} [WHERE clause] <br />在SQL SELECT 语句中可以使用的任何条件都可以在DELECT 语句的WHERE子句 中使用。例如，下面的这个DELETE语句只删除那些first_column字段的值为&rsquo;goodbye&rsquo;或second_column字段的值为&rsquo;so long&rsquo;的记录： <br />&nbsp;<br />代码:<br />DELETE mytable WHERE first_column=&rsquo;goodby&rsquo; OR second_column=&rsquo;so long&rsquo; <br />如果你不给DELETE 语句提供WHERE 子句，表中的所有记录都将被删除。你不应该有这种想法。如果你想删除应该表中的所有记录，应使用第十章所讲的TRUNCATE TABLE语句。 </p>
<p>注意 </p>
<p>为什么要用TRUNCATE TABLE 语句代替DELETE语句？当你使用TRUNCATE TABLE语句时，记录的删除是不作记录的。也就是说，这意味着TRUNCATE TABLE 要比DELETE快得多。 </p>
<p>更新记录 </p>
<p>要修改表中已经存在的一条或多条记录，应使用SQL UPDATE语句。同DELETE语句一样，UPDATE语句可以使用WHERE子句来选择更新特定的记录。请看这个例子： <br />&nbsp;<br />代码:<br />UPDATE mytable SET first_column=&rsquo;Updated!&rsquo; WHERE second_column=&rsquo;Update Me!&rsquo; <br />这个UPDATE 语句更新所有second_column字段的值为&rsquo;Update Me!&rsquo;的记录。对所有被选中的记录，字段first_column的值被置为&rsquo;Updated!&rsquo;。 </p>
<p>下面是UPDATE语句的完整句法： <br />&nbsp;<br />代码:<br />UPDATE {table_name|view_name} SET [{table_name|view_name}] <br />{column_list|variable_list|variable_and_column_list} <br />[,{column_list2|variable_list2|variable_and_column_list2}&hellip; <br />[,{column_listN|variable_listN|variable_and_column_listN}]] <br />[WHERE clause] <br />注意 </p>
<p>你可以对文本型字段使用UPDATE语句。但是，如果你需要更新很长的字符串，应使用UPDATETEXT语句。这部分内容对本书来说太高级了，因此不加讨论。要了解更多的信息，请参考Microsoft SQL Sever 的文档。 </p>
<p>如果你不提供WHERE子句，表中的所有记录都将被更新。有时这是有用的。例如，如果你想把表titles中的所有书的价格加倍，你可以使用如下的UPDATE 语句： </p>
<p>你也可以同时更新多个字段。例如，下面的UPDATE语句同时更新first_column,second_column,和third_column这三个字段： <br />&nbsp;<br />代码:<br />UPDATE mytable SET first_column=&rsquo;Updated!&rsquo; <br />Second_column=&rsquo;Updated!&rsquo; <br />Third_column=&rsquo;Updated!&rsquo; <br />WHERE first_column=&rsquo;Update Me1&rsquo; <br />技巧 </p>
<p>SQL忽略语句中多余的空格。你可以把SQL语句写成任何你最容易读的格式。 </p>
<p>用SELECT 创建记录和表 </p>
<p>你也许已经注意到，INSERT 语句与DELETE语句和UPDATE语句有一点不同，它一次只操作一个记录。然而，有一个方法可以使INSERT 语句一次添加多个记录。要作到这一点，你需要把INSERT 语句与SELECT 语句结合起来，象这样： <br />&nbsp;<br />代码:<br />INSERT mytable (first_column,second_column) <br />SELECT another_first,another_second <br />FROM anothertable <br />WHERE another_first=&rsquo;Copy Me!&rsquo; <br />这个语句从anothertable拷贝记录到mytable.只有表anothertable中字段another_first的值为&rsquo;Copy Me！&rsquo;的记录才被拷贝。 </p>
<p>当为一个表中的记录建立备份时，这种形式的INSERT 语句是非常有用的。在删除一个表中的记录之前，你可以先用这种方法把它们拷贝到另一个表中。 </p>
<p>如果你需要拷贝整个表，你可以使用SELECT INTO 语句。例如，下面的语句创建了一个名为newtable的新表，该表包含表mytable的所有数据： <br />&nbsp;<br />代码:<br />SELECT * INTO newtable FROM mytable <br />你也可以指定只有特定的字段被用来创建这个新表。要做到这一点，只需在字段列表中指定你想要拷贝的字段。另外，你可以使用WHERE 子句来限制拷贝到新表中的记录。下面的例子只拷贝字段second_columnd的值等于&rsquo;Copy Me!&rsquo;的记录的first_column字段。 <br />&nbsp;<br />代码:<br />SELECT first_column INTO newtable <br />FROM mytable <br />WHERE second_column=&rsquo;Copy Me!&rsquo; <br />使用SQL修改已经建立的表是很困难的。例如，如果你向一个表中添加了一个字段，没有容易的办法来去除它。另外，如果你不小心把一个字段的数据类型给错了，你将没有办法改变它。但是，使用本节中讲述的SQL语句，你可以绕过这两个问题。 </p>
<p>例如，假设你想从一个表中删除一个字段。使用SELECT INTO 语句，你可以创建该表的一个拷贝，但不包含要删除的字段。这使你既删除了该字段，又保留了不想删除的数据。 </p>
<p>如果你想改变一个字段的数据类型，你可以创建一个包含正确数据类型字段的新表。创建好该表后，你就可以结合使用UPDATE语句和SELECT 语句，把原来表中的所有数据拷贝到新表中。通过这种方法，你既可以修改表的结构，又能保存原有的数据。<br /></p>]]>
</description>
<guid isPermaLink="false">http://www.bokee.net/blogmodule/weblogcomment_viewEntry/1892545.html</guid>
<subject>数据库</subject>
<author>amxiaomao</author>
<category>数据库</category>
<pubDate>Thu, 12 Jun 2008 18:49:30 CST </pubDate>
</item>

<item>
<title>C破解cmos密码 </title>
<link>http://www.bokee.net/blogmodule/weblogcomment_viewEntry/1863277.html</link>
<description>
<![CDATA[一说到破解cmos密码，你可能说，咳，这有什么难的，用debug <br />o 70 20 <br />o 71 20 <br />不就地了吗。 <br />慢~~~，以上这种方法是通过向cmos芯片随便写入数字，使之在开机检测时无法通过奇偶校验导致cmos芯片数据重新初始化，自然密码也没有了，但是这种方法是破坏性的（暴力！），清除的不止是密码而已，cmos芯片的其他数据，包括cpu频率，ide借口设备等等都被清除了，而且，最重要的一点就是--在你破掉密码之后，别人就知道密码被破解了。这绝对不符合我们的原则---\&quot;我轻轻的走,正如我轻轻的来,敲一下esc,不留下一个足迹....\&quot;. 而用程序将cmos密码读出,绝对不会留下一点痕迹. <br />原理如下:award密码存在cmos芯片的0x1c,0x1d处的两个字节中,将这两个字节的数据读出来,用四进制表示,就是密码了. <br />以下为c语言的源程序: <br /><br />代码： <br />-------------------------------------------------------------------------------- <br /><br />#include &lt;stdio.h&gt; <br />#include &lt;dos.h&gt; <br />#include &lt;conio.h&gt; <br /><br />main() <br />{ <br />int i; <br />char result; <br />char temp=0 <br />printf(\&quot;The award bios password is:\&quot;); <br />outportb(0x70,0x1d); <br />result=inportb(0x71); <br /><br />for(i=6;i&gt;=0;i-=2) <br />{ <br />temp=result; <br />temp&gt;&gt;=i; <br />temp=temp&amp;0x03; <br />printf(\&quot;%d\&quot;,temp); <br />} <br />outportb(0x70,0x1c); <br />result=inportb(0x71); <br /><br />for(i=6;i&gt;=0;i-=2) <br />{ <br />temp=result; <br />temp&gt;&gt;=i; <br />temp=temp&amp;0x03; <br />printf(\&quot;%d\&quot;,temp); <br />} <br />return 0; <br />} <br />]]>
</description>
<guid isPermaLink="false">http://www.bokee.net/blogmodule/weblogcomment_viewEntry/1863277.html</guid>
<subject>C/C++</subject>
<author>amxiaomao</author>
<category>C/C++</category>
<pubDate>Wed, 04 Jun 2008 00:26:56 CST </pubDate>
</item>

<item>
<title>PHP篇:date 与 strtotime的学习</title>
<link>http://www.bokee.net/blogmodule/weblogcomment_viewEntry/1807196.html</link>
<description>
<![CDATA[<p>&lt;?php<br />$nowDate = date(&quot;y-m-d星期w &quot;);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /*获取时间*/<br />echo&nbsp; &quot;今天是:$nowDate&lt;br&gt; &quot;;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /*打印时间*/<br />echo&nbsp; &rsquo;08年以过去了:&rsquo;.date(&quot;z&quot;);&nbsp;/*参数z计算过去了多少天*/<br />echo&nbsp; &quot;&lt;br&gt;&quot;;&nbsp;&nbsp;&nbsp;&nbsp;/*打印回车*/<br />$aoyun=date(&quot;z&quot;,strtotime(&quot;2008-08-08&quot;))-date(&quot;z&quot;); /*计算时间*/<br />echo &quot;距奥运会还有:$aoyun&quot;;&nbsp;/*打印剩下的时间*/<br />?&gt;</p>
<p>&nbsp;</p>
<p>/*PHP,超爽*/</p>
<p>/*使用函式 date() 实现 <br />&lt;?php echo $showtime=date(&quot;Y-m-d H:i:s&quot;);?&gt; <br />显示的格式: 年-月-日 小时:分钟:妙 <br />相关时间参数: <br />a - &quot;am&quot; 或是 &quot;pm&quot; <br />A - &quot;AM&quot; 或是 &quot;PM&quot; <br />d - 几日，二位数字，若不足二位则前面补零; 如: &quot;01&quot; 至 &quot;31&quot; <br />D - 星期几，三个英文字母; 如: &quot;Fri&quot; <br />F - 月份，英文全名; 如: &quot;January&quot; <br />h - 12 小时制的小时; 如: &quot;01&quot; 至 &quot;12&quot; <br />H - 24 小时制的小时; 如: &quot;00&quot; 至 &quot;23&quot; <br />g - 12 小时制的小时，不足二位不补零; 如: &quot;1&quot; 至 12&quot; <br />G - 24 小时制的小时，不足二位不补零; 如: &quot;0&quot; 至 &quot;23&quot; <br />i - 分钟; 如: &quot;00&quot; 至 &quot;59&quot; <br />j - 几日，二位数字，若不足二位不补零; 如: &quot;1&quot; 至 &quot;31&quot; <br />l - 星期几，英文全名; 如: &quot;Friday&quot; <br />m - 月份，二位数字，若不足二位则在前面补零; 如: &quot;01&quot; 至 &quot;12&quot; <br />n - 月份，二位数字，若不足二位则不补零; 如: &quot;1&quot; 至 &quot;12&quot; <br />M - 月份，三个英文字母; 如: &quot;Jan&quot; <br />s - 秒; 如: &quot;00&quot; 至 &quot;59&quot; <br />S - 字尾加英文序数，二个英文字母; 如: &quot;th&quot;，&quot;nd&quot; <br />t - 指定月份的天数; 如: &quot;28&quot; 至 &quot;31&quot; <br />U - 总秒数 <br />w - 数字型的星期几，如: &quot;0&quot; (星期日) 至 &quot;6&quot; (星期六) <br />Y - 年，四位数字; 如: &quot;1999&quot; <br />y - 年，二位数字; 如: &quot;99&quot; <br />z - 一年中的第几天; 如: &quot;0&quot; 至 &quot;365&quot;</p>
<p>*/</p>]]>
</description>
<guid isPermaLink="false">http://www.bokee.net/blogmodule/weblogcomment_viewEntry/1807196.html</guid>
<subject>PHP</subject>
<author>amxiaomao</author>
<category>PHP</category>
<pubDate>Tue, 20 May 2008 17:57:02 CST </pubDate>
</item>

<item>
<title>开源 游戏</title>
<link>http://www.bokee.net/blogmodule/weblogcomment_viewEntry/1795970.html</link>
<description>
<![CDATA[<p><span class="hei18"><font size="3">1</font>.linux的魔兽2啦,是2003年自由软件组推出的,比warcraft好玩得多,设计的也好一些,还有windows的freecraft1.18,在两个平台下可以互联打游戏,我昨天和朋友一起还对联打过!把windows文件下的data copy 到linux下,才可以地图同步!!:)<br />软件说明来自<a href="http://www.linuxeden.com">http://www.linuxeden.com</a></span></p>
<p><span class="hei18">下载：<a href="http://download.it168.com/14/1413/33799/33799_3.shtml">http://download.it168.com/14/1413/33799/33799_3.shtml</a></span></p>
<pre><span class="hei18">2.<a target="_blank" href="http://www.freera.org/">freera </a>&nbsp;<span class="bold">红色警戒 for Linux 
</span><a target="_blank" href="http://www.freera.org/">http://www.freera.org/</a></span></pre>
<pre style="MARGIN-TOP: 0px; MARGIN-BOTTOM: 0px; LINE-HEIGHT: 200%">3.<span class="bold">Mega Mario&nbsp; 又一个超级马利游戏 
</span><span class="bold"><a target="_blank" href="http://prdownloads.sourceforge.net/mmario/MegaMario_v1.3_w32_linux.zip?download">http://prdownloads.sourceforge.net/mmario/MegaMario_v1.3_w32_linux.zip?download</a><br /><a target="_blank" href="http://mmario.sourceforge.net/"></a><a target="_blank" href="http://mmario.sourceforge.net/">http://mmario.sourceforge.net/</a></span></pre>
<pre style="MARGIN-TOP: 0px; MARGIN-BOTTOM: 0px; LINE-HEIGHT: 200%">4.实况网球游戏</pre>
<div>
<pre style="MARGIN-TOP: 0px; MARGIN-BOTTOM: 0px; LINE-HEIGHT: 200%">Free Tennis 是一个前网球运动员发展的一个网球模拟游戏。 它的主要特征是写实主义。 对于游戏可玩性，这意谓你有对打出的抛物线完全控制。 对于图形，它体现运动员现实的姿势。 对于人工智能，它表现出真正的手法。支持网络对战。</pre>
</div>
<pre style="MARGIN-TOP: 0px; MARGIN-BOTTOM: 0px; LINE-HEIGHT: 200%"><a href="http://freetennis.sourceforge.net/"></a><a target="_blank" href="http://freetennis.sourceforge.net/">http://freetennis.sourceforge.net/</a></pre>
<pre style="MARGIN-TOP: 0px; MARGIN-BOTTOM: 0px; LINE-HEIGHT: 200%"><p style="MARGIN-TOP: 0px; MARGIN-BOTTOM: 0px; LINE-HEIGHT: 200%"><font face="arial,Simsun"><font size="3"></font></font></p></pre>
<font size="3"><font face="arial,Simsun"></font></font>]]>
</description>
<guid isPermaLink="false">http://www.bokee.net/blogmodule/weblogcomment_viewEntry/1795970.html</guid>
<subject>游戏</subject>
<author>amxiaomao</author>
<category>游戏</category>
<pubDate>Sat, 17 May 2008 19:03:51 CST </pubDate>
</item>

<item>
<title>自制简漏的终端聊天脚本</title>
<link>http://www.bokee.net/blogmodule/weblogcomment_viewEntry/1768806.html</link>
<description>
<![CDATA[<h6>无聊时用write做了个简单的icq.sh,目前只实现了在同一主机下的所有终端互聊。谈不上什么功能和界面了,主要是抛砖引玉，各位请多修正改进请大家帮着精进啊,谢谢! <br /><br />脚本简单说明： <br /><br />&nbsp;&nbsp;1）由于write默认为root权限，普通用户要使用write必须要先由root授权 <br />授权成功后，可建一普通聊天用户icq(呵呵，不爽就自已改改,当然脚本中的用户名也请相应修改)&nbsp; <br /><br />&nbsp;&nbsp;&nbsp;2)icq用户根下必须要有配置表user.dat,规则为每行为3个字段,分别为序号,tty名,网点名称,字段间以空格分隔.各位可按实际情况编辑生成该表,shell根据这表来选择聊天对像,未在该表中反映的终端和用户将不能应用本shell <br />引用：<em>$cat&nbsp;user.dat <br />1&nbsp;&nbsp;ttyp0&nbsp;沙湾局 <br />2&nbsp;&nbsp;ttyp1&nbsp;乐山局</em><br /><br /><br />&nbsp;&nbsp;&nbsp;3)必须要对方TTY开启并已用icq用户登陆才能与之互聊,聊完之后按Ctrl-d即可退出。已在sco5.0.5&nbsp;ksh下测试通过，在unix下自已和自已聊起来还是别有一番风味的&nbsp;^_^ <br />#/bin/ksh <br />#终端聊天shell&nbsp; <br />trap&nbsp;&rsquo;tput&nbsp;sgr0&nbsp;;&nbsp;rm&nbsp;$HOME/talk.temp&nbsp;$HOME/icq.tmp&nbsp;2&gt;/dev/null&nbsp;;&nbsp;clear&nbsp;;&nbsp;exit&nbsp;0&nbsp;&rsquo;&nbsp;0&nbsp;1&nbsp;3&nbsp;9&nbsp;15 <br />trap&nbsp;&rsquo;&rsquo;&nbsp;2 <br />tput&nbsp;bold <br />clear <br />icqname=&quot;icq&quot; <br /><br />test&nbsp;-e&nbsp;$HOME/user.dat&nbsp;||&nbsp;{&nbsp;echo&nbsp;&quot;\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;用户配置表&nbsp;user.dat&nbsp;不存在\n\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;请联系管理人员解决&nbsp;^_^&nbsp;&quot;&nbsp;;&nbsp;read&nbsp;;&nbsp;exit&nbsp;0&nbsp;;&nbsp;} <br /><br />metty=`tty|awk&nbsp;-F&quot;/&quot;&nbsp;&rsquo;{print&nbsp;$3}&rsquo;` <br /><br />if&nbsp;[&nbsp;-e&nbsp;$HOME/icq.tmp&nbsp;] <br />then <br />me=`awk&nbsp;&rsquo;{print&nbsp;$3}&rsquo;&nbsp;$HOME/icq.tmp` <br />if&nbsp;[&nbsp;&quot;$metty&quot;&nbsp;=&nbsp;&quot;$me&quot;&nbsp;] <br />then <br />yourtty=`awk&nbsp;&rsquo;{print&nbsp;$2}&rsquo;&nbsp;$HOME/icq.tmp`&nbsp; <br />yourname=`awk&nbsp;&rsquo;{&nbsp;if&nbsp;($2==&quot;&rsquo;$yourtty&rsquo;&quot;)&nbsp;print&nbsp;$3}&rsquo;&nbsp;$HOME/user.dat`&nbsp;&nbsp;&nbsp; <br />mename=`awk&nbsp;&rsquo;{if&nbsp;($2==&quot;&rsquo;metty&rsquo;&quot;)&nbsp;print&nbsp;$3}&rsquo;&nbsp;$HOME/user.dat`&nbsp; <br />mexh=`awk&nbsp;&rsquo;{if&nbsp;($2==&quot;&rsquo;metty&rsquo;&quot;)&nbsp;print&nbsp;$1}&rsquo;&nbsp;$HOME/user.dat` <br />clear&nbsp;;&nbsp;mesg&nbsp;-y&nbsp;;&nbsp;echo&nbsp;&quot;\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;你正与&nbsp;${yourname}&nbsp;聊天\n&nbsp;&quot;&nbsp; <br />echo&nbsp;&quot;\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;${mename}&nbsp;正与你聊天,请选择&nbsp;${mexh}&nbsp;与之对聊\n&quot;&nbsp;&gt;/dev/$yourtty <br />/tcb/bin/asroot&nbsp;write&nbsp;$icqname&nbsp;$yourtty&nbsp;;&nbsp;exit&nbsp;0&nbsp; <br />fi <br />fi <br /><br />while&nbsp;: <br />do <br />clear&nbsp; <br />who&nbsp;|&nbsp;awk&nbsp;&rsquo;{print&nbsp;$1,$2}&rsquo;&nbsp;&gt;$HOME/talk.temp <br />sed&nbsp;&rsquo;/&rsquo;&quot;$metty&quot;&rsquo;/d;/^#/d&rsquo;&nbsp;$HOME/user.dat&nbsp;|awk&nbsp;&rsquo;BEGIN{printf(&quot;\n%-5s%-10s%-16s\n&quot;),&quot;序号&quot;,&quot;TTY&quot;,&quot;用户名&quot;}&nbsp;\ <br />{printf(&quot;%-5s%-10s%-16s\n&quot;),$1,$2,$3}&rsquo;&nbsp; <br /><br />echo&nbsp;-n&nbsp;&nbsp;&quot;\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;请输入对方的序号(q键退出程序):&nbsp;&nbsp;&nbsp;&quot; <br />read&nbsp;xh <br />test&nbsp;&quot;$xh&quot;&nbsp;=&nbsp;&quot;q&quot;&nbsp;-o&nbsp;&quot;$xh&quot;&nbsp;=&nbsp;&quot;Q&quot;&nbsp;&amp;&amp;&nbsp;exit&nbsp;0&nbsp;&nbsp;&nbsp; <br />yourtty=`awk&nbsp;&rsquo;{if&nbsp;($1==&quot;&rsquo;$xh&rsquo;&quot;)&nbsp;print&nbsp;$2&nbsp;}&rsquo;&nbsp;$HOME/user.dat&nbsp;2&gt;/dev/null` <br />test&nbsp;-z&nbsp;&quot;$yourtty&quot;&nbsp;&amp;&amp;&nbsp;{&nbsp;echo&nbsp;&quot;\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$xh&nbsp;未配置TTY\n&quot;&nbsp;;&nbsp;read&nbsp;;&nbsp;continue&nbsp;;&nbsp;} <br /><br />ut=`awk&nbsp;&rsquo;{if&nbsp;($2==&quot;&rsquo;$yourtty&rsquo;&quot;)&nbsp;print&nbsp;$2}&rsquo;&nbsp;$HOME/talk.temp&nbsp;2&gt;/dev/null` <br />test&nbsp;-z&nbsp;&quot;$ut&quot;&nbsp;&amp;&amp;&nbsp;{&nbsp;echo&nbsp;&quot;\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;${ut}&nbsp;终端未登陆\n&quot;&nbsp;;&nbsp;read&nbsp;;&nbsp;echo&nbsp;$icqname&nbsp;$metty&nbsp;$yourtty&nbsp;&gt;&nbsp;$HOME/icq.tmp&nbsp;;&nbsp;continue&nbsp;;&nbsp;}&nbsp; <br /><br />yn=`awk&nbsp;&rsquo;{if&nbsp;($1==&quot;&rsquo;$icqname&rsquo;&quot;&nbsp;&amp;&amp;&nbsp;$2==&quot;&rsquo;$ut&rsquo;&quot;)&nbsp;print&nbsp;$1,$2}&rsquo;&nbsp;$HOME/talk.temp&nbsp;2&gt;/dev/null` <br />test&nbsp;-z&nbsp;&quot;$yn&quot;&nbsp;&amp;&amp;&nbsp;{&nbsp;echo&nbsp;&quot;\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$icqname&nbsp;用户未在&nbsp;$ut&nbsp;终端上登陆\n&quot;&nbsp;;&nbsp;read&nbsp;;&nbsp;\ <br />echo&nbsp;$icqname&nbsp;$metty&nbsp;$yourtty&nbsp;&gt;&nbsp;$HOME/icq.tmp&nbsp;;&nbsp;continue&nbsp;;&nbsp;&nbsp;}&nbsp;||&nbsp;break&nbsp; <br />done <br />mesg&nbsp;-y <br />clear <br />echo&nbsp;$icqname&nbsp;$metty&nbsp;$yourtty&nbsp;&gt;&nbsp;$HOME/icq.tmp&nbsp; <br />yourname=`awk&nbsp;&rsquo;{if&nbsp;($2==&quot;&rsquo;$ut&rsquo;&quot;)&nbsp;print&nbsp;$3&nbsp;}&rsquo;&nbsp;$HOME/user.dat` <br />mename=`awk&nbsp;&rsquo;{if&nbsp;($2==&quot;&rsquo;$metty&rsquo;&quot;)&nbsp;print&nbsp;$3&nbsp;}&rsquo;&nbsp;$HOME/user.dat` <br />mexh=`awk&nbsp;&rsquo;{if&nbsp;($2==&quot;&rsquo;$metty&rsquo;&quot;)&nbsp;print&nbsp;$1&nbsp;}&rsquo;&nbsp;$HOME/user.dat` <br />echo&nbsp;&quot;\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;你正与&nbsp;${yourname}&nbsp;聊天\n&quot; <br />echo&nbsp;&quot;\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;你正与&nbsp;${mename}&nbsp;聊天\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;请选择&nbsp;${mexh}&nbsp;与之对聊\n&quot;&nbsp;&gt;/dev/$yourtty <br />/tcb/bin/asroot&nbsp;write&nbsp;$icqname&nbsp;$yourtty</h6>]]>
</description>
<guid isPermaLink="false">http://www.bokee.net/blogmodule/weblogcomment_viewEntry/1768806.html</guid>
<subject>linux</subject>
<author>amxiaomao</author>
<category>linux</category>
<pubDate>Sun, 11 May 2008 16:32:10 CST </pubDate>
</item>

<item>
<title>好久没更新了~~</title>
<link>http://www.bokee.net/blogmodule/weblogcomment_viewEntry/1723903.html</link>
<description>
<![CDATA[&nbsp; 更新一下~]]>
</description>
<guid isPermaLink="false">http://www.bokee.net/blogmodule/weblogcomment_viewEntry/1723903.html</guid>
<subject></subject>
<author>amxiaomao</author>
<category></category>
<pubDate>Tue, 29 Apr 2008 22:03:45 CST </pubDate>
</item>

</channel>
</rss>