﻿<?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>IT博客-textbox-随笔分类-概念</title><link>http://www.cnitblog.com/textbox/category/8658.html</link><description /><language>zh-cn</language><lastBuildDate>Mon, 26 Sep 2011 14:39:03 GMT</lastBuildDate><pubDate>Mon, 26 Sep 2011 14:39:03 GMT</pubDate><ttl>60</ttl><item><title>winInet 的错误描述</title><link>http://www.cnitblog.com/textbox/archive/2011/03/17/73127.html</link><dc:creator>零度</dc:creator><author>零度</author><pubDate>Thu, 17 Mar 2011 07:31:00 GMT</pubDate><guid>http://www.cnitblog.com/textbox/archive/2011/03/17/73127.html</guid><wfw:comment>http://www.cnitblog.com/textbox/comments/73127.html</wfw:comment><comments>http://www.cnitblog.com/textbox/archive/2011/03/17/73127.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/textbox/comments/commentRss/73127.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/textbox/services/trackbacks/73127.html</trackback:ping><description><![CDATA[
		<pre class="in_text">   12001       ERROR_INTERNET_OUT_OF_HANDLES
               No more handles could be generated at this time.

   12002       ERROR_INTERNET_TIMEOUT
               The request has timed out.

   12003       ERROR_INTERNET_EXTENDED_ERROR
               An extended error was returned from the server. This is
               typically a string or buffer containing a verbose error
               message. Call InternetGetLastResponseInfo to retrieve the
               error text.

   12004       ERROR_INTERNET_INTERNAL_ERROR
               An internal error has occurred.

   12005       ERROR_INTERNET_INVALID_URL
               The URL is invalid.

   12006       ERROR_INTERNET_UNRECOGNIZED_SCHEME
               The URL scheme could not be recognized or is not supported.

   12007       ERROR_INTERNET_NAME_NOT_RESOLVED
               The server name could not be resolved.

   12008       ERROR_INTERNET_PROTOCOL_NOT_FOUND
               The requested protocol could not be located.

   12009       ERROR_INTERNET_INVALID_OPTION
               A request to InternetQueryOption or InternetSetOption
               specified an invalid option value.

   12010       ERROR_INTERNET_BAD_OPTION_LENGTH
               The length of an option supplied to InternetQueryOption or
               InternetSetOption is incorrect for the type of option
               specified.

   12011       ERROR_INTERNET_OPTION_NOT_SETTABLE
               The request option cannot be set, only queried.

   12012       ERROR_INTERNET_SHUTDOWN
               The Win32 Internet function support is being shut down or
               unloaded.

   12013       ERROR_INTERNET_INCORRECT_USER_NAME
               The request to connect and log on to an FTP server could
               not be completed because the supplied user name is
               incorrect.

   12014       ERROR_INTERNET_INCORRECT_PASSWORD
               The request to connect and log on to an FTP server could
               not be completed because the supplied password is
               incorrect.

   12015       ERROR_INTERNET_LOGIN_FAILURE
               The request to connect to and log on to an FTP server
               failed.

   12016       ERROR_INTERNET_INVALID_OPERATION
               The requested operation is invalid.

   12017       ERROR_INTERNET_OPERATION_CANCELLED
               The operation was canceled, usually because the handle on
               which the request was operating was closed before the
               operation completed.

   12018       ERROR_INTERNET_INCORRECT_HANDLE_TYPE
               The type of handle supplied is incorrect for this
               operation.

   12019       ERROR_INTERNET_INCORRECT_HANDLE_STATE
               The requested operation cannot be carried out because the
               handle supplied is not in the correct state.

   12020       ERROR_INTERNET_NOT_PROXY_REQUEST
               The request cannot be made via a proxy.

   12021       ERROR_INTERNET_REGISTRY_VALUE_NOT_FOUND
               A required registry value could not be located.

   12022       ERROR_INTERNET_BAD_REGISTRY_PARAMETER
               A required registry value was located but is an incorrect
               type or has an invalid value.

   12023       ERROR_INTERNET_NO_DIRECT_ACCESS
               Direct network access cannot be made at this time.

   12024       ERROR_INTERNET_NO_CONTEXT
               An asynchronous request could not be made because a zero
               context value was supplied.

   12025       ERROR_INTERNET_NO_CALLBACK
               An asynchronous request could not be made because a
               callback function has not been set.

   12026       ERROR_INTERNET_REQUEST_PENDING
               The required operation could not be completed because one
               or more requests are pending.

   12027       ERROR_INTERNET_INCORRECT_FORMAT
               The format of the request is invalid.

   12028       ERROR_INTERNET_ITEM_NOT_FOUND
               The requested item could not be located.

   12029       ERROR_INTERNET_CANNOT_CONNECT
               The attempt to connect to the server failed.

   12030       ERROR_INTERNET_CONNECTION_ABORTED
               The connection with the server has been terminated.

   12031       ERROR_INTERNET_CONNECTION_RESET
               The connection with the server has been reset.

   12032       ERROR_INTERNET_FORCE_RETRY
               Calls for the Win32 Internet function to redo the request.

   12033       ERROR_INTERNET_INVALID_PROXY_REQUEST
               The request to the proxy was invalid.

   12036       ERROR_INTERNET_HANDLE_EXISTS
               The request failed because the handle already exists.

   12037       ERROR_INTERNET_SEC_CERT_DATE_INVALID
               SSL certificate date that was received from the server is
               bad. The certificate is expired.

   12038       ERROR_INTERNET_SEC_CERT_CN_INVALID
               SSL certificate common name (host name field) is incorrect.
               For example, if you entered www.server.com and the common
               name on the certificate says www.different.com.

   12039       ERROR_INTERNET_HTTP_TO_HTTPS_ON_REDIR
               The application is moving from a non-SSL to an SSL
               connection because of a redirect.

   12040       ERROR_INTERNET_HTTPS_TO_HTTP_ON_REDIR
               The application is moving from an SSL to an non-SSL
               connection because of a redirect.

   12041       ERROR_INTERNET_MIXED_SECURITY
               Indicates that the content is not entirely secure. Some of
               the content being viewed may have come from unsecured
               servers.

   12042       ERROR_INTERNET_CHG_POST_IS_NON_SECURE
               The application is posting and attempting to change
               multiple lines of text on a server that is not secure.

   12043       ERROR_INTERNET_POST_IS_NON_SECURE
               The application is posting data to a server that is not
               secure.

   12110       ERROR_FTP_TRANSFER_IN_PROGRESS
               The requested operation cannot be made on the FTP session
               handle because an operation is already in progress.

   12111       ERROR_FTP_DROPPED
               The FTP operation was not completed because the session was
               aborted.

   12130       ERROR_GOPHER_PROTOCOL_ERROR
               An error was detected while parsing data returned from the
               gopher server.

   12131       ERROR_GOPHER_NOT_FILE
               The request must be made for a file locator.

   12132       ERROR_GOPHER_DATA_ERROR
               An error was detected while receiving data from the gopher
               server.

   12133       ERROR_GOPHER_END_OF_DATA
               The end of the data has been reached.

   12134       ERROR_GOPHER_INVALID_LOCATOR
               The supplied locator is not valid.

   12135       ERROR_GOPHER_INCORRECT_LOCATOR_TYPE
               The type of the locator is not correct for this operation.

   12136       ERROR_GOPHER_NOT_GOPHER_PLUS
               The requested operation can only be made against a Gopher+
               server or with a locator that specifies a Gopher+
               operation.

   12137       ERROR_GOPHER_ATTRIBUTE_NOT_FOUND
               The requested attribute could not be located.

   12138       ERROR_GOPHER_UNKNOWN_LOCATOR
               The locator type is unknown.

   12150       ERROR_HTTP_HEADER_NOT_FOUND
               The requested header could not be located.

   12151       ERROR_HTTP_DOWNLEVEL_SERVER
               The server did not return any headers.

   12152       ERROR_HTTP_INVALID_SERVER_RESPONSE
               The server response could not be parsed.

   12153       ERROR_HTTP_INVALID_HEADER
               The supplied header is invalid.

   12154       ERROR_HTTP_INVALID_QUERY_REQUEST
               The request made to HttpQueryInfo is invalid.

   12155       ERROR_HTTP_HEADER_ALREADY_EXISTS
               The header could not be added because it already exists.

   12156       ERROR_HTTP_REDIRECT_FAILED
               The redirection failed because either the scheme changed
               (for example, HTTP to FTP) or all attempts made to redirect
               failed (default is five attempts).
</pre>
<img src ="http://www.cnitblog.com/textbox/aggbug/73127.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/textbox/" target="_blank">零度</a> 2011-03-17 15:31 <a href="http://www.cnitblog.com/textbox/archive/2011/03/17/73127.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>看完以下的网络资料应该可以很好的理解字符编码问题.以后乱码也不用摸不着头了.</title><link>http://www.cnitblog.com/textbox/archive/2011/03/03/72910.html</link><dc:creator>零度</dc:creator><author>零度</author><pubDate>Thu, 03 Mar 2011 01:06:00 GMT</pubDate><guid>http://www.cnitblog.com/textbox/archive/2011/03/03/72910.html</guid><wfw:comment>http://www.cnitblog.com/textbox/comments/72910.html</wfw:comment><comments>http://www.cnitblog.com/textbox/archive/2011/03/03/72910.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/textbox/comments/commentRss/72910.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/textbox/services/trackbacks/72910.html</trackback:ping><description><![CDATA[
		<strong>文章一<br /></strong>文章来自:http://zhou304082042.javaeye.com/blog/624301<br /><br />   久很久以前，有一群人，他们决定用8个可以开合的晶体管来组合成不同的状态，以表示世界上的万物。他们认为8个开关状态作为原子单位很好，于是他们把这称为"字节"。 <br /><br />再后来，他们又做了一些可以处理这些字节的机器，机器开动了，可以用字节来组合出更多的状态，状态开始变来变去。他们看到这样是好的，于是它们就这机器称为"计算机"。 <br /><br />开始计算机只在美国用。八位的字节一共可以组合出256（2的8次方）种不同的状态。 <br /><br />他们把其中的编号从0开始的32种状态分别规定了特殊的用途，一但终端设备或者打印机遇上这些约定好的字节时，就要做一些约定的动作。遇上 00x10, 终端就换行，遇上0x07, 终端就向人们嘟嘟叫，例好遇上0x1b, 打印机就打印反白的字，对于终端就用彩色显示字母。他们看到这样很好，于是就把这些0x20（十进制32）以下的字节状态称为"控制码"。 <br />他们又把所有的空格、标点符号、数字、大小写字母分别用连续的字节状态表示，一直编到了第127号，这样计算机就可以用不同字节来存储英语的 文字了。大家看到这样，都感觉很好，于是大家都把这个方案叫做 ANSI 的"Ascii"编码（American Standard Code for Information Interchange，美国信息互换标准代码）。当时世界上所有的计算机都用同样的ASCII方案来保存英文文字。 <br /><br />后来，就像建造巴比伦塔一样，世界各地的都开始使用计算机，但是很多国家用的不是英文，他们用到的许多字母在ASCII中根本没有，为了也可以在计算机中保存他们的文字，他们决定采用127号之后的空位来表示这些新的字母、符号，还加入了很多画表格时需要用下到的横线、竖线、交叉等形状，一直把序号编到了最后一个状态255。从128到255这一页的字符集被称"扩展字符集"。从此之后，贪婪的人类再没有新的状态可以用了，美帝国主义可能没有想到还有第三世界国家的人们也希望可以用到计算机吧！ <br /><br />等中国人们得到计算机时，已经没有可以利用的字节状态来表示汉字，况且有6000多个常用汉字需要保存呢。但是这难不倒智慧的中国人民，我们不客气地把那些127号之后的奇异符号们直接取消掉，并且规定：一个小于127的字符的意义与原来相同，但两个大于127的字符连在一起时，就表示一个汉字，前面的一个字节（他称之为高字节）从0xA1用到 0xF7，后面一个字节（低字节）从0xA1到0xFE，这样我们就可以组合出大约7000多个简体汉字了。在这些编码里，我们还把数学符号、罗马希腊的字母、日文的假名们都编进去了，连在 ASCII 里本来就有的数字、标点、字母都统统重新编了两个字节长的编码，这就是常说的"全角"字符，而原来在127号以下的那些就叫"半角"字符了。 <br /><br />中国人民看到这样很不错，于是就把这种汉字方案叫做"GB2312"。GB2312 是对 ASCII 的中文扩展。 <br /><br />但是中国的汉字太多了，我们很快就就发现有许多人的人名没有办法在这里打出来，特别是某些很会麻烦别人的国家领导人（如朱镕基的“镕”字）。于是我们不得不继续把 GB2312 没有用到的码位找出来老实不客气地用上。 <br /><br />后来还是不够用，于是干脆不再要求低字节一定是127号之后的内码，只要第一个字节是大于127就固定表示这是一个汉字的开始，不管后面跟的是不是扩展字符集里的内容。结果扩展之后的编码方案被称为 GBK 标准，GBK 包括了 GB2312 的所有内容，同时又增加了近20000个新的汉字（包括繁体字）和符号。 <br /><br />后来少数民族也要用电脑了，于是我们再扩展，又加了几千个新的少数民族的字，GBK 扩成了 GB18030。从此之后，中华民族的文化就可以在计算机时代中传承了。 <br /><br />中国的程序员们看到这一系列汉字编码的标准是好的，于是通称他们叫做 "DBCS"（Double Byte Charecter Set 双字节字符集）。在DBCS系列标准里，最大的特点是两字节长的汉字字符和一字节长的英文字符并存于同一套编码方案里，因此他们写的程序为了支持中文处 理，必须要注意字串里的每一个字节的值，如果这个值是大于127的，那么就认为一个双字节字符集里的字符出现了。那时候凡是受过加持，会编程的计算机僧侣们都要每天念下面这个咒语数百遍： <br /><br />"一个汉字算两个英文字符！一个汉字算两个英文字符……" <br /><br /><br /><br />因为当时各个国家都像中国这样搞出一套自己的编码标准，结果互相之间谁也不懂谁的编码，谁也不支持别人的编码，连大陆和台湾这样只相隔了150海里，使用着同一种语言的兄弟地区，也分别采用了不同的 DBCS 编码方案——当时的中国人想让电脑显示汉字，就必须装上一个"汉字系统"，专门用来处理汉字的显示、输入的问题，但是那个台湾的愚昧封建人士写的算命程序 就必须加装另一套支持 BIG5 编码的什么"倚天汉字系统"才可以用，装错了字符系统，显示就会乱了套！这怎么办？而且世界民族之林中还有那些一时用不上电脑的穷苦人民，他们的文字又怎 么办？ <br /><br />真是计算机的巴比伦塔命题啊！ <br /><br />正在这时，大天使加百列及时出现了——一个叫 ISO （国际标谁化组织）的国际组织决定着手解决这个问题。他们采用的方法很简单：废了所有的地区性编码方案，重新搞一个包括了地球上所有文化、所有字母和符号的编码！他们打算叫它"Universal Multiple-Octet Coded Character Set"，简称 UCS, 俗称 "UNICODE"。 <br /><br />UNICODE 开始制订时，计算机的存储器容量极大地发展了，空间再也不成为问题了。于是 ISO 就直接规定必须用两个字节，也就是16位来统一表示所有的字符，对于ascii里的那些"半角"字符，UNICODE 包持其原编码不变，只是将其长度由原来的8位扩展为16位，而其他文化和语言的字符则全部重新统一编码。由于"半角"英文符号只需要用到低8位，所以其高 8位永远是0，因此这种大气的方案在保存英文文本时会多浪费一倍的空间。 <br /><br />这时候，从旧社会里走过来的程序员开始发现一个奇怪的现象：他们的strlen函数靠不住了，一个汉字不再是相当于两个字符了，而是一个！是 的，从 UNICODE 开始，无论是半角的英文字母，还是全角的汉字，它们都是统一的"一个字符"！同时，也都是统一的"两个字节"，请注意"字符"和"字节"两个术语的不同， "字节"是一个8位的物理存贮单元，而"字符"则是一个文化相关的符号。在UNICODE 中，一个字符就是两个字节。一个汉字算两个英文字符的时代已经快过去了。 <br /><br />从前多种字符集存在时，那些做多语言软件的公司遇上过很大麻烦，他们为了在不同的国家销售同一套软件，就不得不在区域化软件时也加持那个双字 节字符集咒语，不仅要处处小心不要搞错，还要把软件中的文字在不同的字符集中转来转去。UNICODE 对于他们来说是一个很好的一揽子解决方案，于是从 Windows NT 开始，MS 趁机把它们的操作系统改了一遍，把所有的核心代码都改成了用 UNICODE 方式工作的版本，从这时开始，WINDOWS 系统终于无需要加装各种本土语言系统，就可以显示全世界上所有文化的字符了。 <br /><br />但是，UNICODE 在制订时没有考虑与任何一种现有的编码方案保持兼容，这使得 GBK 与UNICODE 在汉字的内码编排上完全是不一样的，没有一种简单的算术方法可以把文本内容从UNICODE编码和另一种编码进行转换，这种转换必须通过查表来进行。 <br /><br />如前所述，UNICODE 是用两个字节来表示为一个字符，他总共可以组合出65535不同的字符，这大概已经可以覆盖世界上所有文化的符号。如果还不够也没有关系，ISO已经准备了UCS-4方案，说简单了就是四个字节来表示一个字符，这样我们就可以组合出21亿个不同的字符出来（最高位有其他用途），这大概可以用到银河联邦成立那一天吧！ <br /><br />UNICODE 来到时，一起到来的还有计算机网络的兴起，UNICODE 如何在网络上传输也是一个必须考虑的问题，于是面向传输的众多 UTF（UCS Transfer Format）标准出现了，顾名思义，UTF8就是每次8个位传输数据，而UTF16就是每次16个位，只不过为了传输时的可靠性，从UNICODE到 UTF时并不是直接的对应，而是要过一些算法和规则来转换。 <br /><br />受到过网络编程加持的计算机僧侣们都知道，在网络里传递信息时有一个很重要的问题，就是对于数据高低位的解读方式，一些计算机是采用低位先发送的方法，例如我们PC机采用的 INTEL 架构；而另一些是采用高位先发送的方式。在网络中交换数据时，为了核对双方对于高低位的认识是否是一致的，采用了一种很简便的方法，就是在文本流的开始时 向对方发送一个标志符——如果之后的文本是高位在位，那就发送"FEFF"，反之，则发送"FFFE"。不信你可以用二进制方式打开一个UTF-X格式的 文件，看看开头两个字节是不是这两个字节？ <br /><br /><br /><br />下面是Unicode和UTF-8转换的规则 <br /><br />Unicode      UTF-8 <br />0000 - 007F 0xxxxxxx <br />0080 - 07FF 110xxxxx 10xxxxxx <br />0800 - FFFF 1110xxxx 10xxxxxx 10xxxxxx <br /><br />例如"汉"字的Unicode编码是6C49。6C49在0800-FFFF之间，所以要用3字节模板：1110xxxx 10xxxxxx 10xxxxxx。将6C49写成二进制是：0110 1100 0100 1001，将这个比特流按三字节模板的分段方法分为0110 110001 001001，依次代替模板中的x，得到：1110-0110 10-110001 10-001001，即E6 B1 89，这就是其UTF8的编码。 <br /><br /><br />讲到这里，我们再顺便说说一个很著名的奇怪现象：当你在 windows 的记事本里新建一个文件，输入"联通"两个字之后，保存，关闭，然后再次打开，你会发现这两个字已经消失了，代之的是几个乱码！呵呵，有人说这就是联通之所以拼不过移动的原因。 <br /><br />其实这是因为GB2312编码与UTF8编码产生了编码冲撞的原因。 <br /><br />当一个软件打开一个文本时，它要做的第一件事是决定这个文本究竟是使用哪种字符集的哪种编码保存的。软件一般采用三种方式来决定文本的字符集和编码： <br /><br />检测文件头标识，提示用户选择，根据一定的规则猜测 <br /><br />最标准的途径是检测文本最开头的几个字节，开头字节 Charset/encoding,如下表： <br /><br />EF BB BF UTF-8 <br /><br />FE FF UTF-16/UCS-2, little endian <br /><br />FF FE UTF-16/UCS-2, big endian <br /><br />FF FE 00 00 UTF-32/UCS-4, little endian. <br /><br />00 00 FE FF UTF-32/UCS-4, big-endian. <br /><br />2009-01-31 15:10 Kevin Yang <br /><br /><br />当你新建一个文本文件时，记事本的编码默认是ANSI（代表系统默认编码，在中文系统中一般是GB系列编码）, 如果你在ANSI的编码输入汉字，那么他实际就是GB系列的编码方式，在这种编码下，"联通"的内码是： <br />c1 1100 0001 <br /><br />aa 1010 1010 <br /><br />cd 1100 1101 <br /><br />a8 1010 1000 <br /><br />注意到了吗？第一二个字节、第三四个字节的起始部分的都是"110"和"10"，正好与UTF8规则里的两字节模板是一致的， <br /><br />于是当我们再次打开记事本时，记事本就误认为这是一个UTF8编码的文件，让我们把第一个字节的110和第二个字节的10去掉，我们就得到了"00001 101010"，再把各位对齐，补上前导的0，就得到了"0000 0000 0110 1010"，不好意思，这是UNICODE的006A，也就是小写的字母"j"，而之后的两字节用UTF8解码之后是0368，这个字符什么也不是。这就是只有"联通"两个字的文件没有办法在记事本里正常显示的原因。 <br /><br />而如果你在"联通"之后多输入几个字，其他的字的编码不见得又恰好是110和10开始的字节，这样再次打开时，记事本就不会坚持这是一个utf8编码的文件，而会用ANSI的方式解读之，这时乱码又不出现了 <br />==============================================================================================================<br /><strong>文章二:谈谈Unicode编码，简要解释UCS、UTF、BMP、BOM等名词 <br /></strong>这是一篇程序员写给程序员的趣味读物。所谓趣味是指可以比较轻松地了解一些原来不清楚的概念，增进知识，类似于打RPG游戏的升级。整理这篇文章的动机是两个问题： 
<dl><dt>问题一： 
</dt><dd><br />使用Windows记事本的“另存为”，可以在GBK、Unicode、Unicode big endian和UTF-8这几种编码方式间相互转换。同样是txt文件，Windows是怎样识别编码方式的呢？ <br />我很早前就发现Unicode、Unicode big endian和UTF-8编码的txt文件的开头会多出几个字节，分别是FF、FE（Unicode）,FE、FF（Unicode big endian）,EF、BB、BF（UTF-8）。但这些标记是基于什么标准呢？ 
</dd><dt>问题二： 
</dt><dd>最近在网上看到一个ConvertUTF.c，实现了UTF-32、UTF-16和UTF-8这三种编码方式的相互转换。对于Unicode(UCS2)、GBK、UTF-8这些编码方式，我原来就了解。但这个程序让我有些糊涂，想不起来UTF-16和UCS2有什么关系。 </dd></dl><br />查了查相关资料，总算将这些问题弄清楚了，顺带也了解了一些Unicode的细节。写成一篇文章，送给有过类似疑问的朋友。本文在写作时尽量做到通俗易懂，但要求读者知道什么是字节，什么是十六进制。 0、big endian和little endian <br />big endian和little endian是CPU处理多字节数的不同方式。例如“汉”字的Unicode编码是6C49。那么写到文件里时，究竟是将6C写在前面，还是将49写在前面？如果将6C写在前面，就是big endian。如果将49写在前面，就是little endian。 <br />“endian”这个词出自《格列佛游记》。小人国的内战就源于吃鸡蛋时是究竟从大头(Big-Endian)敲开还是从小头(Little-Endian)敲开，由此曾发生过六次叛乱，一个皇帝送了命，另一个丢了王位。 <br />我们一般将endian翻译成“字节序”，将big endian和little endian称作“大尾”和“小尾”。 1、字符编码、内码，顺带介绍汉字编码 <br />字符必须编码后才能被计算机处理。计算机使用的缺省编码方式就是计算机的内码。早期的计算机使用7位的ASCII编码，为了处理汉字，程序员设计了用于简体中文的GB2312和用于繁体中文的big5。 <br />GB2312(1980年)一共收录了7445个字符，包括6763个汉字和682个其它符号。汉字区的内码范围高字节从B0-F7，低字节从A1-FE，占用的码位是72*94=6768。其中有5个空位是D7FA-D7FE。 <br />GB2312支持的汉字太少。1995年的汉字扩展规范GBK1.0收录了21886个符号，它分为汉字区和图形符号区。汉字区包括21003个字符。 <br />从ASCII、GB2312到GBK，这些编码方法是向下兼容的，即同一个字符在这些方案中总是有相同的编码，后面的标准支持更多的字符。在这些编码中，英文和中文可以统一地处理。区分中文编码的方法是高字节的最高位不为0。按照程序员的称呼，GB2312、GBK都属于双字节字符集 (DBCS)。 <br />2000年的GB18030是取代GBK1.0的正式国家标准。该标准收录了27484个汉字，同时还收录了藏文、蒙文、维吾尔文等主要的少数民族文字。从汉字字汇上说，GB18030在GB13000.1的20902个汉字的基础上增加了CJK扩展A的6582个汉字（Unicode码0x3400-0x4db5），一共收录了27484个汉字。 <br />CJK就是中日韩的意思。Unicode为了节省码位，将中日韩三国语言中的文字统一编码。GB13000.1就是ISO/IEC 10646-1的中文版，相当于Unicode 1.1。 <br />GB18030的编码采用单字节、双字节和4字节方案。其中单字节、双字节和GBK是完全兼容的。4字节编码的码位就是收录了CJK扩展A的6582个汉字。 例如：UCS的0x3400在GB18030中的编码应该是8139EF30，UCS的0x3401在GB18030中的编码应该是8139EF31。 <br />微软提供了GB18030的升级包，但这个升级包只是提供了一套支持CJK扩展A的6582个汉字的新字体：新宋体-18030，并不改变内码。Windows 的内码仍然是GBK。 <br />这里还有一些细节： 
<ul><li><br />GB2312的原文还是区位码，从区位码到内码，需要在高字节和低字节上分别加上A0。 
</li><li><br />对于任何字符编码，编码单元的顺序是由编码方案指定的，与endian无关。例如GBK的编码单元是字节，用两个字节表示一个汉字。 这两个字节的顺序是固定的，不受CPU字节序的影响。UTF-16的编码单元是word（双字节），word之间的顺序是编码方案指定的，word内部的字节排列才会受到endian的影响。后面还会介绍UTF-16。 
</li><li><br />GB2312的两个字节的最高位都是1。但符合这个条件的码位只有128*128=16384个。所以GBK和GB18030的低字节最高位都可能不是1。不过这不影响DBCS字符流的解析：在读取DBCS字符流时，只要遇到高位为1的字节，就可以将下两个字节作为一个双字节编码，而不用管低字节的高位是什么。</li></ul>2、Unicode、UCS和UTF <br />前面提到从ASCII、GB2312、GBK到GB18030的编码方法是向下兼容的。而Unicode只与ASCII兼容（更准确地说，是与ISO-8859-1兼容），与GB码不兼容。例如“汉”字的Unicode编码是6C49，而GB码是BABA。 <br />Unicode也是一种字符编码方法，不过它是由国际组织设计，可以容纳全世界所有语言文字的编码方案。Unicode的学名是"Universal Multiple-Octet Coded Character Set"，简称为UCS。UCS可以看作是"Unicode Character Set"的缩写。 <br />根据维基百科全书(http://zh.wikipedia.org/wiki/)的记载：历史上存在两个试图独立设计Unicode的组织，即国际标准化组织（ISO）和一个软件制造商的协会（unicode.org）。ISO开发了ISO 10646项目，Unicode协会开发了Unicode项目。 <br />在1991年前后，双方都认识到世界不需要两个不兼容的字符集。于是它们开始合并双方的工作成果，并为创立一个单一编码表而协同工作。从Unicode2.0开始，Unicode项目采用了与ISO 10646-1相同的字库和字码。 <br />目前两个项目仍都存在，并独立地公布各自的标准。Unicode协会现在的最新版本是2005年的Unicode 4.1.0。ISO的最新标准是ISO 10646-3:2003。 <br />UCS只是规定如何编码，并没有规定如何传输、保存这个编码。例如“汉”字的UCS编码是6C49，我可以用4个ascii数字来传输、保存这个编码；也可以用utf-8编码:3个连续的字节E6 B1 89来表示它。关键在于通信双方都要认可。UTF-8、UTF-7、UTF-16都是被广泛接受的方案。UTF-8的一个特别的好处是它与ISO-8859-1完全兼容。UTF是“UCS Transformation Format”的缩写。 <br />IETF的RFC2781和RFC3629以RFC的一贯风格，清晰、明快又不失严谨地描述了UTF-16和UTF-8的编码方法。我总是记不得IETF是Internet Engineering Task Force的缩写。但IETF负责维护的RFC是Internet上一切规范的基础。 2.1、内码和code page <br />目前Windows的内核已经支持Unicode字符集，这样在内核上可以支持全世界所有的语言文字。但是由于现有的大量程序和文档都采用了某种特定语言的编码，例如GBK，Windows不可能不支持现有的编码，而全部改用Unicode。 <br />Windows使用代码页(code page)来适应各个国家和地区。code page可以被理解为前面提到的内码。GBK对应的code page是CP936。 <br />微软也为GB18030定义了code page：CP54936。但是由于GB18030有一部分4字节编码，而Windows的代码页只支持单字节和双字节编码，所以这个code page是无法真正使用的。 3、UCS-2、UCS-4、BMP <br />UCS有两种格式：UCS-2和UCS-4。顾名思义，UCS-2就是用两个字节编码，UCS-4就是用4个字节（实际上只用了31位，最高位必须为0）编码。下面让我们做一些简单的数学游戏： <br />UCS-2有2^16=65536个码位，UCS-4有2^31=2147483648个码位。 <br />UCS-4根据最高位为0的最高字节分成2^7=128个group。每个group再根据次高字节分为256个plane。每个plane根据第3个字节分为256行 (rows)，每行包含256个cells。当然同一行的cells只是最后一个字节不同，其余都相同。 <br />group 0的plane 0被称作Basic Multilingual Plane, 即BMP。或者说UCS-4中，高两个字节为0的码位被称作BMP。 <br />将UCS-4的BMP去掉前面的两个零字节就得到了UCS-2。在UCS-2的两个字节前加上两个零字节，就得到了UCS-4的BMP。而目前的UCS-4规范中还没有任何字符被分配在BMP之外。 4、UTF编码 <br />  <br />UTF-8就是以8位为单元对UCS进行编码。从UCS-2到UTF-8的编码方式如下： 
<table width="75%" border="1"><tbody><tr><td>UCS-2编码(16进制)</td><td>UTF-8 字节流(二进制)</td></tr><tr><td>0000 - 007F</td><td>0xxxxxxx</td></tr><tr><td>0080 - 07FF</td><td>110xxxxx 10xxxxxx</td></tr><tr><td>0800 - FFFF</td><td>1110xxxx 10xxxxxx 10xxxxxx</td></tr></tbody></table><br />例如“汉”字的Unicode编码是6C49。6C49在0800-FFFF之间，所以肯定要用3字节模板了：1110xxxx 10xxxxxx 10xxxxxx。将6C49写成二进制是：0110 110001 001001， 用这个比特流依次代替模板中的x，得到：11100110 10110001 10001001，即E6 B1 89。 <br />读者可以用记事本测试一下我们的编码是否正确。需要注意，UltraEdit在打开utf-8编码的文本文件时会自动转换为UTF-16，可能产生混淆。你可以在设置中关掉这个选项。更好的工具是Hex Workshop。 <br />UTF-16以16位为单元对UCS进行编码。对于小于0x10000的UCS码，UTF-16编码就等于UCS码对应的16位无符号整数。对于不小于0x10000的UCS码，定义了一个算法。不过由于实际使用的UCS2，或者UCS4的BMP必然小于0x10000，所以就目前而言，可以认为UTF-16和UCS-2基本相同。但UCS-2只是一个编码方案，UTF-16却要用于实际的传输，所以就不得不考虑字节序的问题。 5、UTF的字节序和BOM <br />UTF-8以字节为编码单元，没有字节序的问题。UTF-16以两个字节为编码单元，在解释一个UTF-16文本前，首先要弄清楚每个编码单元的字节序。例如“奎”的Unicode编码是594E，“乙”的Unicode编码是4E59。如果我们收到UTF-16字节流“594E”，那么这是“奎”还是“乙”？ <br />Unicode规范中推荐的标记字节顺序的方法是BOM。BOM不是“Bill Of Material”的BOM表，而是Byte Order Mark。BOM是一个有点小聪明的想法： <br />在UCS编码中有一个叫做"ZERO WIDTH NO-BREAK SPACE"的字符，它的编码是FEFF。而FFFE在UCS中是不存在的字符，所以不应该出现在实际传输中。UCS规范建议我们在传输字节流前，先传输字符"ZERO WIDTH NO-BREAK SPACE"。 <br />这样如果接收者收到FEFF，就表明这个字节流是Big-Endian的；如果收到FFFE，就表明这个字节流是Little-Endian的。因此字符"ZERO WIDTH NO-BREAK SPACE"又被称作BOM。 <br />UTF-8不需要BOM来表明字节顺序，但可以用BOM来表明编码方式。字符"ZERO WIDTH NO-BREAK SPACE"的UTF-8编码是EF BB BF（读者可以用我们前面介绍的编码方法验证一下）。所以如果接收者收到以EF BB BF开头的字节流，就知道这是UTF-8编码了。 <br />Windows就是使用BOM来标记文本文件的编码方式的。 6、进一步的参考资料 <br />本文主要参考的资料是 "Short overview of ISO-IEC 10646 and Unicode" (http://www.nada.kth.se/i18n/ucs/unicode-iso10646-oview.html)。 <br />我还找了两篇看上去不错的资料，不过因为我开始的疑问都找到了答案，所以就没有看： 
<ol><li>"Understanding Unicode A general introduction to the Unicode Standard" (http://scripts.sil.org/cms/scripts/page.php?site_id=nrsi&amp;item_id=IWS-Chapter04a) 
</li><li>"Character set encoding basics Understanding character set encodings and legacy encodings" (http://scripts.sil.org/cms/scripts/page.php?site_id=nrsi&amp;item_id=IWS-Chapter03) </li></ol><br />我写过UTF-8、UCS-2、GBK相互转换的软件包，包括使用Windows API和不使用Windows API的版本。以后有时间的话，我会整理一下放到我的个人主页上(http://fmddlmyy.home4u.china.com)。 <br />我是想清楚所有问题后才开始写这篇文章的，原以为一会儿就能写好。没想到考虑措辞和查证细节花费了很长时间，竟然从下午1:30写到9:00。希望有读者能从中受益。附录1 再说说区位码、GB2312、内码和代码页 <br />有的朋友对文章中这句话还有疑问：<br />“GB2312的原文还是区位码，从区位码到内码，需要在高字节和低字节上分别加上A0。” <br />我再详细解释一下： <br />“GB2312的原文”是指国家1980年的一个标准《中华人民共和国国家标准 信息交换用汉字编码字符集 基本集 GB 2312-80》。这个标准用两个数来编码汉字和中文符号。第一个数称为“区”，第二个数称为“位”。所以也称为区位码。1-9区是中文符号，16-55区是一级汉字，56-87区是二级汉字。现在Windows也还有区位输入法，例如输入1601得到“啊”。（这个区位输入法可以自动识别16进制的GB2312和10进制的区位码，也就是说输入B0A1同样会得到“啊”。） <br />内码是指操作系统内部的字符编码。早期操作系统的内码是与语言相关的。现在的Windows在系统内部支持Unicode，然后用代码页适应各种语言，“内码”的概念就比较模糊了。微软一般将缺省代码页指定的编码说成是内码。 <br />内码这个词汇，并没有什么官方的定义，代码页也只是微软这个公司的叫法。作为程序员，我们只要知道它们是什么东西，没有必要过多地考证这些名词。 <br />Windows中有缺省代码页的概念，即缺省用什么编码来解释字符。例如Windows的记事本打开了一个文本文件，里面的内容是字节流：BA、BA、D7、D6。Windows应该去怎么解释它呢？ <br />是按照Unicode编码解释、还是按照GBK解释、还是按照BIG5解释，还是按照ISO8859-1去解释？如果按GBK去解释，就会得到“汉字”两个字。按照其它编码解释，可能找不到对应的字符，也可能找到错误的字符。所谓“错误”是指与文本作者的本意不符，这时就产生了乱码。 <br />答案是Windows按照当前的缺省代码页去解释文本文件里的字节流。缺省代码页可以通过控制面板的区域选项设置。记事本的另存为中有一项ANSI，其实就是按照缺省代码页的编码方法保存。 <br />Windows的内码是Unicode，它在技术上可以同时支持多个代码页。只要文件能说明自己使用什么编码，用户又安装了对应的代码页，Windows就能正确显示，例如在HTML文件中就可以指定charset。 <br />有的HTML文件作者，特别是英文作者，认为世界上所有人都使用英文，在文件中不指定charset。如果他使用了0x80-0xff之间的字符，中文Windows又按照缺省的GBK去解释，就会出现乱码。这时只要在这个html文件中加上指定charset的语句，例如：<br />&lt;meta http-equiv="Content-Type" content="text/html; charset=ISO8859-1"&gt;<br />如果原作者使用的代码页和ISO8859-1兼容，就不会出现乱码了。 <br />再说区位码，啊的区位码是1601，写成16进制是0x10,0x01。这和计算机广泛使用的ASCII编码冲突。为了兼容00-7f的ASCII编码，我们在区位码的高、低字节上分别加上A0。这样“啊”的编码就成为B0A1。我们将加过两个A0的编码也称为GB2312编码，虽然GB2312的原文根本没提到这一点。 <br />===============================================================================================================<br /><b>文章三，本文转载自:http://www.donews.net/holen/archive/2004/11/30/188182.aspx<br /></b><br />Unicode: <br /><br />unicode.org制定的编码机制, 要将全世界常用文字都函括进去.<br />在1.0中是16位编码, 由U+0000到U+FFFF. 每个2byte码对应一个字符; 在2.0开始抛弃了16位限制, 原来的16位作为基本位平面, 另外增加了16个位平面, 相当于20位编码, 编码范围0到0x10FFFF.<br /><br />UCS: <br /><br />ISO制定的ISO10646标准所定义的 Universal Character Set, 采用4byte编码.<br /><br />Unicode与UCS的关系:<br /><br />ISO与unicode.org是两个不同的组织, 因此最初制定了不同的标准; 但自从unicode2.0开始, unicode采用了与ISO 10646-1相同的字库和字码, ISO也承诺ISO10646将不会给超出0x10FFFF的UCS-4编码赋值, 使得两者保持一致.<br /><br />UCS的编码方式:<br /><br /><li>UCS-2, 与unicode的2byte编码基本一样. <br /></li><li>UCS-4, 4byte编码, 目前是在UCS-2前加上2个全零的byte.<br /><br />UTF: Unicode/UCS Transformation Format<br />----------------------------------------------------------原文------------------------------------------------------------------------------------ 
</li><li>UTF-8, 8bit编码, ASCII不作变换, 其他字符做变长编码, 每个字符1-3 byte. 通常作为外码. 有以下优点:<br />* 与CPU字节顺序无关, 可以在不同平台之间交流<br />* 容错能力高, 任何一个字节损坏后, 最多只会导致一个编码码位损失, 不会链锁错误(如GB码错一个字节就会整行乱码) <br /></li><li>UTF-16, 16bit编码, 是变长码, 大致相当于20位编码, 值在0到0x10FFFF之间, 基本上就是unicode编码的实现. 它是变长码, 与CPU字序有关, 但因为最省空间, 常作为网络传输的外码. <br />----------------------------------------------------------原文------------------------------------------------------------------------------------<br />----------------------------------------------------------纠正后------------------------------------------------------------------------------------ 
</li><li>UTF-8, 8bit编码, ASCII不作变换, 其他字符做变长编码, 每个字符1-3 byte. 通常作为外码. 有以下优点:<br />* 与CPU字节顺序无关, 可以在不同平台之间交流<br />* 容错能力高, 任何一个字节损坏后, 最多只会导致一个编码码位损失, 不会链锁错误(如GB码错一个字节就会整行乱码) <br /></li><li>UTF-16, 16bit编码, 是定长码,  基本上就是unicode编码的实现. 与CPU字序有关 <br />----------------------------------------------------------纠正后----------------------------------------------------------------------------------- 
</li><li>UTF-16是unicode的preferred encoding. <br /></li><li>UTF-32, 仅使用了unicode范围(0到0x10FFFF)的32位编码, 相当于UCS-4的子集.<br /><br />UTF与unicode的关系:<br /><br />Unicode是一个字符集, 可以看作为内码.<br />而UTF是一种编码方式, 它的出现是因为unicode不适宜在某些场合直接传输和处理. UTF-16直接就是unicode编码, 没有变换, 但它包含了0x00在编码内, 头256字节码的第一个byte都是0x00, 在操作系统(C语言)中有特殊意义, 会引起问题. 采用UTF-8编码对unicode的直接编码作些变换可以避免这问题, 并带来一些优点.<br /><br />中国国标编码:<br /></li><li>GB 13000: 完全等同于ISO 10646-1/Unicode 2.1, 今后也将随ISO 10646/Unicode的标准更改而同步更改.<br /></li><li>GBK: 对GB2312的扩充, 以容纳GB2312字符集范围以外的Unicode 2.1的统一汉字部分, 并且增加了部分unicode中没有的字符. <br /></li><li>GB 18030-2000: 基于GB 13000, 作为Unicode 3.0的GBK扩展版本, 覆盖了所有unicode编码, 地位等同于UTF-8, UTF-16, 是一种unicode编码形式. 变长编码, 用单字节/双字节/4字节对字符编码. GB18030向下兼容GB2312/GBK. <br />GB 18030是中国所有非手持/嵌入式计算机系统的强制实施标准. <br /><br />-------------------------------<br /><br /><br />  什么是 UCS 和 ISO 10646? <br />国际标准 ISO 10646 定义了 通用字符集 (Universal Character Set, UCS). UCS 是所有其他字符集标准的一个超集. 它保证与其他字符集是双向兼容的. 就是说, 如果你将任何文本字符串翻译到 UCS格式, 然后再翻译回原编码, 你不会丢失任何信息. <br />UCS 包含了用于表达所有已知语言的字符. 不仅包括拉丁语,希腊语, 斯拉夫语,希伯来语,阿拉伯语,亚美尼亚语和乔治亚语的描述, 还包括中文, 日文和韩文这样的象形文字, 以及 平假名, 片假名, 孟加拉语, 旁遮普语果鲁穆奇字符(Gurmukhi), 泰米尔语, 印.埃纳德语(Kannada), Malayalam, 泰国语, 老挝语, 汉语拼音(Bopomofo), Hangul, Devangari, Gujarati, Oriya, Telugu 以及其他数也数不清的语. 对于还没有加入的语言, 由于正在研究怎样在计算机中最好地编码它们, 因而最终它们都将被加入. 这些语言包括 Tibetian, 高棉语, Runic(古代北欧文字), 埃塞俄比亚语, 其他象形文字, 以及各种各样的印-欧语系的语言, 还包括挑选出来的艺术语言比如 Tengwar, Cirth 和 克林贡语(Klingon). UCS 还包括大量的图形的, 印刷用的, 数学用的和科学用的符号, 包括所有由 TeX, Postscript, MS-DOS，MS-Windows, Macintosh, OCR 字体, 以及许多其他字处理和出版系统提供的字符. <br />ISO 10646 定义了一个 31 位的字符集. 然而, 在这巨大的编码空间中, 迄今为止只分配了前 65534 个码位 (0x0000 到 0xFFFD). 这个 UCS 的 16位子集称为 基本多语言面 (Basic Multilingual Plane, BMP). 将被编码在 16 位 BMP 以外的字符都属于非常特殊的字符(比如象形文字), 且只有专家在历史和科学领域里才会用到它们. 按当前的计划, 将来也许再也不会有字符被分配到从 0x000000 到 0x10FFFF 这个覆盖了超过 100 万个潜在的未来字符的 21 位的编码空间以外去了. ISO 10646-1 标准第一次发表于 1993 年, 定义了字符集与 BMP 中内容的架构. 定义 BMP 以外的字符编码的第二部分 ISO 10646-2 正在准备中, 但也许要过好几年才能完成. 新的字符仍源源不断地加入到 BMP 中, 但已经存在的字符是稳定的且不会再改变了. <br />UCS 不仅给每个字符分配一个代码, 而且赋予了一个正式的名字. 表示一个 UCS 或 Unicode 值的十六进制数, 通常在前面加上 "U+", 就象 U+0041 代表字符"拉丁大写字母A". UCS 字符 U+0000 到 U+007F 与 US-ASCII(ISO 646) 是一致的, U+0000 到 U+00FF 与 ISO 8859-1(Latin-1) 也是一致的. 从 U+E000 到 U+F8FF, 已经 BMP 以外的大范围的编码是为私用保留的. 什么是组合字符? <br />UCS里有些编码点分配给了 组合字符.它们类似于打字机上的无间隔重音键. 单个的组合字符不是一个完整的字符. 它是一个类似于重音符或其他指示标记, 加在前一个字符后面. 因而, 重音符可以加在任何字符后面. 那些最重要的被加重的字符, 就象普通语言的正字法(orthographies of common languages)里用到的那种, 在 UCS 里都有自己的位置, 以确保同老的字符集的向后兼容性. 既有自己的编码位置, 又可以表示为一个普通字符跟随一个组合字符的被加重字符, 被称为 预作字符(precomposed characters). UCS 里的预作字符是为了同没有预作字符的旧编码, 比如 ISO 8859, 保持向后兼容性而设的. 组合字符机制允许在任何字符后加上重音符或其他指示标记, 这在科学符号中特别有用, 比如数学方程式和国际音标字母, 可能会需要在一个基本字符后组合上一个或多个指示标记. <br />组合字符跟随着被修饰的字符. 比如, 德语中的元音变音字符 ("拉丁大写字母A 加上分音符"), 既可以表示为 UCS 码 U+00C4 的预作字符, 也可以表示成一个普通 "拉丁大写字母A" 跟着一个"组合分音符":U+0041 U+0308 这样的组合. 当需要堆叠多个重音符, 或在一个基本字符的上面和下面都要加上组合标记时, 可以使用多个组合字符. 比如在泰国文中, 一个基本字符最多可加上两个组合字符. 什么是 UCS 实现级别? <br />不是所有的系统都需要支持象组合字符这样的 UCS 里所有的先进机制. 因此 ISO 10646 指定了下列三种实现级别: 
<dl><dt>级别1 
</dt><dd>不支持组合字符和 Hangul Jamo 字符 (一种特别的, 更加复杂的韩国文的编码, 使用两个或三个子字符来编码一个韩文音节) 
</dd><dt>级别2 
</dt><dd>类似于级别1, 但在某些文字中, 允许一列固定的组合字符 (例如, 希伯来文, 阿拉伯文, Devangari, 孟加拉语, 果鲁穆奇语, Gujarati, Oriya, 泰米尔语, Telugo, 印.埃纳德语, Malayalam, 泰国语和老挝语). 如果没有这最起码的几个组合字符, UCS 就不能完整地表达这些语言. 
</dd><dt>级别3 
</dt><dd>支持所有的 UCS 字符, 例如数学家可以在任意一个字符上加上一个 tilde(颚化符号,西班牙语字母上面的～)或一个箭头(或两者都加). </dd></dl>什么是 Unicode? <br />历史上, 有两个独立的, 创立单一字符集的尝试. 一个是国际标准化组织(ISO)的 ISO 10646 项目, 另一个是由(一开始大多是美国的)多语言软件制造商组成的协会组织的 Unicode 项目. 幸运的是, 1991年前后, 两个项目的参与者都认识到, 世界不需要两个不同的单一字符集. 它们合并双方的工作成果, 并为创立一个单一编码表而协同工作. 两个项目仍都存在并独立地公布各自的标准, 但 Unicode 协会和 ISO/IEC JTC1/SC2 都同意保持 Unicode 和 ISO 10646 标准的码表兼容, 并紧密地共同调整任何未来的扩展. 那么 Unicode 和 ISO 10646 不同在什么地方? <br />Unicode 协会公布的 Unicode 标准 严密地包含了 ISO 10646-1 实现级别3的基本多语言面. 在两个标准里所有的字符都在相同的位置并且有相同的名字. <br />Unicode 标准额外定义了许多与字符有关的语义符号学, 一般而言是对于实现高质量的印刷出版系统的更好的参考. Unicode 详细说明了绘制某些语言(比如阿拉伯语)表达形式的算法, 处理双向文字(比如拉丁与希伯来文混合文字)的算法和 排序与字符串比较 所需的算法, 以及其他许多东西. <br />另一方面, ISO 10646 标准, 就象广为人知的 ISO 8859 标准一样, 只不过是一个简单的字符集表. 它指定了一些与标准有关的术语, 定义了一些编码的别名, 并包括了规范说明, 指定了怎样使用 UCS 连接其他 ISO 标准的实现, 比如 ISO 6429 和 ISO 2022. 还有一些与 ISO 紧密相关的, 比如 ISO 14651 是关于 UCS 字符串排序的. <br />考虑到 Unicode 标准有一个易记的名字, 且在任何好的书店里的 Addison-Wesley 里有, 只花费 ISO 版本的一小部分, 且包括更多的辅助信息, 因而它成为使用广泛得多的参考也就不足为奇了. 然而, 一般认为, 用于打印 ISO 10646-1 标准的字体在某些方面的质量要高于用于打印 Unicode 2.0的. 专业字体设计者总是被建议说要两个标准都实现, 但一些提供的样例字形有显著的区别. ISO 10646-1 标准同样使用四种不同的风格变体来显示表意文字如中文, 日文和韩文 (CJK), 而 Unicode 2.0 的表里只有中文的变体. 这导致了普遍的认为 Unicode 对日本用户来说是不可接收的传说, 尽管是错误的. 什么是 UTF-8? <br />首先 UCS 和 Unicode 只是分配整数给字符的编码表. 现在存在好几种将一串字符表示为一串字节的方法. 最显而易见的两种方法是将 Unicode 文本存储为 2 个 或 4 个字节序列的串. 这两种方法的正式名称分别为 UCS-2 和 UCS-4. 除非另外指定, 否则大多数的字节都是这样的(Bigendian convention). 将一个 ASCII 或 Latin-1 的文件转换成 UCS-2 只需简单地在每个 ASCII 字节前插入 0x00. 如果要转换成 UCS-4, 则必须在每个 ASCII 字节前插入三个 0x00. <br />在 Unix 下使用 UCS-2 (或 UCS-4) 会导致非常严重的问题. 用这些编码的字符串会包含一些特殊的字符, 比如 '\0' 或 '/', 它们在 文件名和其他 C 库函数参数里都有特别的含义. 另外, 大多数使用 ASCII 文件的 UNIX 下的工具, 如果不进行重大修改是无法读取 16 位的字符的. 基于这些原因, 在文件名, 文本文件, 环境变量等地方, UCS-2 不适合作为 Unicode 的外部编码. <br />在 ISO 10646-1 Annex R 和 RFC 2279 里定义的 UTF-8 编码没有这些问题. 它是在 Unix 风格的操作系统下使用 Unicode 的明显的方法. <br />UTF-8 有一下特性: 
<ul><li>UCS 字符 U+0000 到 U+007F (ASCII) 被编码为字节 0x00 到 0x7F (ASCII 兼容). 这意味着只包含 7 位 ASCII 字符的文件在 ASCII 和 UTF-8 两种编码方式下是一样的. 
</li><li>所有 &gt;U+007F 的 UCS 字符被编码为一个多个字节的串, 每个字节都有标记位集. 因此, ASCII 字节 (0x00-0x7F) 不可能作为任何其他字符的一部分. 
</li><li>表示非 ASCII 字符的多字节串的第一个字节总是在 0xC0 到 0xFD 的范围里, 并指出这个字符包含多少个字节. 多字节串的其余字节都在 0x80 到 0xBF 范围里. 这使得重新同步非常容易, 并使编码无国界, 且很少受丢失字节的影响. 
</li><li>可以编入所有可能的 2<sup>31</sup>个 UCS 代码 
</li><li>UTF-8 编码字符理论上可以最多到 6 个字节长, 然而 16 位 BMP 字符最多只用到 3 字节长. 
</li><li>Bigendian UCS-4 字节串的排列顺序是预定的. 
</li><li>字节 0xFE 和 0xFF 在 UTF-8 编码中从未用到. </li></ul><br />下列字节串用来表示一个字符. 用到哪个串取决于该字符在 Unicode 中的序号. 
<div align="center"><center><table border="1"><tbody><tr><td>U-00000000 - U-0000007F: </td><td>0xxxxxxx</td></tr><tr><td>U-00000080 - U-000007FF: </td><td>110xxxxx 10xxxxxx</td></tr><tr><td>U-00000800 - U-0000FFFF: </td><td>1110xxxx 10xxxxxx 10xxxxxx</td></tr><tr><td>U-00010000 - U-001FFFFF: </td><td>11110xxx 10xxxxxx 10xxxxxx 10xxxxxx</td></tr><tr><td>U-00200000 - U-03FFFFFF: </td><td>111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx</td></tr><tr><td>U-04000000 - U-7FFFFFFF: </td><td>1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx</td></tr></tbody></table></center></div><br />xxx 的位置由字符编码数的二进制表示的位填入. 越靠右的 x 具有越少的特殊意义. 只用最短的那个足够表达一个字符编码数的多字节串. 注意在多字节串中, 第一个字节的开头"1"的数目就是整个串中字节的数目. <br /><b>例如</b>: Unicode 字符 U+00A9 = 1010 1001 (版权符号) 在 UTF-8 里的编码为: 
<blockquote><br />11000010 10101001 = 0xC2 0xA9<br />而字符 U+2260 = 0010 0010 0110 0000 (不等于) 编码为: 
<blockquote><br />11100010 10001001 10100000 = 0xE2 0x89 0xA0<br />这种编码的官方名字拼写为 UTF-8, 其中 UTF 代表 <b>U</b>CS <b>T</b>ransformation <b>F</b>ormat. 请勿在任何文档中用其他名字 (比如 utf8 或 UTF_8) 来表示 UTF-8, 当然除非你指的是一个变量名而不是这种编码本身. 什么编程语言支持 Unicode? <br />在大约 1993 年之后开发的大多数现代编程语言都有一个特别的数据类型, 叫做 Unicode/ISO 10646-1 字符. 在 Ada95 中叫 Wide_Character, 在 Java 中叫 char. <br />ISO C 也详细说明了处理多字节编码和宽字符 (wide characters) 的机制, 1994 年 9 月 Amendment 1 to ISO C 发表时又加入了更多. 这些机制主要是为各类东亚编码而设计的, 它们比处理 UCS 所需的要健壮得多. UTF-8 是 ISO C 标准调用多字节字符串的编码的一个例子, wchar_t 类型可以用来存放 Unicode 字符.</blockquote></blockquote></li><img src ="http://www.cnitblog.com/textbox/aggbug/72910.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/textbox/" target="_blank">零度</a> 2011-03-03 09:06 <a href="http://www.cnitblog.com/textbox/archive/2011/03/03/72910.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>用户模式的调试原理</title><link>http://www.cnitblog.com/textbox/archive/2010/11/03/70852.html</link><dc:creator>零度</dc:creator><author>零度</author><pubDate>Wed, 03 Nov 2010 14:07:00 GMT</pubDate><guid>http://www.cnitblog.com/textbox/archive/2010/11/03/70852.html</guid><wfw:comment>http://www.cnitblog.com/textbox/comments/70852.html</wfw:comment><comments>http://www.cnitblog.com/textbox/archive/2010/11/03/70852.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/textbox/comments/commentRss/70852.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/textbox/services/trackbacks/70852.html</trackback:ping><description><![CDATA[用户模式的调试原理和过程.<br />主要对象: <br />    1.调试进程 (用户界面的输入\输出与被调试进程的桥梁)<br />    2.被调试进程<br /><br />调试器一般会用两个线程(也有用单线程的)来完成调试与用户界面的交互.UI线程与调试线程(DWT Debuger's Work Thread)<br />这样的原因是界面不会因为调试的等待而停止输入输出.<br /><br />  DWT的主要内容是<br />    1.建立会话.调用CreateProcess或DebugActiveProcess <br />    2.循环调用WaitForDebugEvent,ContinueDebugEvent 来接收被调试进程的调试的event<br />  类似window的消息循环.<br /> <br />  DWT的TEP与普通TEP的不同地方在于DbgSsReserved 数组主要用于保存(DebugObject)在xp中数组的每一个元素都是指向DBGSS_THREAD_DATA结构 该结构主要用于保存被调试的进程/句柄调用WaitForDebugEvent,ContinueDebugEvent,dbgUIGetThreadDebugObject,dbgUISetThreadDebugObject 会维护这个数组<br /><br />  被调试进程与普通进程的差别.<br />  EPB的DebugPort  不为空<br />  PEB的BeginDebugged 不为0<br /><br /><br /><br /><br />  CreateProcess<br />  CreateProcessInternalW<br />  ZwCeateProcessEx<br />   -DbgConnectToDbg<br />    -NtConnectPort<br />     设置DbgSsReserved[0]/DbgSsReserved[1] 调试端口句柄/Semaphore信号对象 很多API调试通讯都是通过该调试端口来传递.<br />   -NtCreateProcess<br />    -PspCreateProcess<br />     设置EPROCESS和DebugPort=1<br />  把普通的进程晋升为调试子系统"眼里"的被调试进程.<br /><br />   <br /><img src ="http://www.cnitblog.com/textbox/aggbug/70852.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/textbox/" target="_blank">零度</a> 2010-11-03 22:07 <a href="http://www.cnitblog.com/textbox/archive/2010/11/03/70852.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>About GDT LDT ID (转)</title><link>http://www.cnitblog.com/textbox/archive/2010/10/29/70691.html</link><dc:creator>零度</dc:creator><author>零度</author><pubDate>Fri, 29 Oct 2010 03:38:00 GMT</pubDate><guid>http://www.cnitblog.com/textbox/archive/2010/10/29/70691.html</guid><wfw:comment>http://www.cnitblog.com/textbox/comments/70691.html</wfw:comment><comments>http://www.cnitblog.com/textbox/archive/2010/10/29/70691.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/textbox/comments/commentRss/70691.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/textbox/services/trackbacks/70691.html</trackback:ping><description><![CDATA[
		<p>转自:<a href="http://blog.csdn.net/lihenair/archive/2010/01/10/5168396.aspx">http://blog.csdn.net/lihenair/archive/2010/01/10/5168396.aspx</a></p>
		<p>Intel   Architecture   Software   Developer’s   Manual Volum 3A: SystemProgramming Guide </p>
		<p>段描述符的作用是将代码，数据，堆栈和任务状态段的虚拟地址转换成线性地址，并指明段的类型。段描述符只在局部和全局描述符表中出现。</p>
		<p>选择符16位长，放在段寄存器中，指针的之一部分是用来在全局或局部描述符表中选择一个描述符，以便确定一个虚拟地址空间中的一个特定的存储器段，故叫选择符。</p>
		<p>LDT用于描述相应程序的代码段、数据段和堆栈段。GDT描述系统段，包括操作系统代码和数据。</p>
		<p>GDT LDT GDTR LDTR</p>
		<p>Global and Local Descriptor Tables</p>
		<p>当工作在保护模式时，所有存储器访问都经过全局描述表(GDT)或者一个可选的局部描述表(LDT)。这些表包含的条目称为段描述符。段描述符提供段基址及段访问权限，段类型和使用信息。</p>
		<p>每个段描述符都有一个对应的段选择符。一个段选择符提供了它在GDT或LDT中的索引(对应的段描述符的偏移量)，一个全局/局部flag(决定选择符指向GDT或LDT)和访问权限信息。</p>
		<p>访问段中的一个字节(byte)必须提供一个段选择符和一个偏移量(offset)。段选择符提供访问段描述符的方法(在GDT或LDT中)。从段
描述符，处理器得到线性空间中的段基址。偏移量提供了相对于基址的以字节(byte)为单位的位置。这种机制可用于访问任何有效的代码去，数据区或者堆栈
段，并提供了在处理器工作时根据当前优先级(CPL)可访问的段。CPL被定义为当前执行代码段的保护级别。</p>
		<p>GDT的线性地址的基址位于GDT寄存器(GDTR)中；LDT的线性地址的基址位于LDT寄存器(LDTR)中；</p>
		<p>Global and Local Descriptor Tables in IA-32e Mode</p>
		<p>System Segments, Segment Descriptors, and Gates</p>
		<p>除了构成程序或过程执行环境代码段，数据段和堆栈段，架构还定义了两个系统段: 任务状态段(TSS)和LDT。GDT不被认为是一个段是因为它不可通过段选择符和段描述符访问。TSSs和LDTs有段描述符定义它们。</p>
		<p>架构还定义了一组特殊的描述符，称为门(call gates, interrupt gates, trap gates and task 
gates).这些门提供了保护系统程序和handler的方法。系统程序和handler可能工作在与应用程序和很多程序不同的优先级上。例如，调用门
的请求可以提供访问一个在代码段的程序的方法，而这个代码段可能与当权代码段同级或数字上低优先级。为了由调用门访问程序，调用过程提供调用门的选择符。
处理器接着执行调用门的访问权检查，比较调用门的优先级CPL和调用门指向的目的代码段。</p>
		<p>如果允许访问的目的代码段，则处理器会得到目的代码段的段选择符和代码段在调用门中的偏移量。如果请求需要改变优先级，处理器还会切换到目标优先级的堆栈。新栈的段选择符从当前执行任务的TSS获得。门可以方便的在16位和32为代码段转换，反之亦然。</p>
		<p>Task-State Segments and Task Gates</p>
		<p>TSS定义了任务的执行环境状态。包括通用目的寄存器，段寄存器，EFLAG寄存器，EIP寄存器和特权级为0、1和2的堆栈段选择符和指针。TSS还包括代表LDT对应任务的段选择符和和页结构层次的基址。</p>
		<p>所有在保护模式执行的程序都运行在任务(成为当前任务)的上下文境中。代表当前任务TSS的段选择符存储在任务寄存器中。最简单的任务切换方法使用
call或jump到新任务。这一点上，新任务的TSS的段选择符由CALL或JMP指令给出。切换任务时，处理器执行如下操作：</p>
		<p>1. 储存保持在当前TSS中当前任务的状态</p>
		<p>2. 装载新任务的段选择符到任务寄存器</p>
		<p>3. 通过GDT中的任务描述符访问新TSS</p>
		<p>4. 从新TSS装载新任务状态到通用目的寄存器，段寄存器，LDTR控制寄存器CR3(页结构层次的基址)，EFLAG寄存器和EIP寄存器。</p>
		<p>5. 开始执行新任务</p>
		<p>任务也可以由任务门访问。任务门与调用门类似，除了它提供的是访问TSS的方法而不是代码段。</p>
		<p>Interrupt and Exception Handling</p>
		<p>外部中断，软中断和异常由中断描述符表(IDT)处理。IDT存储门描述符的集合，这些描述符提供访问中断和异常处理程序的方法。如同GDT，IDT也不是一个段。代表IDT基址的线性地址包含着IDT寄存器(IDTR)中。</p>
		<p>IDT中的门描述符可以是中断，陷阱或者任务门描述符。为了访问中断或异常描述符，处理器首先从内部硬件，外部中断控制器或
INT，INTO，INT 3， 
BOUND中接受一个中断向量(中断号)。中断向量提供了IDT中的索引。如果选择的门描述符是一个中断门或陷阱门，对应的处理函数由类似请求调用门的操
作访问。如果描述符是任务门，处理函数由任务切换访问。</p>
		<p>Memory-Management Registers</p>
		<p>
				<br />
		</p>
		<p>处理器提供4个存储器管理寄存器(GDTR，LDTR，IDTR,TR)。</p>
		<p>Global Descriptor Table Register(GDTR)</p>
		<p>GDTR寄存器保存GDT的实模式32位基址和16位限长。基址指明了GDT 0字节的线性地址；表限长指明了表中的字节数。</p>
		<p>上电或重启处理器后，基址置为默认值0，限长置为0FFFFH。新基址在处理器初始化保护模式操作时装入GDTR。</p>
		<p>Local Descriptor Table Register(LDTR)</p>
		<p>LDTR寄存器保存LDT的16位段选择符，基址(保护模式32位)，段限长和描述符属性。基址指明了GDT 0字节的线性地址；表限长指明了表中的字节数。包含LDT的段必须在GDT中有一个段描述符。</p>
		<p>当任务切换时，LDTR自动装入新任务LDT的段选择符和描述符。</p>
		<p>上电或重启处理器后，基址置为默认值0，限长置为0FFFFH。新基址在处理器初始化保护模式操作时装入GDTR。</p>
		<p>Memory Management Overview</p>
		<p>存储器管理功能分为两个部分：分段和分页。分段提供了隔离单独代码，数据和堆栈模块的机制，因此多个程序(或任务)可以在同一个处理器山执行而不被
其他处理器打扰。分页提供了实现常规页请求，虚拟存储器系统(程序执行环境部分可以按需映射到物理地址中)的机制，分页还可以用来分割多任务。</p>
		<p>
				<br />每个系统必须定义一个GDT，可被系统中所有程序和任务使用。可选地，一个或多个LDT可定义。例如，一个LDT可以为每个单独的任务定义，或一些或所以任务共享相同的LDT。</p>
GDT自己不是一个段；相反，它是一个在线性地址空间的数据结构。GDT的线性基址和限长必须装入GDTR寄存器中。GDT的基址必须以8字节对齐以换取最好的处理器性能。GDT的限长以字节代表。如同其他段一样<img src ="http://www.cnitblog.com/textbox/aggbug/70691.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/textbox/" target="_blank">零度</a> 2010-10-29 11:38 <a href="http://www.cnitblog.com/textbox/archive/2010/10/29/70691.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>TLS</title><link>http://www.cnitblog.com/textbox/archive/2010/09/27/69238.html</link><dc:creator>零度</dc:creator><author>零度</author><pubDate>Mon, 27 Sep 2010 04:41:00 GMT</pubDate><guid>http://www.cnitblog.com/textbox/archive/2010/09/27/69238.html</guid><wfw:comment>http://www.cnitblog.com/textbox/comments/69238.html</wfw:comment><comments>http://www.cnitblog.com/textbox/archive/2010/09/27/69238.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/textbox/comments/commentRss/69238.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/textbox/services/trackbacks/69238.html</trackback:ping><description><![CDATA[
		<h1 class="title_txt">
				<img src="http://blog.csdn.net/images/turnship.gif" alt="转载" width="15" border="0" height="15" /> 
					[转]TLS: 线程局部存储TLS <cite class="fav_csdnstylebykimi"><a class="fav_csdnstylebykimi" title="收藏到我的网摘中，并分享给我的朋友"></a></cite></h1>
		<p>线程局部存储TLS</p>
		<p>堆栈中定义的局部变量，对多线程是安全的，因为不同的线程有自己的堆栈。而通常定义的全局变量，所有线程都可以作读写访问，这样它就不是线程安全
的，为安全就有必要加锁互斥访问。而何为线程局部存储（TLS），简单的说，就是一个变量（通常是指针，指向具体的类型），每个线程都有一个副本，而在程
序中可以按照相同的方式来访问，（比如使用相同的变量名，又或者都调用TlsGetValue），既然是都有副本，自然线程中互不影响。打个比方，就如同
一个人，被克隆出三个，其中一个被砍了一刀，其它两人都不会受伤。</p>
		<p>VC编译器可以隐式的定义线程局部变量，只要定义的时候加上__declspec (thread)前缀。比如</p>
		<p>__declspec (thread) int iGlobal_1 = 1;<br />__declspec (thread) double iGlobal_2 = 2.0;<br />iGlobal_1，iGlobal_2就都有自己的副本。</p>
		<p>
				<br />另外windows也提供了几个api, 来显式定义线程局部变量。这几个api为TlsAlloc, TlsFree, TlsSetValue, TlsGetValue。用法自己查查。</p>
		<p>
				<br />好，现在可以入正题。来说说它的实现。</p>
		<p>
				<span style="color: rgb(0, 0, 255);">应该都知道，操作系统会使用一个结构来描述线程，这结构通常称为
TEB((Thread Environment Block) , 
每个线程有一个对应的TEB，切换线程的时候，也会切换到不同的TEB。有某个指针值指向当前的TEB, 
切换线程的时候就改变这个指针值，这样访问线程相关的数值，就可以统一从这个指针值找起。windows中，这个线程指针值放在fs寄存器。</span>
		</p>
		<p>
				<br />
				<span style="color: rgb(0, 0, 255);">TEB 
里面有些什么变量呢？当然是跟线程有关的变量啦。更具体的自己去查资料。其中有个变量是线程TLS数组的指针。称为_tls_array，利用这个数组就
可以管理线程相关的数据了。_tls_array_指针在windows中处于TEB偏移0x2h的地方。结合上面说的，看到mov ecx, 
dowrd ptr fs:[2ch]，就应该知道是取当前线程的_tls_array的指针，放在ecx寄存器中。</span>
		</p>
		<p>
				<br />现在，我们在不同的线程中已经可以取得各自的_tls_array，这时候，要访问数组的元素，还差索引。这时，再看看TlsAlloc,
 你应该很清楚它的意思？无错，它就是说，请为我分配一个索引号，表示相应的数组项已被使用。TlsFree, 
就是释放索引号，表示相应的数组项可以被再次使用。TlsSetValue，TlsGetValue就是拿个索引，向相应的数组项设值或者取值。</p>
		<p>
				<br />好好想想，为什么我有个相同索引号，在不同的线程中调用TlsGetValue，取出来的值会不同呢？因为数组的起始指针已经变了。在计算
机中反反复复都会出现 
基址+偏移的模式。基址不变，偏移变，取的值不同；基址变，偏移不变，取的值也不同。这看起来很简单，但很可能没有意识到这点。比如为什么C++中，不同
的对象，都有变量m_a, 
它可以有不同值呢，因为不同的对象基址也不同(也就是this指针),而为什么它们可以用相同的代码来访问变量m_a,因为变量m_a的相对偏移是不变
的。</p>
		<p>
				<br />
				<span style="color: rgb(0, 0, 255);">回到TLS, 
索引号对应的是偏移，因为线程切换引起了_tls_array数组的切换, 
因此取值可以不同。这样用TlsAlloc分配了一个索引号，所有线程中_tls_array的对应元素其实都已经是归你所有，并非只是当前线程。再次强
调，分配出一个索引，所有线程的_tls_array数组中的索引对应项都已经被分配，有5个线程，你可以管理的已经有5个格子，并非只是当前线程的一个
格子。又因为索引是一样的，就可以用相同的方式来使用这些数组的小格子。现在你已经有个小格子了，可以往里面放东西了，放什么东西你可以自己确定，你可以
放指针，或者放整数，或者放字符。因为是自己放的，自己可以知道意思，取出来对你就是有用的。这里，又引起另一个很简单但又很容易忽略的问题，内存中放的
究竟是什么？数字？可以说是，但更准确的是放状态，只不过这状态可以用数字来编码（任何东西都可以用数字来编码，只要你懂得解码的方式，这串数字对你就是
有意义的）。 2bit, 可以表示4个状态，4bit可以表示16个状态，32bit可以表示4G个状态。</span>
		</p>
		<p>
				<br />
				<span style="color: rgb(255, 0, 255);">上面其实已经说完了显式TLS分配，也就是调用TlsAlloc等方式。那隐式的TLS分配，又是怎么实现的呢?</span>
		</p>
		<p>第一次调用TlsAlloc, 检查返回值，会发现返回1，为什么是1，而不是0呢? 因为0已经被使用了，谁在使用? 编译器。<br />定义<br /><span style="color: rgb(0, 0, 255);">__declspec (thread) int iGlobal_1 = 1;<br />__declspec (thread) double iGlobal_2 = 2.0;<br />时
候，生成了一个段.tls, 
这个段中有这两个数据，保持下来放在执行文件中。当程序运行，每个线程会将.tls复制一份。线程_tls_array的0索引号被占据，对应的格子就放
着指向这份数据的指针(即指向已分配的数据)。比如上面的语句，你可以想象成隐式定义了一个结构<br />struct TLS_Data<br />{<br />    int iGlobal_1;<br />    double iGlobal_2;<br />};</span><br />每
个线程运行时，new出这个结构，在用TlsSetValue就指针设置到线程各自的_tls_array，0索引对应的位置。因为不同变量的偏移值在结
构中是不同的，这样基址变，偏移不变，取得线程各自的TLS_Data结构，再跟着基址不变，偏移变，就可以访问不同的变量。</p>
		<p>分析一下<br />__declspec (thread) int iGlobal = 1;</p>
		<p>int main()<br />{<br />    int i = iGlobal;<br />    return 0;<br />}<br />的汇编代码<br />mov         eax,[__tls_index]            // 将索引放在eax中，通常为0<br />mov         ecx,dword ptr fs:[2Ch]        // 将线程对应的_tls_array指针放在ecx中<br />mov         edx,dword ptr [ecx+eax*4]    <br />// 每个格有4 byte, 取出_tls_array数组元素，放在edx中，这数组元素放着的是我们假象的TLS_Data结构指针<br />mov         eax,dword ptr [edx+104h]    // 指针加上变量在结构中的偏移，取得iGlobal变量值<br />mov         dword ptr [ebp-4],eax        // 将iGlobal变量值放在栈变量，也就是i中</p>
		<p>注意，iGlobal的偏移并不是0, 因为已经有些变量定义了，比如线程各自的errno变量，strtok函数用的变量等等。</p>
		<p>
				<br />
				<span style="color: rgb(0, 0, 255);">可以这样说，编译器拿出_tls_array的一个格子，自
己管理，又再实现出另一种风格的TLS。我们也可以自己用TlsAlloc取得一个索引，跟着 new 
出另一个子数组，子数组指针放在_tls_array元素中。真正的数据指针放在子数组中。这样，我们就可以根据自己的需要来实现自己的线程局部存储。而
又不占用多个_tls_array数组的索引。</span>
		</p>
		<p>再来讨论一下_tls_array数组的索引的分配跟释放。一定要有某种方式来标记着那个索引被分配了，那个索引还可以使用。如果
_tls_array一定要放指针，那我们可以将没有分配的索引元素设置为NULL, 
已分配的非NULL，从前到后检查数值，取第一个NULL元素索引分配出去。但因为数组不一定放指针，也可以放整数，整数没有所谓的无效值，就不能用这种
方式。你可以创建一个同样大小的bool数组作标记，也可以采用位判断方式来替代bool数组。如果有需要，还可以定义自己的结构作标记用。但一定要有种
方式来区别分配的索引号跟没有分配的索引号。</p>
		<p>本文来自CSDN博客，转载请标明出处：<a href="http://blog.csdn.net/complex_ok/archive/2009/07/15/4351673.aspx">http://blog.csdn.net/complex_ok/archive/2009/07/15/4351673.aspx</a></p>
<img src ="http://www.cnitblog.com/textbox/aggbug/69238.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/textbox/" target="_blank">零度</a> 2010-09-27 12:41 <a href="http://www.cnitblog.com/textbox/archive/2010/09/27/69238.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>XSLT 文件做什么用啊??</title><link>http://www.cnitblog.com/textbox/archive/2010/07/06/67191.html</link><dc:creator>零度</dc:creator><author>零度</author><pubDate>Tue, 06 Jul 2010 04:09:00 GMT</pubDate><guid>http://www.cnitblog.com/textbox/archive/2010/07/06/67191.html</guid><wfw:comment>http://www.cnitblog.com/textbox/comments/67191.html</wfw:comment><comments>http://www.cnitblog.com/textbox/archive/2010/07/06/67191.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/textbox/comments/commentRss/67191.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/textbox/services/trackbacks/67191.html</trackback:ping><description><![CDATA[
		<h2 class="first">1、XSLT 简介</h2>　　XSLT 是一种用于将 XML 文档转换为 XHTML 文档或其他 XML 
文档的语言。
　　XPath 是一种用于在 XML 文档中进行导航的语言。
　　<b>什么是 XSLT？</b>
　　XSLT 指 XSL 转换（XSL Transformations）。 
　　XSLT 是 XSL 中最重要的部分。 
　　XSLT 可将一种 XML 文档转换为另外一种 XML 文档。 
　　XSLT 使用 XPath 在 XML 文档中进行导航。 
　　XPath 是一个 W3C 标准。 
　　<b>XSLT = XSL 转换</b>
　　XSLT 是 XSL 中最重要的部分。
　　XSLT 用于将一种 XML 文档转换为另外一种 XML 
文档，或者可被浏览器识别的其他类型的文档，比如 HTML 和 XHTML。通常，XSLT 是通过把每个 XML 元素转换为 (X)HTML 
元素来完成这项工作的。
　　通过 
XSLT，您可以向或者从输出文件添加或移除元素和属性。您也可重新排列元素，执行测试并决定隐藏或显示哪个元素，等等。
　　描述转化过程的一种通常的说法是，<b>XSLT 把 XML 源树转换为 XML 结果树。</b>
　　<b>XSLT 使用 XPath</b>
　　XSLT 使用 XPath 在 XML 文档中查找信息。XPath 
被用来通过元素和属性在 XML 文档中进行导航。
　　<b>它如何工作？</b>
　　在转换过程中，XSLT 使用 XPath 
来定义源文档中可匹配一个或多个预定义模板的部分。一旦匹配被找到，XSLT 就会把源文档的匹配部分转换为结果文档。
　　<b>XSLT 是 W3C 标准</b>
　　XSLT 在 1999 年 11 月 16 日被确立为 W3C 标准。<h2 class=""><a name="2"></a>2、XSLT 浏览器</h2>　　几乎所有主要的浏览器均支持 XML 和 XSLT。
　　<b>Mozilla Firefox</b>
　　从 1.0.2 版本开始，Firefox 就已开始支持 XML 和 XSLT（以及 
CSS）。
　　<b>Mozilla</b>
　　Mozilla 含有用于 XML 解析的 Expat，并支持 XML + 
CSS。Mozilla 同样支持命名空间。
　　Mozilla 可执行 XSLT。
　　<b>Netscape</b>
　　从版本 8 开始，Netscape 就开始使用 Mozilla 引擎，所以它对 XML /
 XSLT 的支持与Mozilla是相同的。
　　<b>Opera</b>
　　从版本 9 开始，Opera 已开始支持 XML 和 XSLT（以及 CSS）。版本 8
 仅支持 XML + CSS。
　　<b>Internet Explorer</b>
　　从版本 6 开始，Internet Explorer 已开始 
XML、命名空间、CSS、XSLT 以及 XPath。
　　版本 5 不兼容官方的 W3C XSL 标准<h2 class=""><a name="3"></a>XSLT 元素</h2>　　如果您需要有关下列元素的更详细的信息，请点击元素列中的链接。
　　N: 表示最早支持此标签的 Netscape 版本 
　　IE: 表示最早支持此标签的 Internet Explorer 版本 
　　注释：在 IE 5 中所支持的元素可能出现非标准的行为，这是由于 IE 5 发布于 
XSLT 被确立为正式的 W3C 标准之前。
　　元素 描述 IE N 
　　<br />apply-imports 应用来自导入样式表中的模版规则。 6.0 
　　<br />apply-templates 向当前元素或当前元素的子元素应用模板。 5.0 6.0 
　　<br />attribute 向元素添加属性。 5.0 6.0 
　　<br />attribute-set 创建命名的属性集。 6.0 6.0 
　　<br />call-template 调用一个指定的模板。 6.0 6.0 
　　<br />choose 
与&lt;when&gt;以及&lt;otherwise&gt;协同使用，来表达多重条件测试。 5.0 6.0 
　　<br />comment 在结果树中创建注释节点。 5.0 6.0 
　　<br />copy 创建当前节点的一个备份（无子节点及属性）。 5.0 6.0 
　　<br />copy-of 创建当前节点的一个备份（带有子节点及属性）。 6.0 6.0 
　　<br />decimal-format 定义当通过 format-number() 
函数把数字转换为字符串时，所要使用的字符和符号。 6.0 
　　<br />element 在输出文档中创建一个元素节点。 5.0 6.0 
　　<br />fallback 假如处理器不支持某个XSLT元素，规定一段备用代码来运行。 6.0 
　　<br />for-each 遍历指定的节点集中的每个节点。 5.0 6.0 
　　<br />if 包含一个模板，仅当某个指定的条件成立时应用此模板。 5.0 6.0 
　　<br />import 用于把一个样式表中的内容倒入另一个样式表中。 6.0 6.0 
　　<br />include 把一个样式表中的内容包含到另一个样式表中。 6.0 6.0 
　　<br />key 声明一个命名的键。 6.0 6.0 
　　<br />message 向输出写一条消息（用于错误报告）。 6.0 6.0 
　　<br />namespace-alias 把样式表中的命名空间替换为输出中不同的命名空间。 6.0
 
　　<br />number 测定当前节点的整数位置，并对数字进行格式化。 6.0 6.0 
　　<br />otherwise 规定 &lt;choose&gt; 元素的默认动作。 5.0 6.0
 
　　<br />output 定义输出文档的格式。 6.0 6.0 
　　<br />param 声明一个局部或全局参数。 6.0 6.0 
　　<br />preserve-space 用于定义保留空白的元素。 6.0 6.0 
　　<br />processing-instruction 生成处理指令节点。 5.0 6.0 
　　<br />sort 对结果进行排序。 6.0 6.0 
　　<br />strip-space 定义应当删除空白字符的元素。 6.0 6.0 
　　<br />stylesheet 定义样式表的根元素。 5.0 6.0 
　　<br />template 当指定的节点被匹配时所应用的规则。 5.0 6.0 
　　<br />text 通过样式表生成文本节点。 5.0 6.0 
　　<br />transform 定义样式表的根元素。 6.0 6.0 
　　<br />value-of 提取选定节点的值。 5.0 6.0 
　　<br />variable 声明局部或者全局的变量。 6.0 6.0 
　　<br />when 规定 &lt;choose&gt; 元素的动作。 5.0 6.0 
　　<br />with-param 规定需被传入某个模板的参数的值。 6.0 6.0<br /><br /><b>通俗点来说说吧xslt文件就是一个以xml为数据源的模板文件.作用是把xml里面的内容按xslt里面的规则填进去.</b><b><br />xslt里面的规则就是所说的xslt样式语言 其实跟sql脚本性质相似. sql脚步是以数据库为数据源,xslt是以xml作为数据源.<br /></b><img src ="http://www.cnitblog.com/textbox/aggbug/67191.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/textbox/" target="_blank">零度</a> 2010-07-06 12:09 <a href="http://www.cnitblog.com/textbox/archive/2010/07/06/67191.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>rfc822 rfc2045 rfc2046 rfc2047 rfc2183</title><link>http://www.cnitblog.com/textbox/archive/2010/07/01/67122.html</link><dc:creator>零度</dc:creator><author>零度</author><pubDate>Thu, 01 Jul 2010 02:15:00 GMT</pubDate><guid>http://www.cnitblog.com/textbox/archive/2010/07/01/67122.html</guid><wfw:comment>http://www.cnitblog.com/textbox/comments/67122.html</wfw:comment><comments>http://www.cnitblog.com/textbox/archive/2010/07/01/67122.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/textbox/comments/commentRss/67122.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/textbox/services/trackbacks/67122.html</trackback:ping><description><![CDATA[　Request For Comments 
(RFC)，是一系列以编号排定的文件。文件收集了有关因特网相关资讯，以及UNIX和因特网社群的软件文件。目前RFC文件是由Internet 
Society（ISOC）所赞助发行。
　　基本的因特网通讯协定都有在RFC文件内详细说明。RFC文件还额外加入许多的论题在标准内，
例如对于因特网新开发的协定及发展中所有的记录。因此几乎所有的因特网标准都有收录在RFC文件之中。
<br />    C(Request For 
Comments)-意即“请求评议”，包含了关于Internet的几乎所有重要的文字资料。如果你想成为网络方面的专家，那么RFC无疑是最重要也是
最经常需要用到的资料之一，所以RFC享有网络知识圣经之美誉<br /><br /><br />官方描述: http://www.ietf.org/rfc/rfc822.txt<br /><br /><img src ="http://www.cnitblog.com/textbox/aggbug/67122.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/textbox/" target="_blank">零度</a> 2010-07-01 10:15 <a href="http://www.cnitblog.com/textbox/archive/2010/07/01/67122.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Windows 中不规则窗体的编程原理(转) </title><link>http://www.cnitblog.com/textbox/archive/2010/06/30/67102.html</link><dc:creator>零度</dc:creator><author>零度</author><pubDate>Wed, 30 Jun 2010 04:22:00 GMT</pubDate><guid>http://www.cnitblog.com/textbox/archive/2010/06/30/67102.html</guid><wfw:comment>http://www.cnitblog.com/textbox/comments/67102.html</wfw:comment><comments>http://www.cnitblog.com/textbox/archive/2010/06/30/67102.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/textbox/comments/commentRss/67102.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/textbox/services/trackbacks/67102.html</trackback:ping><description><![CDATA[
		<p align="center">
				<b>Windows 中不规则窗体的编程实现<br /></b>
				<br />
      作者：<a href="mailto:txqc4@sohu.com">上海伟功通信 roc</a></p>
		<a href="http://www.vckbase.com/code/downcode.asp?id=2572">下载源代码</a>
		<br />
		<br />
		<b>一、序言</b>
		<br />
		<br />
      
　　在绝大多数的Windows应用程序中，其窗体都是使用的正规正矩的矩形窗体,例如我们常用的，“记事本”，“扫雷”，等等。矩形窗体，具有编程实现
简单，风格简洁的优点，所以在普通文档应用程序和
简单小游戏中使用足矣。但在某些娱乐游戏程序中使用就略显呆板些了，这时若用不规则窗体替代原先
的矩形窗体，将会使这类程序更添情趣。典型的例子有windows 自代的Media Player,新版本的Media 
Player有个控制面板的选项，选中这些面板，播放器就以选中的面板形状出现，这时的播放器比以前版
本的Media Player的古老矩形界面要生动有趣的多了。 
要实现不规则窗体不是太难，知道了基本原理后，你也可以创建各种有趣的不规则窗体。<br /><br /><b>二、实现原理</b><br /><br />
      　　
所有的 Windows 窗体都位于一个称为“region”中，窗体的大小如果超出“region”的范围，windows
会自动裁剪超出"region"范围那部分的窗体，使其不可见。所以，要创建不规则窗体有两个步骤：第一
步就是创建不规则"region".第二步就是将窗体放到创建的“region”中。<br />　　其中第二步很简单就调用一条语句即可。在SDK中调用
API函数SetWindowRgn，该函数原型如下：<pre>int SetWindowRgn( HWND hWnd, HRGN hRgn, BOOL bRedraw );</pre><p>　　
其中hWnd为待设置的窗体句柄，hRgn为已经创建的"region"句柄，bRedraw代表是否要重绘窗体。在MFC
中使用窗口类CWnd的成员函数int CWnd::SetWindowRgn（HRGN hRgn, BOOL bRedraw );该函数的参数意
义与API中同名函数相同。<br />　　相对与第二步，创建不规则窗体的第一步要复杂许多，并且不规则窗体越复杂，创建其"region"的过程也越复
杂。接下去我们将由浅入深地介绍各种创建”region”的方法。<br />
      　　在MFC中"region"对象，由CRgn类实现。CRgn的几乎每个成员函数都有同名的SDK API函数对应。<br /><br />

三、<b>简单“region”的创建</b><br /><br />
      　　
类CRgn创建一个新的"region"的简单方法有以下几个成员函数：</p><ol><li>BOOL CRgn::CreateRectRgn( int x1, int y1, int x2, int y2 ); 
创建矩形的“region”。</li><li>BOOL CRgn::CreateEllipticRgn( int x1, int y1, int x2, int y2
 ); 创建圆形或椭圆形“region”。</li><li>BOOL CRgn::CreateRoundRectRgn( int x1, int y1, int x2, int 
y2, int x3, int y3 ); 创建圆角矩形“region”。</li><li>BOOL CRgn::CreatePolygonRgn( LPPOINT lpPoints, int nCount, 
int nMode ); 创建多边形“region”。</li></ol><p>　　这里以创建椭圆窗体为例，介绍椭圆窗体创建的方法。在创建椭圆“region”的CreateEllipticRgn函数
中，x1,y1指椭圆所在矩形的左上角坐标，x2,y2指该矩形的右下角坐标。<br />
      　　
下面的代码加入到MFC对话框程序的OnInitDialog函数中，可将该对话框变成椭圆窗体：<br /></p><pre>BOOL CTestDlg::OnInitDialog()<br />{<br />	CDialog::OnInitDialog();<br />	...<br />	CRgn rgn;<br />	rgn. CreateEllipticRgn(0,0,200,100);<br />	SetWindowRgn(rgn,TRUE);<br />}<br /></pre><img src="http://www.vckbase.com/document/journal/vckbase38/images/Irregularimg1.gif" width="202" border="0" height="103" /><br />
      图一 椭圆窗体效果图<br /><br />
四、<b>作图路径法创建”region”</b><br /><br />
	使用该方法创建”region”的过程如下：<br />第一步绘制所要创建的窗体形状。<br />
该步骤中使用到CDC类中的一些成员函数如下：<pre>BOOL CDC::BeginPath( );</pre><p>调用该函数后当前设备环境(DC)开始追踪绘图的过程。</p><pre>int CDC::SetBkMode( int nBkMode );</pre><p>设置绘图时的背景模式，此应用中nBkMode必须取值为TRANSPARENT 。即设置绘图时背景不发生变化。</p><pre>BOOL CDC::EndPath( );</pre><p>调用该函数后当前设备环境(DC)结束追踪绘图的过程。<br />　　
开始绘图前，先调用BeginPath，然后调用SetBkMode。接下去就可调用CDC的其他绘图函数作图，例如
Arc,AngleArc,LineTo,MoveTo,RoundRect,,Textout等等。绘图完毕调用EndPath().<br /><br />

第二步将绘制的结果转成”region”.<br /><br />
此步骤中使用SDK API函数</p><pre>HRGN PathToRegion( HDC hdc );</pre><p>　　Hdc为作图DC的句柄， 
CDC类中的m_hDC成员变量可做此参数传入。示例，将下面代码加入某个按钮单击事件中，可以将当前窗体变为字符串”hello”的形状<br /></p><pre>void CTestDlg::OnTest() <br />{<br />    HRGN wndRgn;<br />    CClientDC dc(this);<br />    CFont mFont;<br /><br />    if (dc.m_hDC!=NULL)<br />    {<br />        VERIFY(mFont.CreateFont(<br />            200, 50, 0, 0, FW_HEAVY, TRUE, FALSE, <br />            0, ANSI_CHARSET, OUT_DEFAULT_PRECIS,        <br />            CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY,             <br />            DEFAULT_PITCH | FF_SWISS, "宋体"));                  <br /><br />	//开始记录窗体轮廓路径<br />        dc.BeginPath();		<br /><br />        //设置背景为透明模式,这句话是必须有的。<br />        dc.SetBkMode(TRANSPARENT);	<br /><br />        CFont * pOldFont;<br />        pOldFont = dc.SelectObject( &amp;mFont );<br />        dc.TextOut(0, 0, "Hello");<br /><br />        //结束记录窗体轮廓路径<br />        dc.SelectObject( pOldFont );<br />        dc.EndPath();<br /><br />        //把所记录的路径转化为窗体轮廓句柄<br />        wndRgn = ::PathToRegion(dc.m_hDC);<br /><br />        //赋予窗体指定的轮廓形状<br />        this-&gt;SetWindowRgn(wndRgn, TRUE);		<br />    }<br />}<br /></pre>
CClientDC是CDC的派生类，故此该类具有所有CDC类的成员变量和成员函数。
<br /><br /><img src="http://www.vckbase.com/document/journal/vckbase38/images/Irregularimg2.gif" width="275" border="0" height="204" /><br />
      图二 hello形状的窗体效果图<br /><br />

五、<b>根据图像创建”region”</b><br /><br />
      　　
此法创建不规则窗体比较复杂。首先准备一张含有目标窗体形状的图片，设置透明色即将图片中部不属于窗体形状的部分，标记成同一种颜色，例如蓝色
RGB(0,0,255).程序运行后先装入图片。然后逐个扫描图片的每个像素，如这个像素不属于透明色，则在相应位置创建一个只含一个像素的
“region”然后将这些小”region ”合并起来组成一个任意形状的”region”.这里将使用到CRgn的一个成员函数
      ：<pre>int CRgn::CombineRgn( CRgn* pRgn1, CRgn* pRgn2, int nCombineMode );</pre><p>　　其中pRgn1,pRgn2为要合并的两个“region”，nCombineMode为合并的方式，此应用中取RGN_OR，即
两”region”全部合并去处重复部分。代码实现如下：<br /></p><pre>void SetupRegion(<br />CDC *pDC, //窗体的DC指针<br />CBitmap &amp;cBitmap, //含有窗体形状的位图对象<br />COLORREF TransColor //透明色<br />)<br />{    CDC memDC;<br />    //创建与传入DC兼容的临时DC<br />    memDC.CreateCompatibleDC(pDC);<br /><br />    CBitmap *pOldMemBmp=NULL;<br />    //将位图选入临时DC<br />    pOldMemBmp=memDC.SelectObject(&amp;cBitmap);<br /><br />    CRgn wndRgn;<br />    //创建总的窗体区域，初始region为0<br />    wndRgn.CreateRectRgn(0,0,0,0);<br /><br />    BITMAP bit;   <br />    cBitmap.GetBitmap (&amp;bit);//取得位图参数，这里要用到位图的长和宽     <br /><br />    int y;<br />        for(y=0;y&lt;=bit.bmHeight  ;y++)<br />        {<br />	    CRgn rgnTemp; //保存临时region<br /><br />            int iX = 0;<br />            do<br />            {<br />                //跳过透明色找到下一个非透明色的点.<br />                while (iX &lt;= bit.bmWidth  &amp;&amp; memDC.GetPixel(iX, y) == TransColor)<br />                    iX++;<br /><br />                //记住这个起始点<br />                int iLeftX = iX;<br /><br />                //寻找下个透明色的点<br />                while (iX &lt;= bit.bmWidth  &amp;&amp; memDC.GetPixel(iX, y) != TransColor)<br />                    ++iX;<br /><br />                //创建一个包含起点与重点间高为1像素的临时“region”<br />                rgnTemp.CreateRectRgn(iLeftX, y, iX, y+1);<br /><br />                //合并到主"region".<br />                wndRgn.CombineRgn(&amp;wndRgn, &amp;rgnTemp, RGN_OR);<br /><br />		//删除临时"region",否则下次创建时和出错<br />                rgnTemp.DeleteObject();<br />            }while(iX <bit.bmwidth );="" ix="0;" }="" if(poldmembmp)="" memdc.selectobject(poldmembmp);="" cwnd="" *="" pwnd="pDC-">GetWindow();<br />    pWnd-&gt;SetWindowRgn(wndRgn,TRUE);    <br />    pWnd-&gt;SetForegroundWindow();    <br />}<br /></bit.bmwidth></pre>
      　　
上述代码创建的不规则窗体中，在OnEraseBkgnd事件中绘制该位图，就可得到与该位图形状一模一样的窗体。
<br /><br /><img src="http://www.vckbase.com/document/journal/vckbase38/images/Irregularimg3.gif" width="110" border="0" height="254" /><br />
      图三 根据位图和位图中的透明色创建的窗体效果图<br /><br /><b>六、小结<br /></b><br />
	  
　　三种创建“region”的方法，第一种最简单，如果所需的窗体形状是简单的几何图形，这种方法最合适；第二种稍微复杂些，但是创建的窗体形状更多
些；第三种方法可以创建任何在图片中画出的窗体形状，但是实现的复杂度也最高。<br /><br />
注：本文的写作曾参考了“<a target="_blank" href="http://www.vckbase.com/document/viewdoc/?id=541">形
态各异的不规则窗体</a>”一文。<img src ="http://www.cnitblog.com/textbox/aggbug/67102.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/textbox/" target="_blank">零度</a> 2010-06-30 12:22 <a href="http://www.cnitblog.com/textbox/archive/2010/06/30/67102.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>pop</title><link>http://www.cnitblog.com/textbox/archive/2010/06/28/67081.html</link><dc:creator>零度</dc:creator><author>零度</author><pubDate>Mon, 28 Jun 2010 06:17:00 GMT</pubDate><guid>http://www.cnitblog.com/textbox/archive/2010/06/28/67081.html</guid><wfw:comment>http://www.cnitblog.com/textbox/comments/67081.html</wfw:comment><comments>http://www.cnitblog.com/textbox/archive/2010/06/28/67081.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/textbox/comments/commentRss/67081.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/textbox/services/trackbacks/67081.html</trackback:ping><description><![CDATA[POP3 协议分析<br />第1 章.      POP3 概述<br />POP3 全称为Post Office Protocol version3，即邮局协议第3版。它被用户代理用来邮件服务器取得邮 件。POP3采用 的也是C/S通信 模型，对应的RFC文 档为RFC1939。该协议非常简单，所以我们只重点介绍其通信过程，而相关的一些概念和术语请参考RFC文档或另外一篇文章《SMTP协议分析》<br />第2 章.      POP3 详解<br />2.1.   通信过程<br />用户从邮件服务器上接收邮件的典型通信过 程如下。<br />1)         用户运行用户代理（如Foxmail, Outlook Express）。<br />2)         用户代理（以下简称客户端）与邮件服务器（以下简称服务器端）的110端口建立TCP连 接。<br />3)         客户端向服务器端发出各种命令，来请求各种服务（如查询邮箱信息，下载某封邮件等）。<br />4)         服务端解析用户的命令，做出相应动作并返回给客户端一个响应。<br />5)         3 ）和4)交替进行，直到接收完所有邮件转到步骤6)，或两者的连接被意外中断而直接退出。<br />6)         用户代理解析从服务器端获得的邮件，以适当地形式（如可读）的形式呈现给用户。<br />其中2)、3）和4）用POP3协议通信。可以看出命令和响应是POP3通信的重点，我们将 予以重点讲述。<br />2.2.   命令和响应<br />2.2.1.   格式<br />POP3 的命令不多，它的一般形式是：COMMAND  [Parameter] &lt;CRLF&gt;。其中COMMAND是ASCII形式的命令名，Parameter是相应的命令参数，&lt;CRLF&gt;是回车换行符 (0DH, 0AH)。<br />服务器响应是由一个单独的命令行组成，或 多个命令行组成，响应第一行“+OK”或“-ERR”开头，然后再加上一些ASCII文本。“+OK”和“-ERR”分别指出相应的操作状态是成功的还是失败的。<br />2.2.2.   三个状态<br />POP3 协议中有三种状态，认正状态，处理状态，和更新状态。 命令的执行可以改变协议的状态，而对于具体的某命令，它只能在具体的某状态下使用，这些请参看表1和RFC193。<br />客户机与服务器刚与服务器建立连接时，它 的状态为认证状态；一旦客户机提供了自己身份并被成功地确认，即由认可状态转入处理状态；在完成相应的操作后客户机发出QUIT命令（具体说明见后续内容），则进入更新状态，更新之后又重返认可状态；当然在认可状态下执行QUIT命令，可释放连接。状态间的转移如图 1所示。 <br />--- 建立连接---|认可|--认证成功--|处理|--执行QUIT--|更新| <br />                  |_______ -QUIT结束_________________|<br /><br /><br />2.2.3.   一个例子<br />命令和响应的格式是语法，各命令和响应的 意思则是语义，各命令和各响应在时间上的关系则是同步。我们还是通过以个简单的POP3通信过程来说明协议的这三个 要素。<br />C ：telnet pop3.126.com 110   /*　以telnet方式连接126邮件服务器　*/<br />S ：+OK Welcome to coremail Mail Pop3 Server (126coms[3adb99eb4207ae5256632eecb8f8b4855])　/* +OK,代表命令成功，其后的信息则随服务器的不同而不同*/<br />C ：USER bripengandre /* 采用明文认证 */<br />S ：+OK core mail<br />C ：PASS Pop3world /* 发送邮箱密码 */<br />S ：+OK 654 message(s) [30930370 byte(s)] /* 认证成功，转入处理状态 */<br />C ：LIST 1 /* 显示第一封邮件的信息 */<br />S ：+OK 1 5184 ./* 第一封邮件 的大小为5184 字节 */<br />C ：UIDL 1 /* 返回第一封邮件的唯一标识符 */<br />S ：+OK 1 1tbisBsHaEX9byI9EQAAsd /* 数字1 后的长字符串就是第一封邮件的唯一标志符 */<br />C ：RETR 1 /* 下载第一封邮件 */<br />S ：+OK 5184 octets /* 第 一封邮件的大小为5184字节 */<br />S ：Receive…  /* 第 一封邮件的具体内容 */<br />S ：…<br />C ：QUIT /* 转入更新状态，接着再转入认证状态 */<br />S ：+OK<br />C: QUIT /* 退出连接 */<br />S ：+OK core mail /* 成功地退出了连接 */<br />对于上述的过程，补充如下几点内容。<br />1)         “C：”开头的行(不包括"C：")是客户端的输入，而以“S：”开头的行(不包括"S：")则是服务器的输出。<br />2)         上述的命令并不一定会一次性成功，服务器会返回错误响应（以“-ERR”开头），客户端应该按照协议规定的时序，来输入后续的命令（或重复执行失败的命令，或重置会话，或退出会话等等）。<br />3)         上述过程是示意性的，实际过程可能与其有较大不同。例如，实际过程中可能使用加密认证（MD5摘要认证）。<br />4)         RETR 下载下来的邮件可能会难以看懂，这是 因为其可能使用了quoted-printable编码或base64编码，我们可用Foxmail等用户代理软件来解码它。<br />2.2.4.   常用命令和响应<br />SMTP 命令不区分大小写，但参数区分大小写，有关这方面的详细说明请参考RFC1939。常用的命令如表 1所示。<br /><br />命 令     <br />参 数     <br />使 用在何种状态中     <br />描 述<br />USER   Username 认证此命令与下面的pass命令若成功，将导致状态转 换<br />PASS   Password 认证此命令若成功，状态转化为更新<br />APOP   Name,Digest 认证Digest 是MD5消息摘要<br />STAT     None 处理请求服务器发回关于邮箱的统计资料，如邮件总数和总字节数<br />UIDL      [Msg#] （邮件号，下同）处理返回邮件的唯一标识符，POP3会话的每个标识符都将是唯一的<br />LIST       [Msg#]     处理 返回邮件的唯一标识符，POP3会话的每个标识符都将是唯一的<br />RETR     [Msg#]     处理 返回由参数标识的邮件的全部文本<br />DELE     [Msg#]     处理 服务器将由参数标识的邮件标记为删除，由QUIT命 令执行<br />TOP        [Msg#]     处理 服务器将返回由参数标识的邮件的邮件头+前n行内容，n必须是正整数<br />NOOP     None     处理 服务器返回一个肯定的响应，用于测试连接是否成功<br />QUIT     None     处理、认证     <br />1)         如果服务器处于“处理”状态，么将进入“更新”状态以删除任何标记为 删除的邮件，并重返“认证”状态。<br />2)         如果服务器处于“认证”状态，则结束会话，退出连接<br /><br />表 1 POP3 的常用命令<br />至于响应则如2.2.1所述，由“+OK”或“-ERR”开头，后跟一些可读的说明和一些其它参数（对RETR，这个参数就是邮件的内容）。更详细的说明请参考RFC1939。<br /><br /><img src ="http://www.cnitblog.com/textbox/aggbug/67081.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/textbox/" target="_blank">零度</a> 2010-06-28 14:17 <a href="http://www.cnitblog.com/textbox/archive/2010/06/28/67081.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>通用邮件格式 RFC822 MIME格式</title><link>http://www.cnitblog.com/textbox/archive/2010/06/23/66958.html</link><dc:creator>零度</dc:creator><author>零度</author><pubDate>Wed, 23 Jun 2010 02:55:00 GMT</pubDate><guid>http://www.cnitblog.com/textbox/archive/2010/06/23/66958.html</guid><wfw:comment>http://www.cnitblog.com/textbox/comments/66958.html</wfw:comment><comments>http://www.cnitblog.com/textbox/archive/2010/06/23/66958.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/textbox/comments/commentRss/66958.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/textbox/services/trackbacks/66958.html</trackback:ping><description><![CDATA[ <b>(RFC 822) 
</b><b>Request for Comments</b><br /><br /><b>Request for Comments</b> (<b>RFC</b>) is a <a href="http://en.wikipedia.org/wiki/Memorandum" title="Memorandum">memorandum</a>
 published by the <a href="http://en.wikipedia.org/wiki/Internet_Engineering_Task_Force" title="Internet Engineering Task Force">Internet Engineering Task Force</a>
 (IETF) describing methods, behaviors, research, or innovations 
applicable to the working of the <a href="http://en.wikipedia.org/wiki/Internet" title="Internet">Internet</a>
 and Internet-connected systems<br /><br /><br />除了由一个Internet用户传递给另一个用户的信息之外，电子邮件中还必须包含附加的服务信息。SMTP服务器利用这些信息来传递邮件，而客户端的邮
件接收软件则利用这些信息来对邮件进行分类。
　　每封邮件都有两个部分：信头和主体。
　　信头部分的字段可分为两类。一类是由你的电子邮件程序产生的，另一类是邮件通过SMTP服务器
时被加上的。在所有被SMTP服务器加上的字段中，对我们而言最重要的是Message-Id字段。这个字段是由你传向的SMTP服务器加上的。这个一个
唯一的ID号。你可用这个号码作为邮件的编号。
　　下表列出了可由用户的邮件程序控制的信头字段。这并不意味着所有的字段都是必须的。实际上可以
忽略形成信头这一步骤而只发送正文。让你的SMTP服务器为你加上最起码的必需字段。
　　<br />信头字段 目的 
　　<br />From 邮件作者 
　　<br />Sender 发信人 
　　<br />Reply-To 回邮地址 
　　<br />To 收信人地址 
　　<br />CC 抄送：另一个收信人地址 
　　<br />BCC 密送：收信人地址，但其它收信人看不到这个收信人的地址。 
　　<br />Subject 主题 
<br />　　(编码规则：encoded-word = "=?" charset "?" encoding "?" encoded-text "?="<br />
                encoding<br />
                Q --- Quote Printable<br />
                B --- BASE64<br />
                U --- UUENCODE<br /><br />          
例1: Subject: =?GB2312?Q?=C4=E3=BA=C3?=<br />           例2: Subject: =?utf-7?B?WFgrWUNkU0swNE9kbjVPRVZiKy0z?=<br />         )<br />Comments 备注 
　　<br />Keywords 关键字，用来进一步搜索邮件 
　　<br />In-Reply-To 被当前邮件回复的邮件的ID 
　　<br />References 几乎同In-Reply-To一样 
　　<br />Encrypted 加密邮件的加密类型 
　　<br />Date 发信日期<br /><br /><br /><b>MIME, 全称为“Multipurpose Internet Mail Extensions”,</b> 
比较确切的中文名称为“多用途互联网邮件扩展”。它是当前广泛应用的一种电子邮件技术规范，基本内容定义于RFC 2045-2049
<div>什么是MIME类型?-在把输出结果传送到浏览器上的时候，浏览器必须启动适当的应用程序来处理这个输出文档。这可以通过多种类型MIME（多
功能网际邮件扩充协议）来完成。在HTTP中，MIME类型被定义在Content-Type header中。</div><div>例如，架设你要传送一个Microsoft 
Excel文件到客户端。那么这时的MIME类型就是“application/vnd.ms-excel”。在大多数实际情况中，这个文件然后将传送给
 Execl来处理（假设我们设定Execl为处理特殊MIME类型的应用程序）。在ASP中，设定MIME类型的方法是通过Response对象的 
ContentType属性。</div><div><br />多媒体文件格式MIME</div><div>最早的HTTP协议中，并没有附加的数据类型信息，所有传送的数据都被客户程序解释为超文本标记语言HTML 
文档，而为了支持多媒体数据类型，HTTP协议中就使用了附加在文档之前的MIME数据类型信息来标识数据类型。</div><div>MIME意为多目Internet邮件扩展，它设计的最初目的是为了在发送电子邮件时附加多媒体数据，让邮件客户程序能根据其类型进行处理。然
而当它被HTTP协议支持之后，它的意义就更为显著了。它使得HTTP传输的不仅是普通的文本，而变得丰富多彩。</div><div>每个MIME类型由两部分组成，前面是数据的大类别，例如声音audio、图象image等，后面定义具体的种类。</div><div>常见的MIME类型</div><div>超文本标记语言文本 .html,.html text/html<br />普通文本 .txt text/plain<br />RTF文本 
.rtf application/rtf<br />GIF图形 .gif image/gif<br />JPEG图形 .ipeg,.jpg 
image/jpeg<br />au声音文件 .au audio/basic<br />MIDI音乐文件 mid,.midi 
audio/midi,audio/x-midi<br />RealAudio音乐文件 .ra, .ram audio/x-pn-realaudio<br />MPEG
文件 .mpg,.mpeg video/mpeg<br />AVI文件 .avi video/x-msvideo<br />GZIP文件 .gz 
application/x-gzip<br />TAR文件 .tar application/x-tar</div><div>Internet中有一个专门组织IANA来确认标准的MIME类型，但Internet发展的太快，很多应用程序等不及IANA来确认他们使
用的 
MIME类型为标准类型。因此他们使用在类别中以x-开头的方法标识这个类别还没有成为标准，例如：x-gzip，x-tar等。事实上这些类型运用的很
广泛，已经成为了事实标准。只要客户机和服务器共同承认这个MIME类型，即使它是不标准的类型也没有关系，客户程序就能根据MIME类型，采用具体的处
理手段来处理数据。而Web服务器和浏览器（包括操作系统）中，缺省都设置了标准的和常见的MIME类型，只有对于不常见的 
MIME类型，才需要同时设置服务器和客户浏览器，以进行识别。</div><div>由于MIME类型与文档的后缀相关，因此服务器使用文档的后缀来区分不同文件的MIME类型，服务器中必须定义文档后缀和MIME类型之间的对
应关系。而客户程序从服务器上接收数据的时候，它只是从服务器接受数据流，并不了解文档的名字，因此服务器必须使用附加信息来告诉客户程序数据的MIME
类型。服务器在发送真正的数据之前，就要先发送标志数据的MIME类型的信息，这个信息使用Content-type关键字进行定义，例如对于HTML文
档，服务器将首先发送以下两行MIME标识信息,这个标识并不是真正的数据文件的一部分。</div><div>Content-type: text/html</div><div>注意，第二行为一个空行，这是必须的，使用这个空行的目的是将MIME信息与真正的数据内容分隔开。<br /><br /><br /><br />后语:现在msword2003支持保存成mht格式的文件,我尝试了几天想把他转换成mime格式邮件发送都失败了.而word里面自带有调用outlook来发送生产的mht文件.<br /><br />格式连接: <br />http://en.wikipedia.org/wiki/MIME<br />http://www.mhonarc.org/~ehood/MIME/<br />http://zh.wikipedia.org/zh-hk/MIME (中文)<br />http://docs.sun.com/source/816-6027-10/asdk3.htm<br /><br /><br /><br /><br /><br /><br /><br /></div><br /><img src ="http://www.cnitblog.com/textbox/aggbug/66958.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/textbox/" target="_blank">零度</a> 2010-06-23 10:55 <a href="http://www.cnitblog.com/textbox/archive/2010/06/23/66958.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>SMTP 资料</title><link>http://www.cnitblog.com/textbox/archive/2010/06/21/66901.html</link><dc:creator>零度</dc:creator><author>零度</author><pubDate>Mon, 21 Jun 2010 05:00:00 GMT</pubDate><guid>http://www.cnitblog.com/textbox/archive/2010/06/21/66901.html</guid><wfw:comment>http://www.cnitblog.com/textbox/comments/66901.html</wfw:comment><comments>http://www.cnitblog.com/textbox/archive/2010/06/21/66901.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/textbox/comments/commentRss/66901.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/textbox/services/trackbacks/66901.html</trackback:ping><description><![CDATA[
		<link rel="File-List" href="file:///C:%5CUsers%5Cadmin%5CAppData%5CLocal%5CTemp%5Cmsohtml1%5C02%5Cclip_filelist.xml" />
		<!--[if gte mso 9]><xml>
 <w:WordDocument>
  <w:View>Normal</w:View>
  <w:Zoom>0</w:Zoom>
  <w:PunctuationKerning/>
  <w:DrawingGridVerticalSpacing>7.8 pt</w:DrawingGridVerticalSpacing>
  <w:DisplayHorizontalDrawingGridEvery>0</w:DisplayHorizontalDrawingGridEvery>
  <w:DisplayVerticalDrawingGridEvery>2</w:DisplayVerticalDrawingGridEvery>
  <w:ValidateAgainstSchemas/>
  <w:SaveIfXMLInvalid>false</w:SaveIfXMLInvalid>
  <w:IgnoreMixedContent>false</w:IgnoreMixedContent>
  <w:AlwaysShowPlaceholderText>false</w:AlwaysShowPlaceholderText>
  <w:Compatibility>
   <w:SpaceForUL/>
   <w:BalanceSingleByteDoubleByteWidth/>
   <w:DoNotLeaveBackslashAlone/>
   <w:ULTrailSpace/>
   <w:DoNotExpandShiftReturn/>
   <w:AdjustLineHeightInTable/>
   <w:BreakWrappedTables/>
   <w:SnapToGridInCell/>
   <w:WrapTextWithPunct/>
   <w:UseAsianBreakRules/>
   <w:DontGrowAutofit/>
   <w:UseFELayout/>
  </w:Compatibility>
  <w:BrowserLevel>MicrosoftInternetExplorer4</w:BrowserLevel>
 </w:WordDocument>
</xml><![endif]-->
		<!--[if gte mso 9]><xml>
 <w:LatentStyles DefLockedState="false" LatentStyleCount="156">
 </w:LatentStyles>
</xml><![endif]-->
		<style>
				<!--
 /* Font Definitions */
 @font-face
	{font-family:SimSun;
	panose-1:2 1 6 0 3 1 1 1 1 1;
	mso-font-alt:宋体;
	mso-font-charset:134;
	mso-generic-font-family:roman;
	mso-font-pitch:auto;
	mso-font-signature:3 680460288 22 0 262145 0;}
@font-face
	{font-family:"\@SimSun";
	panose-1:2 1 6 0 3 1 1 1 1 1;
	mso-font-charset:134;
	mso-generic-font-family:auto;
	mso-font-pitch:variable;
	mso-font-signature:3 680460288 22 0 262145 0;}
 /* Style Definitions */
 p.MsoNormal, li.MsoNormal, div.MsoNormal
	{mso-style-parent:"";
	margin:0cm;
	margin-bottom:.0001pt;
	text-align:justify;
	text-justify:inter-ideograph;
	mso-pagination:none;
	font-size:10.5pt;
	mso-bidi-font-size:12.0pt;
	font-family:"Times New Roman";
	mso-fareast-font-family:SimSun;
	mso-font-kerning:1.0pt;}
a:link, span.MsoHyperlink
	{color:blue;
	text-decoration:underline;
	text-underline:single;}
a:visited, span.MsoHyperlinkFollowed
	{color:purple;
	text-decoration:underline;
	text-underline:single;}
 /* Page Definitions */
 @page
	{mso-page-border-surround-header:no;
	mso-page-border-surround-footer:no;}
@page Section1
	{size:595.3pt 841.9pt;
	margin:72.0pt 90.0pt 72.0pt 90.0pt;
	mso-header-margin:42.55pt;
	mso-footer-margin:49.6pt;
	mso-paper-source:0;
	layout-grid:15.6pt;}
div.Section1
	{page:Section1;}
-->
		</style>
		<!--[if gte mso 10]>
<style>
 /* Style Definitions */
 table.MsoNormalTable
	{mso-style-name:"Table Normal";
	mso-tstyle-rowband-size:0;
	mso-tstyle-colband-size:0;
	mso-style-noshow:yes;
	mso-style-parent:"";
	mso-padding-alt:0cm 5.4pt 0cm 5.4pt;
	mso-para-margin:0cm;
	mso-para-margin-bottom:.0001pt;
	mso-pagination:widow-orphan;
	font-size:10.0pt;
	font-family:"Times New Roman";
	mso-ansi-language:#0400;
	mso-fareast-language:#0400;
	mso-bidi-language:#0400;}
</style>
<![endif]-->
		<p class="MsoNormal" style="text-align: left;" align="left">
				<b>
						<span style="font-size: 18pt; font-family: SimSun;" lang="EN-US">SMTP</span>
				</b>
				<b>
						<span style="font-size: 18pt; font-family: SimSun;">协议简介<span lang="EN-US"><o:p></o:p></span></span>
				</b>
		</p>
		<p class="MsoNormal" style="text-align: left;" align="left">
				<span style="font-size: 12pt; font-family: SimSun;">　　<b><span lang="EN-US">SMTP</span></b>目前已是事实上的在<b><span lang="EN-US">Internet</span></b>传输<b><span lang="EN-US"><a href="http://baike.baidu.com/view/8409.htm" target="_blank">E-Mail</a></span></b>的
标准，是一个相对简单的基于文本的协议。在其之上指定了一条消息的一个或多个接收者（在大多数情况下被确定是存在的），然后消息文本就传输了。可以很简单 地通过<b><span lang="EN-US">Telnet</span></b>程序来测试一个<b><span lang="EN-US">SMTP</span></b>服务器，<b><span lang="EN-US">SMTP</span></b>使用<b><span lang="EN-US">TCP</span></b>端口<span lang="EN-US">25</span>。要为一个给定 的域名决定一个<b><span lang="EN-US">SMTP</span></b>服务器，需要使用<b><span lang="EN-US">MX(Mail eXchange</span>）<span lang="EN-US">DNS</span></b>。<span lang="EN-US"><o:p></o:p></span></span>
		</p>
		<p class="MsoNormal" style="text-align: left;" align="left">
				<a name="2">
				</a>
				<b>
						<span style="font-size: 18pt; font-family: SimSun;" lang="EN-US">SMTP </span>
				</b>
				<b>
						<span style="font-size: 18pt; font-family: SimSun;">协议发展<span lang="EN-US"><o:p></o:p></span></span>
				</b>
		</p>
		<p class="MsoNormal" style="text-align: left;" align="left">
				<span style="font-size: 12pt; font-family: SimSun;">　　在<span lang="EN-US">20</span>世纪<span lang="EN-US">80</span>年代早期<b><span lang="EN-US">SMTP</span></b>开始被广泛地使用。当时它只是作为<b><span lang="EN-US">UUCP</span></b>的补充，<b><span lang="EN-US">UUCP</span></b>更 适合于处理在间歇连接的机器间传送邮件。相反<b><span lang="EN-US">SMTP</span></b>在发送和接收的机器始终都联网的情况下工作得最好。<span lang="EN-US"><o:p></o:p></span></span>
		</p>
		<p class="MsoNormal" style="text-align: left;" align="left">
				<span style="font-size: 12pt; font-family: SimSun;">　　<b><span lang="EN-US">SMTP</span></b>独立于特定的传输子系统，且只需要可靠有序的数据流信道支持。<b><span lang="EN-US">SMTP</span></b>重 要特性之一是其能跨越网络传输邮件，即<span lang="EN-US">“<b>SMTP</b></span>邮件中继<span lang="EN-US">”</span>。通常，一个网络可以由公用因特网上<b><span lang="EN-US">TCP</span></b>可相互间访问的主机、
防火墙分隔的<b><span lang="EN-US"><a href="http://baike.baidu.com/view/7729.htm" target="_blank">TCP/IP</a></span></b>网 络上<b><span lang="EN-US">TCP</span></b>可相互访问的主机，以及其他<b><span lang="EN-US">LAN/WAN</span></b>中的主机利用非<b><span lang="EN-US">TCP</span></b>传输层协议组成。使用<b><span lang="EN-US">SMTP</span></b>， 可实现相同网络上处理机之间的邮件传输，也可通过中继器或网关是实现某处理机与其他网络之间的邮件传输。<span lang="EN-US"><o:p></o:p></span></span>
		</p>
		<p class="MsoNormal" style="text-align: left;" align="left">
				<span style="font-size: 12pt; font-family: SimSun;">　　在这种方式下，邮件的发送可能经过从发送端到接收端路径上的大量中间中继器或网关主机。域名服 务系统（<b><span lang="EN-US">DNS)</span></b>的邮件交换服务器可以用来识别出传输邮件的下一跳<b><span lang="EN-US">IP</span></b>地址。<span lang="EN-US"><o:p></o:p></span></span>
		</p>
		<p class="MsoNormal" style="text-align: left;" align="left">
				<span style="font-size: 12pt; font-family: SimSun;">　　<b><span lang="EN-US">Sendmail</span></b>是最早实现<b><span lang="EN-US">SMTP</span></b>的邮件传输代理之一。到<span lang="EN-US"> 2001</span>年至少有<span lang="EN-US">50</span>个程序将<b><span lang="EN-US">SMTP</span></b><span lang="EN-US"></span>实现为一个客户端（消息的发送者）或一个服务器（消息的接受者）。一些其他的流行的<b><span lang="EN-US">SMTP</span></b>服 务器包括<b><span lang="EN-US">Philip Hazel</span></b><span lang="EN-US"></span>的<b><span lang="EN-US">exim</span>，<span lang="EN-US">IBM</span></b>的<b><span lang="EN-US">Postfix</span>，<span lang="EN-US">D.J.Bernstein</span></b>的<b><span lang="EN-US">Qmail</span></b>， 以及<span lang="EN-US">Mi<b>crosoft Exchange Server.</b><o:p></o:p></span></span>
		</p>
		<p class="MsoNormal" style="text-align: left;" align="left">
				<span style="font-size: 12pt; font-family: SimSun;">　　由于这个协议开始是基于纯<b><span lang="EN-US"><a href="http://baike.baidu.com/view/441541.htm" target="_blank">ASCⅡ</a></span></b>文本的，在二进制文件上处理得
并不好。后来开发了用来编码二进制文件的标准，如<b><span lang="EN-US">MIME</span></b>，以使其通过<b><span lang="EN-US">SMTP</span></b>来传输。今天，大多数<b><span lang="EN-US">SMTP</span></b>服 务器都支持<span lang="EN-US">8</span>位<b><span lang="EN-US">MIME</span></b>扩展，它使二进制文件的传输变得几乎和纯文本一样简单。<span lang="EN-US"><o:p></o:p></span></span>
		</p>
		<p class="MsoNormal" style="text-align: left;" align="left">
				<span style="font-size: 12pt; font-family: SimSun;">　　<span lang="EN-US">( </span>注意：<b><span lang="EN-US">SMTP</span></b>是一个<span lang="EN-US">"</span>推<span lang="EN-US">"</span>的协议，它不允许根据需要从远程服务器上<span lang="EN-US">“</span>拉<span lang="EN-US">” </span>来消息。要做到这点，邮件客户端必须使用<b><span lang="EN-US"><a href="http://baike.baidu.com/view/5404.htm" target="_blank">POP3</a></span></b>或<b><span lang="EN-US"><a href="http://baike.baidu.com/view/17877.htm" target="_blank">IMAP</a></span></b>上。
另一个，<b><span lang="EN-US">SMTP</span></b>服务器可以使用<b><span lang="EN-US">ETRN</span></b><span lang="EN-US">(<b>Extended Turn</b></span>，扩展回车）命令在<b><span lang="EN-US">SMTP</span></b>上
触发一个发送。<span lang="EN-US">) <o:p></o:p></span></span>
		</p>
		<p class="MsoNormal" style="text-align: left;" align="left">
				<span style="font-size: 12pt; font-family: SimSun;">　　垃圾邮件仍然是个重要的问题。原始的<b><span lang="EN-US">SMTP</span></b>协议的局限之一在于它没有为发送方
进行认证的功能。因此定义了<b><span lang="EN-US">SMTP-AUTH</span></b><span lang="EN-US"></span>扩展。由于<b><span lang="EN-US">SMTP</span></b><span lang="EN-US"></span>巨大安装基础的网络效应，广阔地修改<b><span lang="EN-US">SMTP</span></b>或 者完全替代它被认为是不现实的。<b><span lang="EN-US">Internet Mail</span></b><span lang="EN-US"><b>2000</b></span>就是这样一个为替换而做的建议。<b><span lang="EN-US">IRTF </span></b>的<span lang="EN-US"><a href="http://baike.baidu.com/view/1484964.htm" target="_blank"><span lang="EN-US"><span lang="EN-US">反垃圾邮件</span></span></a></span>研 究小组正在研究一些提供简单、灵活、轻量级的、可升级的源端认证的建议。最有可能被接受的建议是<b><span lang="EN-US">Sender Policy Framework</span></b><span lang="EN-US"></span>协议。<span lang="EN-US"><o:p></o:p></span></span>
		</p>
		<p class="MsoNormal" style="text-align: left;" align="left">
				<a name="3">
				</a>
				<b>
						<span style="font-size: 18pt; font-family: SimSun;" lang="EN-US">SMTP </span>
				</b>
				<b>
						<span style="font-size: 18pt; font-family: SimSun;">协议命令<span lang="EN-US"><o:p></o:p></span></span>
				</b>
		</p>
		<p class="MsoNormal" style="text-align: left;" align="left">
				<span style="font-size: 12pt; font-family: SimSun;">　　<b><span lang="EN-US">SMTP</span></b>命令是发送于<b><span lang="EN-US">SMTP</span></b>主机之间的<b><span lang="EN-US">ASCⅡ</span></b>信息，可能使用到的命令如下表所示。<span lang="EN-US"><o:p></o:p></span></span>
		</p>
		<p class="MsoNormal" style="text-align: left;" align="left">
				<span style="font-size: 12pt; font-family: SimSun;">　　<b><span lang="EN-US">SMTP</span>协议命令</b><span lang="EN-US"><o:p></o:p></span></span>
		</p>
		<p class="MsoNormal" style="text-align: left;" align="left">
				<span style="font-size: 12pt; font-family: SimSun;">　　<span lang="EN-US"><o:p></o:p></span></span>
		</p>
		<table class="MsoNormalTable" style="" border="0" cellpadding="0">
				<tbody>
						<tr style="">
								<td style="width: 105.75pt; padding: 0.75pt;" width="141">
										<p class="MsoNormal" style="text-align: left;" align="left">
												<span style="font-size: 12pt; font-family: SimSun;">命 令<span lang="EN-US"><o:p></o:p></span></span>
										</p>
								</td>
								<td style="width: 438.75pt; padding: 0.75pt;" width="585">
										<p class="MsoNormal" style="text-align: left;" align="left">
												<span style="font-size: 12pt; font-family: SimSun;">描述<span lang="EN-US"><o:p></o:p></span></span>
										</p>
								</td>
						</tr>
						<tr style="">
								<td style="width: 105.75pt; padding: 0.75pt;" width="141">
										<p class="MsoNormal" style="text-align: left;" align="left">
												<span style="font-size: 12pt; font-family: SimSun;" lang="EN-US">DATA<o:p></o:p></span>
										</p>
								</td>
								<td style="width: 438.75pt; padding: 0.75pt;" width="585">
										<p class="MsoNormal" style="text-align: left;" align="left">
												<span style="font-size: 12pt; font-family: SimSun;">开始信息写作<span lang="EN-US"><o:p></o:p></span></span>
										</p>
								</td>
						</tr>
						<tr style="">
								<td style="width: 105.75pt; padding: 0.75pt;" width="141">
										<p class="MsoNormal" style="text-align: left;" align="left">
												<span style="font-size: 12pt; font-family: SimSun;" lang="EN-US">EXPN&lt;string&gt;<o:p></o:p></span>
										</p>
								</td>
								<td style="width: 438.75pt; padding: 0.75pt;" width="585">
										<p class="MsoNormal" style="text-align: left;" align="left">
												<span style="font-size: 12pt; font-family: SimSun;">验证给定的邮箱列表是否存在，扩充邮箱列表，也常被禁用<span lang="EN-US"><o:p></o:p></span></span>
										</p>
								</td>
						</tr>
						<tr style="">
								<td style="width: 105.75pt; padding: 0.75pt;" width="141">
										<p class="MsoNormal" style="text-align: left;" align="left">
												<span style="font-size: 12pt; font-family: SimSun;" lang="EN-US">HELO&lt;domain&gt;<o:p></o:p></span>
										</p>
								</td>
								<td style="width: 438.75pt; padding: 0.75pt;" width="585">
										<p class="MsoNormal" style="text-align: left;" align="left">
												<span style="font-size: 12pt; font-family: SimSun;">向服务 器标识用户身份，返回邮件服务器身份<span lang="EN-US"><o:p></o:p></span></span>
										</p>
								</td>
						</tr>
						<tr style="">
								<td style="width: 105.75pt; padding: 0.75pt;" width="141">
										<p class="MsoNormal" style="text-align: left;" align="left">
												<span style="font-size: 12pt; font-family: SimSun;" lang="EN-US">HELP&lt;command&gt;<o:p></o:p></span>
										</p>
								</td>
								<td style="width: 438.75pt; padding: 0.75pt;" width="585">
										<p class="MsoNormal" style="text-align: left;" align="left">
												<span style="font-size: 12pt; font-family: SimSun;">查询服务器支持什么命令，返回命令中的信息<span lang="EN-US"><o:p></o:p></span></span>
										</p>
								</td>
						</tr>
						<tr style="">
								<td style="width: 105.75pt; padding: 0.75pt;" width="141">
										<p class="MsoNormal" style="text-align: left;" align="left">
												<span style="font-size: 12pt; font-family: SimSun;" lang="EN-US">MAIL FROM&lt;host&gt;<o:p></o:p></span>
										</p>
								</td>
								<td style="width: 438.75pt; padding: 0.75pt;" width="585">
										<p class="MsoNormal" style="text-align: left;" align="left">
												<span style="font-size: 12pt; font-family: SimSun;">在主机上初始化一个邮件会 话<span lang="EN-US"><o:p></o:p></span></span>
										</p>
								</td>
						</tr>
						<tr style="">
								<td style="width: 105.75pt; padding: 0.75pt;" width="141">
										<p class="MsoNormal" style="text-align: left;" align="left">
												<span style="font-size: 12pt; font-family: SimSun;" lang="EN-US">NOOP<o:p></o:p></span>
										</p>
								</td>
								<td style="width: 438.75pt; padding: 0.75pt;" width="585">
										<p class="MsoNormal" style="text-align: left;" align="left">
												<span style="font-size: 12pt; font-family: SimSun;">无操作，服务器应响应<span lang="EN-US">OK<o:p></o:p></span></span>
										</p>
								</td>
						</tr>
						<tr style="">
								<td style="width: 105.75pt; padding: 0.75pt;" width="141">
										<p class="MsoNormal" style="text-align: left;" align="left">
												<span style="font-size: 12pt; font-family: SimSun;" lang="EN-US">QUIT<o:p></o:p></span>
										</p>
								</td>
								<td style="width: 438.75pt; padding: 0.75pt;" width="585">
										<p class="MsoNormal" style="text-align: left;" align="left">
												<span style="font-size: 12pt; font-family: SimSun;">终止邮件会话<span lang="EN-US"><o:p></o:p></span></span>
										</p>
								</td>
						</tr>
						<tr style="">
								<td style="width: 105.75pt; padding: 0.75pt;" width="141">
										<p class="MsoNormal" style="text-align: left;" align="left">
												<span style="font-size: 12pt; font-family: SimSun;" lang="EN-US">RCPT TO&lt;user&gt;<o:p></o:p></span>
										</p>
								</td>
								<td style="width: 438.75pt; padding: 0.75pt;" width="585">
										<p class="MsoNormal" style="text-align: left;" align="left">
												<span style="font-size: 12pt; font-family: SimSun;">标识单个的邮件接收人；常在<span lang="EN-US">MAIL</span>命令后面可有多个<span lang="EN-US"> rcpt to</span>：<span lang="EN-US"><o:p></o:p></span></span>
										</p>
								</td>
						</tr>
						<tr style="">
								<td style="width: 105.75pt; padding: 0.75pt;" width="141">
										<p class="MsoNormal" style="text-align: left;" align="left">
												<span style="font-size: 12pt; font-family: SimSun;" lang="EN-US">RSET<o:p></o:p></span>
										</p>
								</td>
								<td style="width: 438.75pt; padding: 0.75pt;" width="585">
										<p class="MsoNormal" style="text-align: left;" align="left">
												<span style="font-size: 12pt; font-family: SimSun;">重置会话，当前传输被取消<span lang="EN-US"><o:p></o:p></span></span>
										</p>
								</td>
						</tr>
						<tr style="">
								<td style="width: 105.75pt; padding: 0.75pt;" width="141">
										<p class="MsoNormal" style="text-align: left;" align="left">
												<span style="font-size: 12pt; font-family: SimSun;" lang="EN-US">SAML FROM&lt;host&gt;<o:p></o:p></span>
										</p>
								</td>
								<td style="width: 438.75pt; padding: 0.75pt;" width="585">
										<p class="MsoNormal" style="text-align: left;" align="left">
												<span style="font-size: 12pt; font-family: SimSun;">发送邮件到用户终端和邮箱<span lang="EN-US"><o:p></o:p></span></span>
										</p>
								</td>
						</tr>
						<tr style="">
								<td style="width: 105.75pt; padding: 0.75pt;" width="141">
										<p class="MsoNormal" style="text-align: left;" align="left">
												<span style="font-size: 12pt; font-family: SimSun;" lang="EN-US">SEND FROM&lt;host&gt;<o:p></o:p></span>
										</p>
								</td>
								<td style="width: 438.75pt; padding: 0.75pt;" width="585">
										<p class="MsoNormal" style="text-align: left;" align="left">
												<span style="font-size: 12pt; font-family: SimSun;">发 送邮件到用户终端<span lang="EN-US"><o:p></o:p></span></span>
										</p>
								</td>
						</tr>
						<tr style="">
								<td style="width: 105.75pt; padding: 0.75pt;" width="141">
										<p class="MsoNormal" style="text-align: left;" align="left">
												<span style="font-size: 12pt; font-family: SimSun;" lang="EN-US">SOML FROM&lt;host&gt;<o:p></o:p></span>
										</p>
								</td>
								<td style="width: 438.75pt; padding: 0.75pt;" width="585">
										<p class="MsoNormal" style="text-align: left;" align="left">
												<span style="font-size: 12pt; font-family: SimSun;">发送邮件到用户终端或邮箱<span lang="EN-US"><o:p></o:p></span></span>
										</p>
								</td>
						</tr>
						<tr style="">
								<td style="width: 105.75pt; padding: 0.75pt;" width="141">
										<p class="MsoNormal" style="text-align: left;" align="left">
												<span style="font-size: 12pt; font-family: SimSun;" lang="EN-US">TURN<o:p></o:p></span>
										</p>
								</td>
								<td style="width: 438.75pt; padding: 0.75pt;" width="585">
										<p class="MsoNormal" style="text-align: left;" align="left">
												<span style="font-size: 12pt; font-family: SimSun;">接收端和发送端交换角色<span lang="EN-US"><o:p></o:p></span></span>
										</p>
								</td>
						</tr>
						<tr style="">
								<td style="width: 105.75pt; padding: 0.75pt;" width="141">
										<p class="MsoNormal" style="text-align: left;" align="left">
												<span style="font-size: 12pt; font-family: SimSun;" lang="EN-US">VRFY&lt;user&gt;<o:p></o:p></span>
										</p>
								</td>
								<td style="width: 438.75pt; padding: 0.75pt;" width="585">
										<p class="MsoNormal" style="text-align: left;" align="left">
												<span style="font-size: 12pt; font-family: SimSun;">用于验证指定的用户<span lang="EN-US">/</span>邮箱是否存在；由于安全方面的原因，服务器常禁止此命令<span lang="EN-US"><o:p></o:p></span></span>
										</p>
								</td>
						</tr>
				</tbody>
		</table>
		<p class="MsoNormal" style="text-align: left;" align="left">
				<b>
						<span style="font-size: 18pt; font-family: SimSun;" lang="EN-US">
								<br />
								<o:p>
								</o:p>
						</span>
				</b>
		</p>
		<p class="MsoNormal" style="text-align: left;" align="left">
				<a name="4">
				</a>
				<b>
						<span style="font-size: 18pt; font-family: SimSun;" lang="EN-US">SMTP </span>
				</b>
				<b>
						<span style="font-size: 18pt; font-family: SimSun;">协议工作原理<span lang="EN-US"><o:p></o:p></span></span>
				</b>
		</p>
		<p class="MsoNormal" style="text-align: left;" align="left">
				<span style="font-size: 12pt; font-family: SimSun;">　　<b><span lang="EN-US">SMTP</span></b>是工作在两种情况下：一是电子邮件从客户机传输到服务器：二是从某一个服务器传输到另一个服务器。<b><span lang="EN-US">SMTP</span></b>也 是个请求<span lang="EN-US">/</span>响应协议，命令和响应都是基于<b><span lang="EN-US">ASCⅡ</span></b>文本，并以<b><span lang="EN-US">CR</span></b>和<b><span lang="EN-US">LF</span></b>符结束。响应包括一个表示返回状态的三 位数字代码。<b><span lang="EN-US">SMTP</span></b>在<b><span lang="EN-US">TCP</span></b>协议<span lang="EN-US">25</span>号端口监听连续请求。<span lang="EN-US"><o:p></o:p></span></span>
		</p>
		<p class="MsoNormal" style="text-align: left;" align="left">
				<span style="font-size: 12pt; font-family: SimSun;">　　<b>连接和发送过程如下：</b><span lang="EN-US"><o:p></o:p></span></span>
		</p>
		<p class="MsoNormal" style="text-align: left;" align="left">
				<span style="font-size: 12pt; font-family: SimSun;">　　（<span lang="EN-US">1</span>）建立<b><span lang="EN-US">TCP</span></b><span lang="EN-US"></span>连接。<span lang="EN-US"><o:p></o:p></span></span>
		</p>
		<p class="MsoNormal" style="text-align: left;" align="left">
				<span style="font-size: 12pt; font-family: SimSun;">　　（<span lang="EN-US">2</span>）客户端发送<b><span lang="EN-US">HELO</span></b>命令以标识发件人自己的身份，然后客户端发送<b><span lang="EN-US">MAIL</span></b>命 令；服务器端正希望以<b><span lang="EN-US">OK</span></b>作为响应，表明准备接收。<span lang="EN-US"><o:p></o:p></span></span>
		</p>
		<p class="MsoNormal" style="text-align: left;" align="left">
				<span style="font-size: 12pt; font-family: SimSun;">　　（<span lang="EN-US">3</span>）客户端发送<b><span lang="EN-US">RCPT</span></b>命令，以标识该电子邮件的计划接收人，可以有多个<b><span lang="EN-US">RCPT</span></b>行； 服务器端则表示是否愿意为收件人接收邮件。<span lang="EN-US"><o:p></o:p></span></span>
		</p>
		<p class="MsoNormal" style="text-align: left;" align="left">
				<span style="font-size: 12pt; font-family: SimSun;">　　（<span lang="EN-US">4</span>）协商结束，发送邮件，用命令<b><span lang="EN-US">DATA</span></b>发送。<span lang="EN-US"><o:p></o:p></span></span>
		</p>
		<p class="MsoNormal" style="text-align: left;" align="left">
				<span style="font-size: 12pt; font-family: SimSun;">　　（<span lang="EN-US">5</span>）以<span lang="EN-US">“<b>.</b>”</span>号表示结束输入内容一起发送出去，结束此次发送，用<b><span lang="EN-US">QUIT</span></b>命 令退出。<span lang="EN-US"><o:p></o:p></span></span>
		</p>
		<p class="MsoNormal" style="text-align: left;" align="left">
				<b>
						<span style="font-size: 18pt; font-family: SimSun;" lang="EN-US">
								<br />
								<o:p>
								</o:p>
						</span>
				</b>
		</p>
		<p class="MsoNormal" style="text-align: left;" align="left">
				<a name="5">
				</a>
				<b>
						<span style="font-size: 18pt; font-family: SimSun;" lang="EN-US">SMTP </span>
				</b>
				<b>
						<span style="font-size: 18pt; font-family: SimSun;">协议的邮件路由过程<span lang="EN-US"><o:p></o:p></span></span>
				</b>
		</p>
		<p class="MsoNormal" style="text-align: left;" align="left">
				<span style="font-size: 12pt; font-family: SimSun;">　　<b><span lang="EN-US">SMTP</span></b>服务器基于域名服务<b><span lang="EN-US">DNS</span></b>中计划收件人的域名来路由电子邮件。<b><span lang="EN-US">SMTP</span></b>服 务器基于<b><span lang="EN-US">DNS</span></b>中的<b><span lang="EN-US">MX</span></b>记录来路由电子邮件，<b><span lang="EN-US">MX</span></b>记录注册了域名和相关的<b><span lang="EN-US">SMTP</span></b>中继主机，属 于该域的电子邮件都应向该主机发送。若<b><span lang="EN-US">SMTP</span></b>服务器<span lang="EN-US"> mail.abc.com </span>收到一封信要发到<b><span lang="EN-US">shuer@sh.abc.com</span></b>， 则执行以下过程：<span lang="EN-US"><o:p></o:p></span></span>
		</p>
		<p class="MsoNormal" style="text-align: left;" align="left">
				<span style="font-size: 12pt; font-family: SimSun;">　　（<span lang="EN-US">1</span>）<b><span lang="EN-US">Sendmail
</span></b>请求<b><span lang="EN-US">DNS</span></b>给出主机<span lang="EN-US"> sh.abc.com</span>的<b><span lang="EN-US">CNAME</span></b><span lang="EN-US"></span>记录，如有，假若<b><span lang="EN-US">CNAME</span></b>（别名记录）到<span lang="EN-US">shmail.abc.com</span>，则再次请求<span lang="EN-US"> shmail.abc.com</span>的<b><span lang="EN-US">CNAME</span></b>记录，直到没有为止。<span lang="EN-US"><o:p></o:p></span></span>
		</p>
		<p class="MsoNormal" style="text-align: left;" align="left">
				<span style="font-size: 12pt; font-family: SimSun;">　　（<span lang="EN-US">2</span>）假定被<b><span lang="EN-US">CNAME</span></b>到<span lang="EN-US">shmail.abc.com</span>，然后<b><span lang="EN-US">sendmail</span></b>请 求<span lang="EN-US">@abc.com </span>域的<b><span lang="EN-US">DNS</span></b>给出<span lang="EN-US">shmail.abc.com</span>的<b><span lang="EN-US">MX</span></b>记录（邮件路由及记录），<span lang="EN-US">shmail MX 5 shmail.abc.com 10 shmail2.abc.com</span>。<span lang="EN-US"><o:p></o:p></span></span>
		</p>
		<p class="MsoNormal" style="text-align: left;" align="left">
				<span style="font-size: 12pt; font-family: SimSun;">　　（<span lang="EN-US">3</span>）<b><span lang="EN-US">Sendmail</span></b>组合请求<b><span lang="EN-US">DNS</span></b>给出<span lang="EN-US"> shmail.abc.com</span>的<span lang="EN-US">A</span>记录（主机名（或域名）对应的<b><span lang="EN-US">IP</span></b>地址记录），即<b><span lang="EN-US">IP</span></b>地址，若返回值为<span lang="EN-US">1.2.3.4</span>（假 设值）。<span lang="EN-US"><o:p></o:p></span></span>
		</p>
		<p class="MsoNormal" style="text-align: left;" align="left">
				<span style="font-size: 12pt; font-family: SimSun;">　　（<span lang="EN-US">4</span>）<b><span lang="EN-US">Sendmail</span></b>与<span lang="EN-US">1.2.3.4</span>连接，传送这封给<span lang="EN-US"> shuser@sh.abc.com </span>的信到<span lang="EN-US">1.2.3.4 </span>这台服务器的<b><span lang="EN-US">SMTP</span></b>后台程序。<span lang="EN-US"><o:p></o:p></span></span>
		</p>
		<p class="MsoNormal" style="text-align: left;" align="left">
				<b>
						<span style="font-size: 18pt; font-family: SimSun;" lang="EN-US">
								<br />
								<o:p>
								</o:p>
						</span>
				</b>
		</p>
		<br />
<img src ="http://www.cnitblog.com/textbox/aggbug/66901.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/textbox/" target="_blank">零度</a> 2010-06-21 13:00 <a href="http://www.cnitblog.com/textbox/archive/2010/06/21/66901.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>pop3 smtp IMAP 搜集的概念</title><link>http://www.cnitblog.com/textbox/archive/2010/06/21/66896.html</link><dc:creator>零度</dc:creator><author>零度</author><pubDate>Mon, 21 Jun 2010 04:02:00 GMT</pubDate><guid>http://www.cnitblog.com/textbox/archive/2010/06/21/66896.html</guid><wfw:comment>http://www.cnitblog.com/textbox/comments/66896.html</wfw:comment><comments>http://www.cnitblog.com/textbox/archive/2010/06/21/66896.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/textbox/comments/commentRss/66896.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/textbox/services/trackbacks/66896.html</trackback:ping><description><![CDATA[
		<div align="center">
				<b>pop3 smtp 资料</b>
				<br />
		</div>
		<pre>
				<b>POP 即为 Post Office Protocol 的简称</b>，<br />是一种电子邮局传输协议，而 POP3 是它的第三个版本，是规定了怎样将个人计算机连接到 Internet 的邮件服务器和下载电子邮件的电子协<br />议。它是 Internet 电子邮件的第一个离线协议标准。简单点说，POP3 就是一个简单而实用的邮件信息传输协议。<br /><br />  POP &amp; POP3：邮局协议（邮局协议第3版） <br />  POP &amp; POP3：Post Office Protocol <br /><br />  POP 协议允许工作站动态访问服务器上的邮件，目前已发展到第三版，称为 POP3。POP3 允许工作站检索邮件服务器上的邮件。POP3 传输<br />的是数据消息，这些消息可以是指令，也可以是应答。创建一个分布式电子邮件系统有多种不同的技术支持和途径：POP（邮局协议）、<br />DMSP（分层式电子邮件系统协议）和 IMAP（因特网信息访问协议）。其中，POP 协议创建最早因此也最为人们了解；DMSP 具有较好的支持<br />“无连接”操作的性能，但其很大程度上仅限于单个应用程序（PCMAIL）；IMAP 提供了 POP 和 DMSP 的扩展集并提供对远程邮件访问的三种<br />支持方式：离线、在线和无连接。   <br /><br />  POP 协议支持“离线”邮件处理。其具体过程是：邮件发送到服务器上，电子邮件客户端调用邮件客户机程序以连接服务器，并下载所有<br />未阅读的电子邮件。这种离线访问模式是一种存储转发服务，将邮件从邮件服务器端送到个人终端机器上，一般是 PC 机或 MAC。一旦邮件<br />发送到 PC 机或 MAC 上，邮件服务器上的邮件将会被删除。   <br /><br />  POP3 并不支持对服务器上邮件进行扩展操作，此过程由更高级的 IMAP4 完成。 POP3 使用 TCP 作为传输协议。<br /></pre>
		<p>POP3 服务是一种检索电子邮件的电子邮件服务。管理员可以使用 POP3 服务存储以及管理邮件服务器上的电子邮件帐户。</p>
		<p>在邮件服务器上安装 POP3 服务后，用户可以使用支持 POP3 协议的电子邮件客户端（如 
Microsoft Outlook）连接到邮件服务器，并将电子邮件检索到本地计算机。POP3 服务与简单邮件传输协议 (SMTP) 
服务一起使用，后者用于发送传出电子邮件。	
<b><br /></b></p>
		<p>
				<b>SMTP：简单邮件传输协议 </b>
				<br />
		</p>
		<p>（SMTP：Simple Mail Transfer Protocol） <br /></p>
		<pre>SMTP 是一种提供可靠且有效电子邮件传输的协议。 SMTP 是建模在 FTP 文件传输服务上的一种邮件服务，主要用于传输系统之间的邮件信息<br />并提供来信有关的通知。<br /><br />SMTP 独立于特定的传输子系统，且只需要可靠有序的数据流信道支持。 SMTP 重要特性之一是其能跨越网络传输邮件，即“ SMTP 邮件中继”<br />。通常，一个网络可以由公用互联网上 TCP 可相互访问的主机、防火墙分隔的 TCP/IP 网络上 TCP 可相互访问的主机，及其它 LAN/WAN <br />中的主机利用非 TCP 传输层协议组成。使用 SMTP ，可实现相同网络上处理机之间的邮件传输，也可通过中继器或网关实现某处理机与其它<br />网络之间的邮件传输。<br /><br />在这种方式下，邮件的发送可能经过从发送端到接收端路径上的大量中间中继器或网关主机。域名服务系统（DNS）的邮件交换服务器可以用<br />来识别出传输邮件的下一跳 IP 地址<br /><br /><br /><b>IMAP和POP有什么区别？</b><br />POP允许电子邮件客户端下载服务器上的邮件，但是您在电子邮件客户端的操作（如：移动邮件、标记已读等），这是不会反馈到服务器上的，<br />比如：您通过电子邮件客户端收取了QQ邮箱中的3封邮件并移动到了其他文件夹，这些移动动作是不会反馈到服务器上的，也就是说，QQ邮箱<br />服务器上的这些邮件是没有同时被移动的 。但是IMAP就不同了，电子邮件客户端的操作都会反馈到服务器上，您对邮件进行的操作<br />（如：移动邮件、标记已读等），服务器上的邮件也会做相应的动作。也就是说，IMAP是“双向”的。同时，IMAP可以只下载邮件的主题，<br />只有当您真正需要的时候，才会下载邮件的所有内容<br /><br /><br /><b>　Smtp工作机制   </b></pre>
		<p>　　SMTP通常有两种工作模式：发送SMTP和接收SMTP。具体工作方式为：发送SMTP在接到
用户的邮件请求后，判断此邮件是否为本地邮件，若是直接投送到用户的邮箱，否则向dns查询远端邮件服务器的MX纪录，并建立与远端接收SMTP之间的一
个双向传送通道，此后SMTP命令由发送SMTP发出，由接收SMTP接收，而应答则反方面传送。一旦传送通道建立，SMTP发送者发送MAIL命令指明
邮件发送者。如果SMTP接收者可以接收邮件则返回OK应答。SMTP发送者再发出RCPT命令确认邮件是否接收到。如果SMTP接收者接收，则返回OK
应答；如果不能接收到，则发出拒绝接收应答（但不中止整个邮件操作），双方将如此重复多次。当接收者收到全部邮件后会接收到特别的序列，如果接收者成功处
理了邮件，则返回OK应答。</p>
		<p>
				<br />
		</p>
		<h2>POP3 服务概述</h2>
		<p>POP3 服务是一种检索电子邮件的电子邮件服务。管理员可以使用 POP3 
服务存储以及管理邮件服务器上的电子邮件帐户。</p>
		<p>在邮件服务器上安装 POP3 服务后，用户可以使用支持 POP3 协议的电子邮件客户端（如 
Microsoft Outlook）连接到邮件服务器，并将电子邮件检索到本地计算机。POP3 服务与简单邮件传输协议 (SMTP) 
服务一起使用，后者用于发送传出电子邮件。</p>
		<h2>电子邮件的传输与检索概述</h2>
		<div>
				<img alt="" src="http://www.fileden.com/files/2009/4/20/2411766/other/POP3_emc_001c.gif" width="395" border="0" height="210" />
		</div>
		<p>该图表阐释了电子邮件是如何从发件人传送到收件人，以及如何检索到收件人的本地计算机上。</p>
		<p>发件人的客户端计算机通过 Internet 服务提供商 (ISP) 连接到 
Internet。发件人使用电子邮件客户端发送电子邮件。根据 SMTP 协议，电子邮件被提取，再传送到发件人的 ISP，然后由该 ISP 路由到
 Internet 上。</p>
		<p>电子邮件在 Internet 
上，经过许多中间服务器中继，才传送到收件人。当电子邮件到达收件人的 ISP 时，就被放入收件人的邮箱。</p>
		<p>当收件人的计算机连接到他的 ISP 时，根据 POP3 协议，电子邮件就从该 ISP 
传送到收件人本地计算机的电子邮件客户端上。POP3 服务是一种允许用户从邮件服务器检索电子邮件的机制。</p>
		<p>
				<br />
		</p>
		<pre>
				<br />
		</pre>
<img src ="http://www.cnitblog.com/textbox/aggbug/66896.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/textbox/" target="_blank">零度</a> 2010-06-21 12:02 <a href="http://www.cnitblog.com/textbox/archive/2010/06/21/66896.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>名词杂概念(基础)-不断更新</title><link>http://www.cnitblog.com/textbox/archive/2010/04/06/65104.html</link><dc:creator>零度</dc:creator><author>零度</author><pubDate>Tue, 06 Apr 2010 01:43:00 GMT</pubDate><guid>http://www.cnitblog.com/textbox/archive/2010/04/06/65104.html</guid><wfw:comment>http://www.cnitblog.com/textbox/comments/65104.html</wfw:comment><comments>http://www.cnitblog.com/textbox/archive/2010/04/06/65104.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/textbox/comments/commentRss/65104.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/textbox/services/trackbacks/65104.html</trackback:ping><description><![CDATA[
		<br />
		<b>1、Nanomites Processing</b>
		<br />
　　Nanomites是Armadillo嵌入子进程的INT
3中断，虽然在GETRIGHT FINAL版本里没有使用nanomites 保护，但是却在CRUSADER写的教程里的beta版本里用了。
可能有 50， 100甚至 200个INT 3，它们被放入了子进程的第一个section ，以阻止子进程脱离父进程运行。INT
3中断替代了原始文件的条件跳转。所以每当父进程接收到INT
3中断，它就到存放跳转类型的report中去，看一下标志以决定是否跳转，然后测算出新的EIP，改变到子进程中去然后继续运行直到下一个 INT
3。<br />
　　问题是我们不知道每个跳转和INT 3的对应关系，所以我们将要在本篇教程中学习如何patch它。 首先我们要学如何手动patch它，然后(在第二篇教程中) 我们将要学习如何让计算机自动逐行patch它。<br /><b>2、输入表乱序</b><br />
　　Import Table Elimination一般是把输入表放在壳申请的内存处并且乱序处理。<br />
　　对于输入表乱序，以前有两种解法：①、写代码重新排序；②、直接用ImportRec“创建新的IAT”功能来构造新的输入表。<br /><b>3、代码拼接</b><br />
　　Armadillo会把程序中的部分代码挪移到壳申请的内存段运行，普通dump会导致此部分代码丢失，可以使用ArmInline工具来修复这部分代码<br /><b>4、内存校验</b><br />
　　内存补丁保护可以防止攻击者使用Loader改变更程序的代码。付费版本的内存保护将会比Demo版更强大。如果您使用此选项，您必须使用CopyMem-II或Debug-Block，否则本项保护将无法启用。 <br />
　　使用内存保护时应注意，不要在程序里添加自修改代码，否则程序将会自动退出。<br /><b>5.</b><b>CopyMemII保护<br /><br />6.SEH </b>(windows 结构化异常处理) 操作系统处理异常的方案<b><br /> </b>异常处理程序的返回值<b><br />  </b>EXCEPTION_EXECUTE_HANDLER                  equ 1     表示我已经处理了异常,可以优雅地结束了 <br />  EXCEPTION_CONTINUE_SEARCH                  equ 0     表示我不处理,其他人来吧,于是windows调用默认的处理程序显示一个错误框,并结束 <br /> 
        EXCEPTION_CONTINUE_EXECUTION           equ -1  表示错误已经被修复,请从异常发生处继续执行 <br /><b><br />7.PE结构 </b>(Portable Executable File Format)可移植的执行体 即 Windows的可执行文件格式<br /><b><br />8.OEP </b>(Original Entry Point) 即程序加壳前的真正的入口点<br /><b><br />9.PELoader </b>(把PE格式的文件加载到内存并跳到OEP执行)<b><br /><br />10.Blowfish、Twofish、TEA </b> 加密算法<b><br /><br />11.</b><b>KPCR</b><br />   (Kernel's Processor Control Region,内核进程控制区域）是一个不会随WINDOWS版本变动而改变的固定结构体，在它的末尾（偏移0x120）指向<br /><b>      KPRCB</b>结构。KPRCB同样是一个不会随WINDOWS版本变动而改变的固定结构体。它包含有指向当前<b>KTHREAD</b>的指针（偏移值0x004）。<br /><b>      ETHREAD</b>的第一项是KTHREAD，也就知道了当前的ETHREAD基地址。KTHREAD中的_KAPC_STATE结构包含当前<b>KPROCESS</b>的地址每个进程<br />   都有一个EPROCESS结构，里面保存着进程的各种信息，和相关结构的指针。<b>EPROCESS</b>结构位于系统地址空间，所以访问这个结构需要有ring0<br />   的权限。EPROCESS的第一项是KPROCESS<br /><b>12.CreateProcess</b><br />     CreateProcess创建进程的大致步骤：<br />     1.打开可执行文件[.exe]，以FILE_EXECUTE存取方式打开。<br />     2.把可执行映像装载进RAM。<br />     2.创建进程内核对象(EPROCESS，KPROCESS和PEB结构)。<br />     4.为该新建进程分配地址空间。<br />     3.在该进程中创建主线程的线程执行对象(ETHREAD，KTHREAD和TEB结构)，为主线程分配堆栈，建立该进程主线程的执行上下文。<br />     4.Kernel32.dll通知Win32子系统已经创建了一个新进程。<br />     5.如果标志不是CREATE_ SUSPENDED，那么就开始执行进程中的线程     <br />     6.在进程和线程的context里，完成地址空间的初始化（比如，加载需要的DLL），开始执行程序<br /><b>13.PE 格式中的 SectionAlignment 与 FileAlignment <br />     </b>这两个值可以在PE文件IMAGE_NT_HEADER结构体所包含的iamge_optional_header结构体中找到。
FileAlignment指的是二进制文件中，<br />     数据对齐时采用的大小。一般是一个扇区的倍数（扇区大小一般为200h也就是512bytes），这样便
于更快的从硬盘中读取数据。而<br />     SectionAlignment主要指的是PE文件被映射到内存后，其section被映射到进程空间时所采用的数据对齐
的大小。一般就是一个页大小的倍<br />     数（通常为1000h）。这个也是为了更快的进行数据交换，便于内存管理。FileAlignment和硬盘的扇区相
关，SectionAlignment和内存的页<br />     相关,一个是存放在硬盘列文件数据对齐,一个是存放在内存里的数据对齐.<br />14.<b>PEB<em></em>Process Environment Block <em>, </em><em>进程</em></b><b><em><em></em></em>环境块     </b><br />      FS段寄存器指向当前的TEB结构，在TEB偏移0x30处是PEB指针，通过这个指针即可取得PEB的地址<br />      具体用法结构参考: <a title="具体用法结构参考" href="http://www.anqn.com/jiamijiemi/jichuzhishi/2009-01-12/a09105367.shtml">http://www.anqn.com/jiamijiemi/jichuzhishi/2009-01-12/a09105367.shtml</a><br />15.<b>Opcode </b><br />16.<b>VM 虚拟机保护壳.</b> 原理:模仿opcode的运行机制并参合代码加密,代码乱序,代码变形,各种Anti. 如 themida ,vmp 等<br />17.<b>TLS:</b>Thread Local 
Storage 线程局部存储TLS. 堆栈中定义的局部变量，对多线程是安全的，因为不同的线程有自己的堆栈<br />18.<b>CRC 校验值</b> 类似求商的余数原理那样,CRC是求XOR的余数就是CRC值<br />         11110         --&gt; 30<br />         1001  xor    --&gt; 
9<br />         ---------<br />          1100          --&gt; 12    <br />          1001  xor   --&gt; 9<br />          --------<br />           101           --&gt; 3，余数 --&gt; the CRC!19. i<b>nt 2E</b> 指令是未公开指令，eax 中存放函数号，EDX中存放函数地址<br />      作用:1.可以用来 进入 ntoskrnl.exe调用naked API<br />               2.他是从用户模式进入内核模式的main gate。<br />      eax 中存放函数号作为查找表中的索引，去找到最终的目标函数。这个表就是系统服务表SST<br />      详细参考 <a href="http://bbs.pediy.com/showthread.php?threadid=24555">http://bbs.pediy.com/showthread.php?threadid=24555</a><br />20. SST 系统服务表<br /><br /><br /><img src ="http://www.cnitblog.com/textbox/aggbug/65104.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/textbox/" target="_blank">零度</a> 2010-04-06 09:43 <a href="http://www.cnitblog.com/textbox/archive/2010/04/06/65104.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>函數調用方式： stdcall cdecl fastcall WINAPI CALLBACK PASCAL thiscall  fortran syscall declspec(naked)</title><link>http://www.cnitblog.com/textbox/archive/2010/03/10/64575.html</link><dc:creator>零度</dc:creator><author>零度</author><pubDate>Wed, 10 Mar 2010 03:53:00 GMT</pubDate><guid>http://www.cnitblog.com/textbox/archive/2010/03/10/64575.html</guid><wfw:comment>http://www.cnitblog.com/textbox/comments/64575.html</wfw:comment><comments>http://www.cnitblog.com/textbox/archive/2010/03/10/64575.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/textbox/comments/commentRss/64575.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/textbox/services/trackbacks/64575.html</trackback:ping><description><![CDATA[
		<br />        现代的编程语言的函数竟然有那麽多的调用方式。这些东西要完全理解还得通过汇编代码才好理解。他们各自有自己的特点<br />其实这些调用方式的差别在主要在一下几个方面<br /><br />1.参数处理方式（<b>传递顺序，存取(利用盏还是寄存器)</b>）<br />2.函数的结尾处理方式（<b>善后处理 如:栈的恢复由谁恢复? 函数内恢复/还是调用后恢复</b>）<br /><br /><br /><br />以下是理论：<br /><pre>__cdecl    由调用者平栈，参数从右到左依次入栈 是C和C＋＋程序的缺省调用方式。<b>每一个调用它的函数都包含清空堆栈的代码</b>，<br />           所以产生的可执行文件大小会比调用_stdcall函数的大。函数采用从右到左的压栈方式。VC将函数编译后会在函数名前面加上<br />           下划线前缀。是MFC缺省调用约定<br />__stdcall ，WINAPI，CALLBACK ，PASCAL    由被调用者平栈，参数从右到左依次入栈 ._stdcall是Pascal程序的缺省调用方式，<br />           通常用于Win32   Api中，函数采用从右到左的压栈方式，<b>自己在退出时清空堆栈</b>。VC将函数编译后会在函数名前面加上下划<br />           线前缀，在函数名后加上"@"和参数的字节数<br /><br />__fastcall 由被调用者平栈，参数先赋值给寄存器，然后入栈  “人”如其名，它的主要特点就是快，因为它是通过寄存器来传送参数的<br />          （实际上，它<b>用ECX和EDX传送前两个双字（DWORD）或更小的参数</b>，剩下的参数仍旧自右向左压栈传送，被调用的函数在返回前<br />          清理传送参数的内存栈），在函数名修饰约定方面，它和前两者均不同.<br />          _fastcall方式的函数采用寄存器传递参数，VC将函数编译后会在函数名前面加上"@"前缀，在函数名后加上"@"和参数的字节数。  <br /><br />__thiscall 由被调用者平栈，参数入栈，this 指针赋给 ecx 寄存器 仅仅应用于“C++”成员函数。this指针存放于CX寄存器，参数从右<br />           到左压。thiscall不是关键词，因此不能被程序员指定。   <br /><br /><br /><span style="color: rgb(0, 0, 0);">__declspec(naked) </span><span style="font-size: 12pt; font-family: 宋体;">这是一个很少见的调用约定，一般程序设计者建议不要使用。<b>编译器不会给这种函数增加初始化和清理代码</b>，<br />          更特殊的是，你不能用<span lang="EN-US">return</span>返回返回值，只能用插入汇编返回结果。这一般用于实模式驱动程序设计.<br /></span></pre>以下是实践：<br /><br /><font face="宋体" size="2"><font face="宋体" size="2"></font></font> 
<br /><div style="border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; background-color: rgb(238, 238, 238); font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: rgb(0, 0, 255);">int</span><span style="color: rgb(0, 0, 0);"> __stdcall test_stdcall(</span><span style="color: rgb(0, 0, 255);">char</span><span style="color: rgb(0, 0, 0);"> para1, </span><span style="color: rgb(0, 0, 255);">char</span><span style="color: rgb(0, 0, 0);"> para2)<br />{<br />    para1 </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> para2;<br />    </span><span style="color: rgb(0, 0, 255);">return</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">0</span><span style="color: rgb(0, 0, 0);">;<br />}<br /></span><span style="color: rgb(0, 0, 255);">int</span><span style="color: rgb(0, 0, 0);"> __cdecl test_cdecl(</span><span style="color: rgb(0, 0, 255);">char</span><span style="color: rgb(0, 0, 0);"> para, <img src="http://www.cnitblog.com/images/dot.gif" />)<br />{<br />    </span><span style="color: rgb(0, 0, 255);">char</span><span style="color: rgb(0, 0, 0);">    p </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);">\n</span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);">;<br />    va_list marker;<br />    va_start( marker, para );<br />    </span><span style="color: rgb(0, 0, 255);">while</span><span style="color: rgb(0, 0, 0);">( p </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);">\0</span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);"> )<br />    {<br />        p </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> va_arg( marker, </span><span style="color: rgb(0, 0, 255);">char</span><span style="color: rgb(0, 0, 0);">);<br />        printf(</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">%c\n</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">, p);<br />    }<br />    va_end( marker );<br />    </span><span style="color: rgb(0, 0, 255);">return</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">0</span><span style="color: rgb(0, 0, 0);">;<br />}<br /><br /></span><span style="color: rgb(0, 0, 255);">int</span><span style="color: rgb(0, 0, 0);"> pascal test_pascal(</span><span style="color: rgb(0, 0, 255);">char</span><span style="color: rgb(0, 0, 0);"> para1, </span><span style="color: rgb(0, 0, 255);">char</span><span style="color: rgb(0, 0, 0);"> para2)<br />{<br />    </span><span style="color: rgb(0, 0, 255);">return</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">0</span><span style="color: rgb(0, 0, 0);">;<br />}<br /><br /></span><span style="color: rgb(0, 0, 255);">int</span><span style="color: rgb(0, 0, 0);"> __fastcall test_fastcall(</span><span style="color: rgb(0, 0, 255);">char</span><span style="color: rgb(0, 0, 0);"> para1, </span><span style="color: rgb(0, 0, 255);">char</span><span style="color: rgb(0, 0, 0);"> para2, </span><span style="color: rgb(0, 0, 255);">char</span><span style="color: rgb(0, 0, 0);"> para3, </span><span style="color: rgb(0, 0, 255);">char</span><span style="color: rgb(0, 0, 0);"> para4)<br />{<br />    para1 </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> (</span><span style="color: rgb(0, 0, 255);">char</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);">;<br />    para2 </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> (</span><span style="color: rgb(0, 0, 255);">char</span><span style="color: rgb(0, 0, 0);">)</span><span style="color: rgb(0, 0, 0);">2</span><span style="color: rgb(0, 0, 0);">;<br />    para3 </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> (</span><span style="color: rgb(0, 0, 255);">char</span><span style="color: rgb(0, 0, 0);">)</span><span style="color: rgb(0, 0, 0);">3</span><span style="color: rgb(0, 0, 0);">;<br />    para4 </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> (</span><span style="color: rgb(0, 0, 255);">char</span><span style="color: rgb(0, 0, 0);">)</span><span style="color: rgb(0, 0, 0);">4</span><span style="color: rgb(0, 0, 0);">;<br />    </span><span style="color: rgb(0, 0, 255);">return</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">0</span><span style="color: rgb(0, 0, 0);">;<br />}<br />__declspec(naked) </span><span style="color: rgb(0, 0, 255);">void</span><span style="color: rgb(0, 0, 0);"> __stdcall test_naked(</span><span style="color: rgb(0, 0, 255);">char</span><span style="color: rgb(0, 0, 0);"> para1, </span><span style="color: rgb(0, 0, 255);">char</span><span style="color: rgb(0, 0, 0);"> para2)<br />{<br />    __asm<br />    {<br />        push    ebp<br />        mov     ebp, esp<br />        push    eax<br />        mov     al,</span><span style="color: rgb(0, 0, 255);">byte</span><span style="color: rgb(0, 0, 0);"> ptr [ebp </span><span style="color: rgb(0, 0, 0);">+</span><span style="color: rgb(0, 0, 0);"> 0Ch]<br />        xchg    </span><span style="color: rgb(0, 0, 255);">byte</span><span style="color: rgb(0, 0, 0);"> ptr [ebp </span><span style="color: rgb(0, 0, 0);">+</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">8</span><span style="color: rgb(0, 0, 0);">],al      <br />        pop     eax<br />        pop     ebp<br />        ret     </span><span style="color: rgb(0, 0, 0);">8</span><span style="color: rgb(0, 0, 0);"><br />    }<br /></span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);">    return ;</span><span style="color: rgb(0, 128, 0);"></span><span style="color: rgb(0, 0, 0);"><br />}<br /><br /><br /></span><span style="color: rgb(0, 0, 255);">int</span><span style="color: rgb(0, 0, 0);"> main(</span><span style="color: rgb(0, 0, 255);">int</span><span style="color: rgb(0, 0, 0);"> argc, </span><span style="color: rgb(0, 0, 255);">char</span><span style="color: rgb(0, 0, 0);">*</span><span style="color: rgb(0, 0, 0);"> argv[])<br />{<br />    test_stdcall( </span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);">a</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);">b</span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);"> );<br />    test_cdecl( </span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);">c</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);">d</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);">e</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);">f</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);">g</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);">h</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);">\0</span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);">);<br />    test_pascal( </span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);">e</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);">f</span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);"> );<br />    test_fastcall( </span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);">g</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);">h</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);">i</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);">j</span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);"> );<br />    test_naked( </span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);">k</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);">l</span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);">);<br />    </span><span style="color: rgb(0, 0, 255);">return</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">0</span><span style="color: rgb(0, 0, 0);">;<br />}</span></div>汇编代码如下<br /><div style="border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; background-color: rgb(238, 238, 238); font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: rgb(0, 0, 255);">int</span><span style="color: rgb(0, 0, 0);"> main(</span><span style="color: rgb(0, 0, 255);">int</span><span style="color: rgb(0, 0, 0);"> argc, </span><span style="color: rgb(0, 0, 255);">char</span><span style="color: rgb(0, 0, 0);">*</span><span style="color: rgb(0, 0, 0);"> argv[])<br />{<br /></span><span style="color: rgb(0, 0, 0);">00411350</span><span style="color: rgb(0, 0, 0);">  push        ebp  <br /></span><span style="color: rgb(0, 0, 0);">00411351</span><span style="color: rgb(0, 0, 0);">  mov         ebp,esp <br /></span><span style="color: rgb(0, 0, 0);">00411353</span><span style="color: rgb(0, 0, 0);">  sub         esp,0C0h <br /></span><span style="color: rgb(0, 0, 0);">00411359</span><span style="color: rgb(0, 0, 0);">  push        ebx  <br />0041135A  push        esi  <br />0041135B  push        edi  <br />0041135C  lea         edi,[ebp</span><span style="color: rgb(0, 0, 0);">-</span><span style="color: rgb(0, 0, 0);">0C0h] <br /></span><span style="color: rgb(0, 0, 0);">00411362</span><span style="color: rgb(0, 0, 0);">  mov         ecx,30h <br /></span><span style="color: rgb(0, 0, 0);">00411367</span><span style="color: rgb(0, 0, 0);">  mov         eax,0CCCCCCCCh <br />0041136C  rep stos    dword ptr es:[edi] <br />    test_stdcall( </span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);">a</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);">b</span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);"> );<br /><b><font color="#000000">0041136E  push        62h  <br /></font></b></span><b><font color="#000000"><span style="color: rgb(0, 0, 0);">00411370</span><span style="color: rgb(0, 0, 0);">  push        61h  <br /></span><span style="color: rgb(0, 0, 0);">00411372</span><span style="color: rgb(0, 0, 0);">  call        </span></font><font color="#000000"><span style="color: rgb(0, 0, 0);">_test_stdcall@</span><span style="color: rgb(0, 0, 0);">8</span></font><span style="color: rgb(0, 0, 0);"></span></b><span style="color: rgb(0, 0, 0);"><b><font color="#000000"></font></b><br />    test_cdecl( </span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);">c</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);">d</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);">e</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);">f</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);">g</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);">h</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);">\0</span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);">);<br /></span><b><span style="color: rgb(0, 0, 0);">00411377</span><span style="color: rgb(0, 0, 0);">  push        </span><span style="color: rgb(0, 0, 0);">0</span><span style="color: rgb(0, 0, 0);">    <br /></span><span style="color: rgb(0, 0, 0);">00411379</span><span style="color: rgb(0, 0, 0);">  push        68h  <br />0041137B  push        67h  <br />0041137D  push        66h  <br />0041137F  push        65h  <br /></span><span style="color: rgb(0, 0, 0);">00411381</span><span style="color: rgb(0, 0, 0);">  push        64h  <br /></span><span style="color: rgb(0, 0, 0);">00411383</span><span style="color: rgb(0, 0, 0);">  push        63h  <br /></span><span style="color: rgb(0, 0, 0);">00411385</span><span style="color: rgb(0, 0, 0);">  call        </span><span style="color: rgb(0, 0, 0);">_test_cdecl</span></b><span style="color: rgb(0, 0, 0);"><br /><font color="#ff0000"><b>0041138A  add         esp,1Ch </b></font></span><font color="#ff0000"><b><font color="#ff0000"><span style="color: rgb(0, 128, 0);">;恢复</span></font><span style="color: rgb(0, 0, 0);"></span><span style="color: rgb(0, 0, 0);">_te</span></b><b><span style="color: rgb(0, 0, 0);">st_cdecl</span><span style="color: rgb(0, 0, 0);">参数压入前的堆栈指令是: </span><span style="color: rgb(0, 0, 0);">add esp,n*4 </span>n=参数的数量</b></font><br /><span style="color: rgb(0, 0, 0);">    test_fastcall( </span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);">g</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);">h</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);">i</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);">j</span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);"> );<br /><b>0041138D  push        6Ah  <br />0041138F  push        69h  <br /></b></span><b><span style="color: rgb(0, 0, 0);">00411391</span><span style="color: rgb(0, 0, 0);">  mov         dl,68h <br /></span><span style="color: rgb(0, 0, 0);">00411393</span><span style="color: rgb(0, 0, 0);">  mov         cl,67h <br /></span><span style="color: rgb(0, 0, 0);">00411395</span><span style="color: rgb(0, 0, 0);">  call        </span><span style="color: rgb(0, 0, 0);">test_fastcall</span></b><span style="color: rgb(0, 0, 0);"><br />    test_naked( </span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);">k</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);">l</span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);">);<br /><b>0041139A  push        6Ch  <br />0041139C  push        6Bh  <br />0041139E  call        </b></span><b><span style="color: rgb(0, 0, 0);">_test_naked</span></b><span style="color: rgb(0, 0, 0);"><br />    </span><span style="color: rgb(0, 0, 255);">return</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">0</span><span style="color: rgb(0, 0, 0);">;<br />004113A3  xor         eax,eax <br />}<br /><br />int __stdcall test_stdcall(char para1, char para2)<br />{<br />004111F0  push        ebp  <br />004111F1  mov         ebp,esp <br />004111F3  sub         esp,0C0h <br />004111F9  push        ebx  <br />004111FA  push        esi  <br />004111FB  push        edi  <br />004111FC  lea         edi,[ebp-0C0h] <br />00411202  mov         ecx,30h <br />00411207  mov         eax,0CCCCCCCCh <br />0041120C  rep stos    dword ptr es:[edi] ;初始edi<br />    para1 = para2;<br /><font color="#ff0000"><b>0041120E  mov         al,byte ptr [para2] ;mov al,byte ptr[ebp+c]<br />00411211  mov         byte ptr [para1],al ;mov byte ptr[ebp+8],al</b></font><br />    return 0;<br />00411214  xor         eax,eax<br />00411216  pop         edi  <br />00411217  pop         esi  <br />00411218  pop         ebx  <br />00411219  mov         esp,ebp <br />0041121B  pop         ebp  <br /><font color="#ff0000"><b>0041121C ret      8 ;恢复到压入函数参数前堆栈,由于有两个参数所以ret 8 相当于 pop eip 然后esp+8</b></font><br />}<br />int __cdecl test_cdecl(char para,... )<br />{<br />00411230  push        ebp  <br />00411231  mov         ebp,esp <br />00411233  sub         esp,0D8h <br />0041123C  lea         edi,[ebp-0D8h] <br />00411242  mov         ecx,36h <br />00411247  mov         eax,0CCCCCCCCh <br />0041124C  rep stos    dword ptr es:[edi] <br />    char    p = '\n';<br />0041124E  mov         byte ptr [p],0Ah <br />    va_list marker;<br />    va_start( marker, para );<br />00411252  lea         eax,[ebp+0Ch] <br />00411255  mov         dword ptr [marker],eax <br />    while( p != '\0' )<br />00411258  movsx       eax,byte ptr [p] <br />0041125C  test        eax,eax <br />0041125E  je          test_cdecl+60h (411290h) <br />    {<br />        p = va_arg( marker, char);<br />00411260  mov         eax,dword ptr [marker] <br />00411263  add         eax,4 <br />00411266  mov         dword ptr [marker],eax <br />00411269  mov         ecx,dword ptr [marker] <br />0041126C  mov         dl,byte ptr [ecx-4] <br />0041126F  mov         byte ptr [p],dl <br />        printf("%c\n", p);<br />00411272  movsx       eax,byte ptr [p] <br />00411276  mov         esi,esp <br />00411278  push        eax  <br />00411279  push        offset string "%c\n" (41401Ch) <br />0041127E  call        dword ptr [__imp__printf (416180h)] <br />00411284  add         esp,8 <br />0041128E  jmp         test_cdecl+28h (411258h) <br /></span><span style="color: rgb(0, 0, 0);">    }</span><br /><span style="color: rgb(0, 0, 0);">    va_end( marker );<br />00411290  mov         dword ptr [marker],0 <br />    return 0;<br />00411297  xor         eax,eax </span><span style="color: rgb(0, 0, 0);"><br />
004112A9  mov         esp,ebp <br />
004112AB  pop         ebp  <br />
004112AC  ret    </span><br /><span style="color: rgb(0, 0, 0);">}<br />     <br />int __fastcall test_fastcall(char para1, char para2, char para3, char para4)<br />{<br />004112D0  push        ebp  <br />004112D1  mov         ebp,esp <br />004112D3  sub         esp,0D8h  <br />004112DD  lea         edi,[ebp-0D8h] <br />004112E3  mov         ecx,36h <br />004112E8  mov         eax,0CCCCCCCCh <br />004112ED  rep stos    dword ptr es:[edi] <br />004112EF  pop         ecx  <br />004112F0  mov         byte ptr [ebp-14h],dl <br />004112F3  mov         byte ptr [ebp-8],cl <br />    para1 = (char)1;<br />004112F6  mov         byte ptr [para1],1 <br />    para2 = (char)2;<br />004112FA  mov         byte ptr [para2],2 <br />    para3 = (char)3;<br />004112FE  mov         byte ptr [para3],3 <br />    para4 = (char)4;<br />00411302  mov         byte ptr [para4],4 <br />    return 0;<br />00411306  xor         eax,eax  </span><span style="color: rgb(0, 0, 0);"><br />
0041130B  mov         esp,ebp <br />
0041130D  pop         ebp  <br />
0041130E  ret         8  </span><b>;由于使用了ecx ,edx 传递参数 本来4个参数只使用两push 所以这里是 ret 4*2</b><br /><span style="color: rgb(0, 0, 0);">}<br />     <br /><br />__declspec(naked) void __stdcall test_naked(char para1, char para2)<br />{<br />00411330  push        ebp      ;<b>这里编译器没加入任何初始化和清栈的指令,你代码如何写它就复制过来</b><br />00411331  mov         ebp,esp <br />00411333  push        eax  <br />00411334  mov         al,byte ptr [para2]    <br />00411337  xchg        al,byte ptr [para1] <br />0041133A  pop         eax  <br />0041133B  pop         ebp  <br />0041133C  ret         8  <br />} <br /></span></div><br /><img src ="http://www.cnitblog.com/textbox/aggbug/64575.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/textbox/" target="_blank">零度</a> 2010-03-10 11:53 <a href="http://www.cnitblog.com/textbox/archive/2010/03/10/64575.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>BI 概念问题，困扰了几天终于有了更深刻的认识了。</title><link>http://www.cnitblog.com/textbox/archive/2009/11/30/62904.html</link><dc:creator>零度</dc:creator><author>零度</author><pubDate>Mon, 30 Nov 2009 03:20:00 GMT</pubDate><guid>http://www.cnitblog.com/textbox/archive/2009/11/30/62904.html</guid><wfw:comment>http://www.cnitblog.com/textbox/comments/62904.html</wfw:comment><comments>http://www.cnitblog.com/textbox/archive/2009/11/30/62904.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/textbox/comments/commentRss/62904.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/textbox/services/trackbacks/62904.html</trackback:ping><description><![CDATA[
		<br />BI前端报表工具：连接后台数据仓库的工具，并能分割分析数据并能做出相应的报表。<br />后台数据仓库工具SSAS：连接后台数据库（erp的数据库）提取数据并做出数据仓库。<br /><br />维度表 ：数据仓库里的重要元素 ， 其实就是交叉表的行和列 <br />实体表 ：数据仓库里的重要元素，其实就是交叉表的数据<br /><br />总结：从不同的维度（角度）去分析实体（数据）。 找切入点，根据客户的观察点来划分什么是维度，什么是实体。<br /><br /><br /><img src ="http://www.cnitblog.com/textbox/aggbug/62904.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/textbox/" target="_blank">零度</a> 2009-11-30 11:20 <a href="http://www.cnitblog.com/textbox/archive/2009/11/30/62904.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>