﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>BlogJava-SIMONE</title><link>http://www.blogjava.net/wangxinsh55/</link><description /><language>zh-cn</language><lastBuildDate>Mon, 06 Oct 2008 16:32:00 GMT</lastBuildDate><pubDate>Mon, 06 Oct 2008 16:32:00 GMT</pubDate><ttl>60</ttl><item><title>FreeMarker概述</title><link>http://www.blogjava.net/wangxinsh55/archive/2008/08/26/224559.html</link><dc:creator>SIMONE</dc:creator><author>SIMONE</author><pubDate>Tue, 26 Aug 2008 13:11:00 GMT</pubDate><guid>http://www.blogjava.net/wangxinsh55/archive/2008/08/26/224559.html</guid><wfw:comment>http://www.blogjava.net/wangxinsh55/comments/224559.html</wfw:comment><comments>http://www.blogjava.net/wangxinsh55/archive/2008/08/26/224559.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/wangxinsh55/comments/commentRss/224559.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/wangxinsh55/services/trackbacks/224559.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: l&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; FreeMarker是一个模板引擎，一个基于模板生成文本输出的通用工具，使用纯Java编写                                                                        l&nbsp;&nbsp;&nbsp;&nbsp;&n...&nbsp;&nbsp;<a href='http://www.blogjava.net/wangxinsh55/archive/2008/08/26/224559.html'>阅读全文</a><img src ="http://www.blogjava.net/wangxinsh55/aggbug/224559.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/wangxinsh55/" target="_blank">SIMONE</a> 2008-08-26 21:11 <a href="http://www.blogjava.net/wangxinsh55/archive/2008/08/26/224559.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>在hibernate中实现oracle的自动增长[转]</title><link>http://www.blogjava.net/wangxinsh55/archive/2008/08/19/222956.html</link><dc:creator>SIMONE</dc:creator><author>SIMONE</author><pubDate>Tue, 19 Aug 2008 03:43:00 GMT</pubDate><guid>http://www.blogjava.net/wangxinsh55/archive/2008/08/19/222956.html</guid><wfw:comment>http://www.blogjava.net/wangxinsh55/comments/222956.html</wfw:comment><comments>http://www.blogjava.net/wangxinsh55/archive/2008/08/19/222956.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/wangxinsh55/comments/commentRss/222956.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/wangxinsh55/services/trackbacks/222956.html</trackback:ping><description><![CDATA[<p><span style="font-size: 12pt;"><span style="font-family: 宋体;"><span style="font-size: 8pt;"><span style="font-size: 10pt;">在hibernate中实现oracle的自动增长 <br />
<br />
http://kuangbaoxu.javaeye.com/blog/192434<br />
<br />
关键字: hibernate oracle sequence native <br />
根据hibernate的文档，有两种方式实现实体对象的主键自动增长。 <br />
第一种：设置ID的增长策略是sequence，同时指定sequence的名字，最好每个表建一个sequence，此种做法就如同MS-SQL,MY-SQL中的自动增长一样，不需要创建触发器，具体的oracle数据库脚本及hibernate配置文件如下： <br />
<br />
<br />
[1]oracle数据表的创建脚本： <br />
Java代码</span></span></span></span></p>
<span style="font-size: 12pt;"><span style="font-family: 宋体;"><span style="font-size: 8pt;"><span style="font-size: 10pt;">CREATE TABLE DEPARTMENT (&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; ID NUMBER(19,0) DEFAULT '0' NOT NULL,&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; NAME VARCHAR2(255) NOT NULL,&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; DESCRIPTION CLOB&nbsp;&nbsp; <br />
);&nbsp;&nbsp; <br />
ALTER TABLE DEPARTMENT ADD CONSTRAINT PRIMARY_0 PRIMARY KEY(ID) ENABLE;&nbsp;&nbsp; <br />
ALTER TABLE DEPARTMENT ADD CONSTRAINT UK_DEPARTMENT_1 UNIQUE (NAME);&nbsp;&nbsp; <br />
&nbsp; <br />
CREATE SEQUENCE DEPARTMENT_ID_SEQ MINVALUE 10000 MAXVALUE 999999999999999999999999 INCREMENT BY 1 NOCYCLE;&nbsp; <br />
<br />
创建DEPARTMENT表，并为DEPARTMENT表创建一个单独的SEQUENCE，名字为SEQUENCE_ID_SEQ，并不需要创建触发器。 <br />
<br />
[2]hibernate映射文件的配置： <br />
Java代码 <br />
<br />
&lt;?xml version="1.0"?&gt;&nbsp;&nbsp; <br />
&lt;!DOCTYPE hibernate-mapping PUBLIC&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "-//Hibernate/Hibernate Mapping DTD 3.0//EN"&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"&gt;&nbsp;&nbsp; <br />
&lt;hibernate-mapping package="com.liyanframework.demo.domain"&gt;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; &lt;class name="Department" table="DEPARTMENT"&gt;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;id name="id" column="ID"&gt;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;generator class="sequence"&gt;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;param name="sequence"&gt;DEPARTMENT_ID_SEQ&lt;/param&gt;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/generator&gt;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/id&gt;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;property name="name" column="NAME" type="string" /&gt;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;property name="description" column="DESCRIPTION" type="text" /&gt;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; &lt;/class&gt;&nbsp;&nbsp; <br />
&lt;/hibernate-mapping&gt;&nbsp; <br />
<br />
在hibernate映射文件中，对ID的生成策略选择sequence，指定sequence的名字DEPARTMENT_ID_SEQ就可以了，当你
保存新对象的时候，hibernate会自动取得DEPARTMENT_ID_SEQ.NEXTVAL作为新对象的ID保存到数据库，所以不需要再使用触
发器再来生成新记录的ID。 <br />
<br />
<br />
第二种：设置ID的增长策略是native，但是需要创建一个名字为hibernate_sequence（这个名字好像是hibernate默认的
sequence名字，不创建会出错的）的全局使用的sequence，然后再对每一个表的ID生成的时候，使用触发器，取得
hibernate_sequence.CURRVAL作为新记录的ID，具体的oracle数据库脚本及hibernate配置文件如下： <br />
<br />
<br />
[1]oracle数据表的创建脚本： <br />
Java代码 <br />
<br />
<br />
CREATE TABLE STAFF (&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; ID NUMBER(19,0) DEFAULT '0' NOT NULL,&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; NAME VARCHAR2(255) NOT NULL,&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; AGE NUMBER(3,0) NOT NULL,&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; BIRTHDAY DATE NOT NULL,&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; SALARY NUMBER(10,2) NOT NULL,&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; LEVELNESS FLOAT NOT NULL,&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; CREATETIME TIMESTAMP NOT NULL,&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; ENABLE CHAR(2) DEFAULT 'Y' NOT NULL,&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; STATUS VARCHAR2(64) NOT NULL,&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; DEPARTMENT_ID NUMBER(19,0)&nbsp;&nbsp; <br />
);&nbsp;&nbsp; <br />
ALTER TABLE STAFF ADD CONSTRAINT PRIMARY_1 PRIMARY KEY(ID) ENABLE;&nbsp;&nbsp; <br />
ALTER TABLE STAFF ADD CONSTRAINT STAFF_IBFK_0 FOREIGN KEY(DEPARTMENT_ID) REFERENCES DEPARTMENT(ID) ENABLE;&nbsp;&nbsp; <br />
ALTER TABLE STAFF ADD CONSTRAINT UK_STAFF_1 UNIQUE (NAME);&nbsp;&nbsp; <br />
CREATE INDEX IDX_STAFF_STATUS ON STAFF(STATUS);&nbsp;&nbsp; <br />
&nbsp; <br />
CREATE SEQUENCE HIBERNATE_SEQUENCE MINVALUE 90000 MAXVALUE 999999999999999999999999 INCREMENT BY 1 NOCYCLE;&nbsp;&nbsp; <br />
&nbsp; <br />
CREATE OR REPLACE TRIGGER STAFF_ID_TRG BEFORE INSERT ON STAFF&nbsp;&nbsp; <br />
FOR EACH ROW&nbsp;&nbsp; <br />
BEGIN&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; IF INSERTING AND :NEW.ID IS NULL THEN&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; SELECT HIBERNATE_SEQUENCE.CURRVAL INTO :NEW.ID FROM DUAL;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; END IF;&nbsp;&nbsp; <br />
END;&nbsp; <br />
<br />
创建STAFF表，但是并没有为STAFF创建相应的主键sequence，而是创建了一个名字为HIBERNATE_SEQUENCE的
sequence，然后创建一个触发器STAFF_ID_TRG，当执行INSERT操作时，hibernate会先执行一次
HIBERNATE_SEQUENCE.NEXTVAL，所以在触发器中只需要取得HIBERNATE_SEQUENCE.CURRVAL作为新记录的
ID。 <br />
<br />
[2]hibernate映射文件的配置： <br />
Java代码 <br />
<br />
<br />
&lt;?xml version="1.0"?&gt;&nbsp;&nbsp; <br />
&lt;!DOCTYPE hibernate-mapping PUBLIC&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "-//Hibernate/Hibernate Mapping DTD 3.0//EN"&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"&gt;&nbsp;&nbsp; <br />
&lt;hibernate-mapping package="com.liyanframework.demo.domain"&gt;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; &lt;class name="Staff" table="STAFF"&gt;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;id name="id" column="ID"&gt;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;generator class="native" /&gt;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/id&gt;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;property name="name" column="NAME" type="string" /&gt;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;property name="age" column="AGE" type="integer" /&gt;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;property name="birthday" column="BIRTHDAY" type="date" /&gt;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;property name="salary" column="SALARY" type="big_decimal" /&gt;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;property name="level" column="LEVELNESS" type="float" /&gt;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;property name="createTime" column="CREATETIME" type="timestamp" /&gt;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;property name="enable" column="ENABLE" type="character" /&gt;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;property name="status" column="STATUS" type="string" /&gt;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;many-to-one name="department" column="DEPARTMENT_ID" class="Department" /&gt;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; &lt;/class&gt;&nbsp;&nbsp; <br />
&lt;/hibernate-mapping&gt;&nbsp; <br />
<br />
在hibernate映射文件中，对ID的生成策略选择native，hibernate会根据你数据库的触发器来生成新记录的ID。 <br />
</span></span></span></span><u><br />
<span style="font-size: 12pt;"><span style="font-family: 宋体;"><span style="font-size: 8pt;"><span style="font-size: 10pt;">比
较两种做法，第二种做法也就是hibernate在代码中，实现了oracle中的触发器功能。对于不同的情况，选择不懂的做法。如果新的系统，新建的
oracle数据库，推荐使用第一种做法，简单，容易移植到其他支持自动增长的数据库；如果是老的系统，需要把其他数据库转换为oracle的，那就要用
第二种了，使用native的方式，可以不改动配置文件，兼容oracle和mysql之类带有自动增长的数据库。<br />
<br />
<br />
<br />
<br />
</span></span></span></span></u>安装有oracle数据库，创建数据库，总是要创建一个主键ID，唯一标示各条记录，但oracle不支持自动编号，所以还得创建一个SEQUENCE(序列)语句如<br />
&nbsp;&nbsp;&nbsp;&nbsp;
<div style="border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; font-size: 13px; width: 98%; background-color: rgb(238, 238, 238);"><span style="color: rgb(0, 0, 255);">create</span><span style="color: rgb(0, 0, 0);"> sequence bign nocycle maxvalue </span><span style="font-weight: bold; color: rgb(128, 0, 0);">9999999999</span><span style="color: rgb(0, 0, 0);"> start </span><span style="color: rgb(0, 0, 255);">with</span><span style="font-weight: bold; color: rgb(128, 0, 0);">1</span><span style="color: rgb(0, 0, 0);">;</span><span style="color: rgb(128, 128, 128);">//</span><span style="color: rgb(0, 0, 0);">增加数据<br />
<br />
</span><span style="color: rgb(0, 0, 255);">insert</span><span style="color: rgb(0, 0, 255);">into</span><span style="color: rgb(0, 0, 255);">table</span><span style="color: rgb(0, 0, 0);"> (ID,..) </span><span style="color: rgb(0, 0, 255);">values</span><span style="color: rgb(0, 0, 0);">(bign.nextval,..)</span></div>
<br />
&nbsp;&nbsp;&nbsp;&nbsp;  在hibernate中的映射文件可这么写<br />
<div style="border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; font-size: 13px; width: 98%; background-color: rgb(238, 238, 238);"><span style="color: rgb(0, 0, 255);">&nbsp;&nbsp;  &lt;</span><span style="color: rgb(128, 0, 0);">id </span><span style="color: rgb(255, 0, 0);">name</span><span style="color: rgb(0, 0, 255);">="id"</span><span style="color: rgb(255, 0, 0);"> type</span><span style="color: rgb(0, 0, 255);">="java.lang.Long"</span><span style="color: rgb(255, 0, 0);"> column</span><span style="color: rgb(0, 0, 255);">="ID"</span><span style="color: rgb(0, 0, 255);">&gt;</span><span style="color: rgb(0, 0, 0);"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">&lt;</span><span style="color: rgb(128, 0, 0);">generator </span><span style="color: rgb(255, 0, 0);">class</span><span style="color: rgb(0, 0, 255);">="sequence"</span><span style="color: rgb(0, 0, 255);">&gt;</span><span style="color: rgb(0, 0, 0);"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">&lt;</span><span style="color: rgb(128, 0, 0);">param </span><span style="color: rgb(255, 0, 0);">name</span><span style="color: rgb(0, 0, 255);">="sequence"</span><span style="color: rgb(0, 0, 255);">&gt;</span><span style="color: rgb(0, 0, 0);">bign</span><span style="color: rgb(0, 0, 255);">&lt;/</span><span style="color: rgb(128, 0, 0);">param</span><span style="color: rgb(0, 0, 255);">&gt;</span><span style="color: rgb(0, 0, 0);"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">&lt;/</span><span style="color: rgb(128, 0, 0);">generator</span><span style="color: rgb(0, 0, 255);">&gt;</span><span style="color: rgb(0, 0, 0);"><br />
&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">&lt;/</span><span style="color: rgb(128, 0, 0);">id</span><span style="color: rgb(0, 0, 255);">&gt;</span></div>
<br />
或<br />
<br />
<div style="border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; font-size: 13px; width: 98%; background-color: rgb(238, 238, 238);"><span style="color: rgb(0, 0, 255);">&lt;</span><span style="color: rgb(128, 0, 0);">id </span><span style="color: rgb(255, 0, 0);">name</span><span style="color: rgb(0, 0, 255);">="id"</span><span style="color: rgb(255, 0, 0);"> type</span><span style="color: rgb(0, 0, 255);">="java.lang.Long"</span><span style="color: rgb(255, 0, 0);"> column</span><span style="color: rgb(0, 0, 255);">="ID"</span><span style="color: rgb(0, 0, 255);">&gt;</span><span style="color: rgb(0, 0, 0);"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">&lt;</span><span style="color: rgb(128, 0, 0);">generator </span><span style="color: rgb(255, 0, 0);">class</span><span style="color: rgb(0, 0, 255);">="increment"</span><span style="color: rgb(0, 0, 255);">&gt;</span><span style="color: rgb(0, 0, 0);"><br />
&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">&lt;/</span><span style="color: rgb(128, 0, 0);">id</span><span style="color: rgb(0, 0, 255);">&gt;</span></div>
<p><br />
(increment 用与为long，short或者int类型生成唯一标示。只有在没有其他进程忘同一张表中插入数据时才能使用。在集群下不要使用)</p>
<img src ="http://www.blogjava.net/wangxinsh55/aggbug/222956.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/wangxinsh55/" target="_blank">SIMONE</a> 2008-08-19 11:43 <a href="http://www.blogjava.net/wangxinsh55/archive/2008/08/19/222956.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>VC中使用Gdi+合并jpg图片</title><link>http://www.blogjava.net/wangxinsh55/archive/2008/07/05/212754.html</link><dc:creator>SIMONE</dc:creator><author>SIMONE</author><pubDate>Sat, 05 Jul 2008 09:32:00 GMT</pubDate><guid>http://www.blogjava.net/wangxinsh55/archive/2008/07/05/212754.html</guid><wfw:comment>http://www.blogjava.net/wangxinsh55/comments/212754.html</wfw:comment><comments>http://www.blogjava.net/wangxinsh55/archive/2008/07/05/212754.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/wangxinsh55/comments/commentRss/212754.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/wangxinsh55/services/trackbacks/212754.html</trackback:ping><description><![CDATA[合并两张jpg图片为一张jpg图片，思路是先把两张图片jpg图片都转化成bmp图片，然后把两张bmp图片合并成一张bmp图片，然后是把这张bmp图片转化为jpg图片。<br />
<br />
一。jpg，bmp互相转化<br />
/*********************************<br />
format:bmp转为jpg， format为image/jpeg,jpg转为bmp,format为image/bmp<br />
strDst为最终转化结果的图片路径<br />
strSrc为原来图片的路径<br />
**********************************/<br />
BOOL ConvertPic(const WCHAR *format, const CString &amp;strDst, const CString &amp;strSrc)<br />
{<br />
BOOL bConvert = false;<br />
CLSID clsid;<br />
int nRet = 0;<br />
nRet = GetEncoderClsid(format,&amp;clsid);&nbsp;&nbsp;//得到CLSID<br />
USES_CONVERSION;<br />
if (nRet&gt;=0)<br />
{<br />
&nbsp;&nbsp;Image image(A2W(strSrc));<br />
&nbsp;&nbsp;image.Save(A2W(strDst),&amp;clsid,NULL);<br />
&nbsp;&nbsp;bConvert = true;<br />
}<br />
return bConvert;<br />
}<br />
其中GetEncoderClsid函数如下：<br />
/*****************************************************<br />
返回值为-1表示失败，其他为成功<br />
******************************************************/<br />
int GetEncoderClsid(const WCHAR *format, CLSID *pClsid)<br />
{<br />
int nRet = -1;<br />
ImageCodecInfo * pCodecInfo = NULL;<br />
UINT nNum = 0,nSize = 0;<br />
GetImageEncodersSize(&amp;nNum,&amp;nSize);<br />
if (nSize&lt;0)<br />
{<br />
&nbsp;&nbsp;return nRet;<br />
}<br />
pCodecInfo = new ImageCodecInfo[nSize];<br />
if (pCodecInfo==NULL)<br />
{<br />
&nbsp;&nbsp;return nRet;<br />
}<br />
GetImageEncoders(nNum,nSize,pCodecInfo);<br />
for (UINT i=0; i&lt;nNum; i++)<br />
{<br />
&nbsp;&nbsp;if (wcscmp(pCodecInfo[i].MimeType,format)==0)<br />
&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;*pClsid = pCodecInfo[i].Clsid;<br />
&nbsp;&nbsp;&nbsp;nRet = i;<br />
<br />
&nbsp;&nbsp;&nbsp;delete[] pCodecInfo;<br />
&nbsp;&nbsp;&nbsp;return nRet;<br />
&nbsp;&nbsp;}<br />
&nbsp;&nbsp;else<br />
&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;continue;<br />
&nbsp;&nbsp;}<br />
}<br />
delete[] pCodecInfo;<br />
return nRet;<br />
}<br />
bmp转化为jpg<br />
ConvertPic(L"image/jpeg","c:""1.jpg","c:""1.bmp")<br />
jpg转化为bmp<br />
ConvertPic(L"image/bmp","c:""1.bmp","c:""1.jpg")<br />
<br />
二。bmp图片合并<br />
BOOL CombinePic(const WCHAR *format, const CString &amp;strDst, const CString &amp;strPic1, "<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;const CString &amp;strPic2)<br />
{<br />
BOOL bCombine = false;<br />
int nRet = 0;<br />
CLSID clsid;<br />
nRet = GetEncoderClsid(format,&amp;clsid);<br />
if (nRet&gt;=0)<br />
{<br />
&nbsp;&nbsp;USES_CONVERSION;<br />
&nbsp;&nbsp;Bitmap bmp1(A2W(strPic1));<br />
&nbsp;&nbsp;Bitmap bmp2(A2W(strPic2));<br />
&nbsp;&nbsp;<br />
&nbsp;&nbsp;int nWidth = 0, nHeight = 0;<br />
&nbsp;&nbsp;nWidth = bmp1.GetWidth();&nbsp;&nbsp;&nbsp;//假设两图片大小同<br />
&nbsp;&nbsp;nHeight = bmp1.GetHeight();<br />
&nbsp;&nbsp;Bitmap bmpCombine(2*nWidth,nHeight);&nbsp;&nbsp;//高不变，宽*2，水平合并<br />
&nbsp;&nbsp;Graphics * pG = NULL;<br />
&nbsp;&nbsp;pG = Graphics::FromImage(&amp;bmpCombine);<br />
&nbsp;&nbsp;if (pG!=NULL)<br />
&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;pG-&gt;DrawImage(&amp;bmp1,0,0);<br />
&nbsp;&nbsp;&nbsp;pG-&gt;DrawImage(&amp;bmp2,nWidth,0);<br />
<br />
// Create a string.<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp; WCHAR string[] = L"simone";<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp; // Initialize arguments.<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp; Font myFont(L"Arial", 16);<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp; PointF origin(50.0f, 5.0f);<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp; SolidBrush blackBrush(Color(255, 255, 0, 0));<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp; StringFormat format;<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp; format.SetAlignment(StringAlignmentCenter);<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; // Draw string.<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp; pG-&gt;DrawString(<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp; string,<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp; 6,<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp; &amp;myFont,<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp; origin,<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp; &amp;format,<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp; &amp;blackBrush);<br />
<br />
&nbsp;&nbsp;&nbsp;bmpCombine.Save(A2W(strDst),&amp;clsid,NULL);<br />
&nbsp;&nbsp;}<br />
}<br />
return bCombine;<br />
}<br />
例子：<br />
CombinePic(L"image/bmp","12.bmp","1.bmp","2.bmp");<br />
<br />
有了上面的功能，其他的就没问题了
<img src ="http://www.blogjava.net/wangxinsh55/aggbug/212754.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/wangxinsh55/" target="_blank">SIMONE</a> 2008-07-05 17:32 <a href="http://www.blogjava.net/wangxinsh55/archive/2008/07/05/212754.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>VC 界面库 收集</title><link>http://www.blogjava.net/wangxinsh55/archive/2008/07/03/212373.html</link><dc:creator>SIMONE</dc:creator><author>SIMONE</author><pubDate>Thu, 03 Jul 2008 08:32:00 GMT</pubDate><guid>http://www.blogjava.net/wangxinsh55/archive/2008/07/03/212373.html</guid><wfw:comment>http://www.blogjava.net/wangxinsh55/comments/212373.html</wfw:comment><comments>http://www.blogjava.net/wangxinsh55/archive/2008/07/03/212373.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/wangxinsh55/comments/commentRss/212373.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/wangxinsh55/services/trackbacks/212373.html</trackback:ping><description><![CDATA[<div id="art" width="100%" style="margin: 15px;">
<div>
<p>GuiToolkit(开源，类似Visual Studio 2003风格)<br />
<a href="http://www.beyondata.com/default.htm"><font color="#0000ff">http://www.beyondata.com/default.htm</font></a></p>
<p>GardenUI(免费，界面效果挺好的,XML，代码 界面 分离)<br />
<a href="http://www.gardenui.com/"><font color="#800080">http://www.gardenui.com/</font></a></p>
<p>CJLib(开源，免费，UNICODE编码,是xtreme toolkit的前生，但xtreme toolkit收费了)<br />
<a href="http://www.codejock.com/"><font color="#0000ff">http://www.codejock.com/</font></a></p>
<p>LibUIDK(部分免费，不开源，效果好,适合贴图)<br />
<a href="http://www.iuishop.com/download.htm"><font color="#0000ff">http://www.iuishop.com/download.htm</font></a></p>
<p>BCGControlBar(收费，界面感觉和Office类似)<br />
<a href="http://www.bcgsoft.com/"><font color="#0000ff">http://www.bcgsoft.com</font></a></p>
<p>SKin++(收费，界面很好看，从它的截图上可以看出)<br />
<a href="http://www.uipower.com/"><font color="#0000ff">http://www.uipower.com/</font></a></p>
<p>SkinMagic(收费，看起来像Office)<br />
<a href="http://appspeed.com/html/download.html"><font color="#0000ff">http://appspeed.com/html/download.html</font></a></p>
<p>ActiveSkin(未知)<br />
<a href="http://www.softshape.com/software/develop/"><font color="#0000ff">http://www.softshape.com/software/develop/</font></a></p>
<p>SYGUI(收费,类似Office)<br />
<a href="http://www.sygui.com/"><font color="#0000ff">http://www.sygui.com/</font></a></p>
<p><br />
一般到下面两个网站找自己需要的控件，可以参考一下：<br />
<a href="http://www.vckbase.com/code/"><font color="#0000ff">http://www.vckbase.com/code/</font></a><br />
<a href="http://www.codeproject.com/"><font color="#0000ff">http://www.codeproject.com/</font></a></p>
</div>
</div>
<img src ="http://www.blogjava.net/wangxinsh55/aggbug/212373.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/wangxinsh55/" target="_blank">SIMONE</a> 2008-07-03 16:32 <a href="http://www.blogjava.net/wangxinsh55/archive/2008/07/03/212373.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>socket 接收与发送</title><link>http://www.blogjava.net/wangxinsh55/archive/2008/07/03/212354.html</link><dc:creator>SIMONE</dc:creator><author>SIMONE</author><pubDate>Thu, 03 Jul 2008 07:39:00 GMT</pubDate><guid>http://www.blogjava.net/wangxinsh55/archive/2008/07/03/212354.html</guid><wfw:comment>http://www.blogjava.net/wangxinsh55/comments/212354.html</wfw:comment><comments>http://www.blogjava.net/wangxinsh55/archive/2008/07/03/212354.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/wangxinsh55/comments/commentRss/212354.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/wangxinsh55/services/trackbacks/212354.html</trackback:ping><description><![CDATA[&nbsp; void &nbsp; CNetRecvDlg::OnButton1() &nbsp;  &nbsp; <br />
&nbsp; { &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; CString &nbsp; szIP; &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; GetDlgItem(IDC_EDIT1)-&gt;GetWindowText(szIP); &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; struct &nbsp; sockaddr_in &nbsp; sin; &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; WSADATA &nbsp; wsaData; &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; SOCKET &nbsp; sockClient; &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; int &nbsp; IpPort; &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; char &nbsp; *IpAddr; &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; IpAddr=szIP.GetBuffer(szIP.GetLength()); &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; IpPort=800; &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; if(WSAStartup(0x0101, &nbsp; &amp;wsaData &nbsp; )) &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; { &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; AfxMessageBox("初始化 &nbsp; TCP/IP &nbsp; 协议栈发生错误!"); &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; return; &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; } &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; if(wsaData.wVersion &nbsp; != &nbsp; 0x0101) &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; { &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; AfxMessageBox("Winsock &nbsp; version &nbsp; is &nbsp; incorrect!"); &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; WSACleanup(); &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; return; &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; } &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; if &nbsp; ((sockClient &nbsp; = &nbsp; socket &nbsp; (PF_INET, &nbsp; SOCK_STREAM, &nbsp; IPPROTO_IP)) &nbsp; == &nbsp; INVALID_SOCKET) &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; { &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; AfxMessageBox("Create &nbsp; socket &nbsp; error!"); &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; return; &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; } &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; sin.sin_family=AF_INET; &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; sin.sin_addr.s_addr=inet_addr(IpAddr); &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; sin.sin_port=htons((short)IpPort); &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; int &nbsp; timeout=300; &nbsp;  &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; int &nbsp; status=setsockopt(sockClient,SOL_SOCKET,SO_RCVTIMEO,(char*)&amp;timeout,sizeof(timeout)); &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; if(status) &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; { &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; MessageBox("设置超时错误"); &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; WSACleanup(); &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; return &nbsp; ; &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; } &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; int &nbsp; buf=10240; &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; int &nbsp; status2=setsockopt(sockClient,SOL_SOCKET,SO_RCVBUF,(char*)&amp;buf,sizeof(int)); &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; if(status2) &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; { &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; MessageBox("设置缓冲区大小错误"); &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; WSACleanup(); &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; return &nbsp; ; &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; } &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; if(connect &nbsp; (sockClient, &nbsp; (struct &nbsp; sockaddr &nbsp; *)&amp;sin, &nbsp; sizeof &nbsp; (sin)) &nbsp; == &nbsp; SOCKET_ERROR) &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; { &nbsp; <br />
<clk>&nbsp;MessageBox("<nobr id="clickeyekey2" style="border-bottom: 1px dotted #6600ff; text-decoration: underline; color: #6600ff; background-color: transparent;" onclick="$cE.defer(this);return kwC(event,2)" target="_blank" oncontextmenu="return false;" onmouseover="kwE(event,2, this);" onmouseout="kwL(event,this)" onmousemove="kwM(2);">连接错误</nobr>"); &nbsp; </clk><br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; closesocket(sockClient); &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; WSACleanup(); &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; return; &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; } &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; else{ &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; WIN32_FIND_DATA &nbsp; fd; &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; ::Sleep(20); &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; recv(sockClient,(char*)&amp;fd,sizeof(WIN32_FIND_DATA),0); &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; //////////////////////////////////////////////////////// &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; //PROGRESS &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; m_Progress.SetRange(0,(short)fd.nFileSizeLow); &nbsp;  &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; m_Progress.SetPos(0); &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; m_Progress.SetStep(1); &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; //////////////////////////////////////////////////// &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; CString &nbsp; m_ProDir="e:"""; &nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; CFile &nbsp; destFile(m_ProDir+fd.cFileName, &nbsp;
CFile::modeCreate &nbsp; | &nbsp; CFile::modeWrite &nbsp; | &nbsp; CFile::typeBinary); &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; UINT &nbsp; dwRead &nbsp; = &nbsp; 0; &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; while(dwRead&lt;fd.nFileSizeLow) &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; { &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; byte* &nbsp; data &nbsp; = &nbsp; new &nbsp; byte[2048]; &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; memset(data,0,2048); &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; UINT &nbsp; dw=recv(sockClient,(char*)data,2048,0); &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; destFile.Write(data, &nbsp; dw); &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; dwRead+=dw; &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; delete &nbsp; [] &nbsp; data; &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; m_Progress.StepIt(); &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; } &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; m_Progress.SetPos((short)fd.nFileSizeLow); &nbsp;  &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; SetFileTime((HANDLE)destFile.m_hFile,&amp;fd.ftCreationTime, &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; &amp;fd.ftLastAccessTime,&amp;fd.ftLastWriteTime); &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; SetFileAttributes(m_ProDir+fd.cFileName,fd.dwFileAttributes); &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; destFile.Close(); &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; closesocket &nbsp; (sockClient); &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; WSACleanup(); &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; } &nbsp; <br />
&nbsp; }&nbsp; <br />
<br />
***********************************************************************************************<br />
#include &nbsp; "afxmt.h" &nbsp; <br />
&nbsp; CString &nbsp; m_PATH; &nbsp; <br />
&nbsp; DWORD &nbsp; filesize; &nbsp; <br />
&nbsp; HWND &nbsp; hwnd_p; &nbsp; <br />
&nbsp; int &nbsp; IsBegin; &nbsp; <br />
&nbsp;  &nbsp; <br />
&nbsp;  &nbsp; <br />
&nbsp; void &nbsp; CNetSendDlg::OnTransfer(CString &nbsp; m_PATH) &nbsp; <br />
&nbsp; { &nbsp; <br />
&nbsp;  &nbsp; <br />
&nbsp; } &nbsp; <br />
&nbsp;  &nbsp; <br />
&nbsp;  &nbsp; <br />
&nbsp;  &nbsp; <br />
&nbsp; UINT &nbsp; CNetSendDlg::ThreadA(LPVOID &nbsp; pParam) &nbsp; <br />
&nbsp; { &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; IsBegin=0; &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; CFile &nbsp; myFile; &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; if(!myFile.Open(m_PATH, &nbsp; CFile::modeRead &nbsp; | &nbsp; CFile::typeBinary|CFile::shareDenyNone)) &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; { &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; return &nbsp; 0; &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; } &nbsp; <br />
&nbsp;  &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; CString &nbsp; szIP; &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; struct &nbsp; sockaddr_in &nbsp; sin; &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; WSADATA &nbsp; wsaData; &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; SOCKET &nbsp; sockSrvr,sockRecv; &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; char &nbsp; *IpAddr; &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; if(WSAStartup(0x0101, &nbsp; &amp;wsaData &nbsp; )) &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; { &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; AfxMessageBox("初始化 &nbsp; TCP/IP &nbsp; 协议栈发生错误!"); &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; return &nbsp; 0; &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; } &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; if(wsaData.wVersion &nbsp; != &nbsp; 0x0101) &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; { &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; AfxMessageBox("Winsock &nbsp; version &nbsp; is &nbsp; incorrect!"); &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; WSACleanup(); &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; return &nbsp; 0; &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; } &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; if &nbsp; ((sockSrvr &nbsp; = &nbsp; socket &nbsp; (PF_INET, &nbsp; SOCK_STREAM, &nbsp; IPPROTO_IP)) &nbsp; == &nbsp; INVALID_SOCKET) &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; { &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; AfxMessageBox("Create &nbsp; socket &nbsp; error!"); &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; return &nbsp; 0; &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; } &nbsp; <br />
&nbsp;  &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; if &nbsp; ((sockRecv &nbsp; = &nbsp; socket &nbsp; (PF_INET, &nbsp; SOCK_STREAM, &nbsp; IPPROTO_IP)) &nbsp; == &nbsp; INVALID_SOCKET) &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; { &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; AfxMessageBox("Create &nbsp; socket &nbsp; error!"); &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; return &nbsp; 0; &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; } &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; ////////////////////////////////////// &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; CString &nbsp; m_addr; &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; CString &nbsp; m_strT; &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; CString &nbsp; sNetBiosName; &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; char &nbsp; hostname[128]; &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; struct &nbsp; hostent &nbsp; *phost; &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; gethostname(hostname,128); &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; m_addr &nbsp; = &nbsp; hostname; &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; phost &nbsp; = &nbsp; gethostbyname(hostname); &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; int &nbsp; m_iCounter=0; &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; for(int &nbsp; j &nbsp; = &nbsp; 0;j&lt;4;j++) &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; { &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; m_strT.Format("%u", &nbsp; (unsigned &nbsp;
int)((unsigned &nbsp; char*)phost-&gt;h_addr_list[0])[j]); &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; sNetBiosName+=m_strT; &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; if(m_iCounter&lt;3) &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; { &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; m_iCounter++; &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; sNetBiosName+="."; &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; } &nbsp;  &nbsp;  &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; } &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; ////////////////////////////////////// &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; szIP=sNetBiosName; &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; IpAddr=szIP.GetBuffer(szIP.GetLength()); &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; sin.sin_family=AF_INET; &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; sin.sin_addr.s_addr=inet_addr(IpAddr); &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; sin.sin_port=htons(800); &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; if(bind(sockSrvr,(sockaddr*)&amp;sin,sizeof(sin))&lt;0) &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; { &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; AfxMessageBox("绑定错误"); &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; return &nbsp; 0; &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; } &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; listen(sockSrvr,20); &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; int &nbsp; length=sizeof(sin); &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; sockRecv=accept(sockSrvr,(struct &nbsp; sockaddr*)&amp;sin,&amp;length); &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; int &nbsp; timeout=300; &nbsp;  &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; int &nbsp; status=setsockopt(sockRecv,SOL_SOCKET,SO_RCVTIMEO,(char*)&amp;timeout,sizeof(timeout)); &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; if(status) &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; { &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; AfxMessageBox("设置超时错误"); &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; WSACleanup(); &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; return &nbsp; 0; &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; } &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; int &nbsp; buf=10240; &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; int &nbsp; status2=setsockopt(sockRecv,SOL_SOCKET,SO_RCVBUF,(char*)&amp;buf,sizeof(int)); &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; if(status2) &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; { &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; AfxMessageBox("设置缓冲区大小错误"); &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; WSACleanup(); &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; return &nbsp; 0; &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; } &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; ////////////////////////////////////////////////////////////////// &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; WIN32_FIND_DATA &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; FindFileData; &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; FindClose(FindFirstFile(m_PATH,&amp;FindFileData)); &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; send(sockRecv,(char*)&amp;FindFileData,sizeof(WIN32_FIND_DATA),0); &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; //////////////////////////////////////////////////////// &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; //PROGRESS &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; filesize=(short)FindFileData.nFileSizeLow; &nbsp;  &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; ::PostMessage(hwnd_p,WM_USER_PROG,NULL,NULL); &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; //////////////////////////////////////////////////// &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; UINT &nbsp; dwRead=0; &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; byte* &nbsp; data; &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; while(dwRead&lt;FindFileData.nFileSizeLow) &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; { &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; data &nbsp; = &nbsp; new &nbsp; byte[2048]; &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; UINT &nbsp; dw=myFile.Read(data, &nbsp; 2048); &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; send(sockRecv,(char*)data,2048,0); &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; dwRead+=dw; &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; delete &nbsp; [] &nbsp; data; &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; IsBegin=1; &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; ::PostMessage(hwnd_p,WM_USER_PROG,NULL,NULL); &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; } &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; IsBegin=2; &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; //::PostMessage(hwnd_p,WM_USER_PROG,NULL,NULL); &nbsp; <br />
&nbsp;  &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; myFile.Close(); &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; closesocket(sockRecv); &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; closesocket(sockSrvr); &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; WSACleanup(); &nbsp; <br />
&nbsp;  &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; return &nbsp; 0; &nbsp; <br />
&nbsp; } &nbsp; <br />
&nbsp;  &nbsp; <br />
&nbsp; LRESULT &nbsp; CNetSendDlg::OnProgress(WPARAM &nbsp; wParam, &nbsp; LPARAM &nbsp; lParam) &nbsp; <br />
&nbsp; { &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; CString &nbsp; st; &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; st.Format("%d",filesize); &nbsp; <br />
&nbsp;  &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; if(IsBegin==0) &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; { &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; m_Progress.SetRange(0,(short)filesize/1000); &nbsp;  &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; m_Progress.SetPos(0); &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; m_Progress.SetStep(1); &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; } &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; else &nbsp; if(IsBegin==1) &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; { &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; m_Progress.StepIt(); &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; } &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; else &nbsp; if(IsBegin==2) &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; { &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; m_Progress.SetPos((short)filesize/1000); &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; } &nbsp; <br />
&nbsp;  &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; return &nbsp; 0; &nbsp; <br />
&nbsp;  &nbsp; <br />
&nbsp; } &nbsp; <br />
&nbsp;  &nbsp; <br />
&nbsp; static &nbsp; char &nbsp; BASED_CODE &nbsp; szFilter[]="|*.*|"; &nbsp; <br />
&nbsp; void &nbsp; CNetSendDlg::OnButton1() &nbsp;  &nbsp; <br />
&nbsp; { &nbsp; <br />
&nbsp; OPENFILENAME &nbsp;  &nbsp;  &nbsp;  &nbsp; ofn &nbsp; ; &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; TCHAR &nbsp;  &nbsp; szFullName[_MAX_PATH]; &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; ::ZeroMemory &nbsp; (&amp;ofn, &nbsp; sizeof(OPENFILENAME)) &nbsp; ; &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; szFullName[0] &nbsp; = &nbsp; TEXT('"0') &nbsp; ; &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; ofn.lStructSize &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; = &nbsp; sizeof &nbsp; (OPENFILENAME) &nbsp; ; &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; ofn.hwndOwner &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; = &nbsp; m_hWnd; &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; ofn.hInstance &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; = &nbsp; NULL &nbsp; ; &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; ofn.lpstrFilter &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; = &nbsp; "*.txt"0"0" &nbsp; ; &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; ofn.lpstrCustomFilter &nbsp; = &nbsp; NULL &nbsp; ; &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; ofn.nMaxCustFilter &nbsp;  &nbsp;  &nbsp;  &nbsp; = &nbsp; 0 &nbsp; ; &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; ofn.nFilterIndex &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; = &nbsp; 0 &nbsp; ; &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; ofn.nMaxFile &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; = &nbsp; MAX_PATH &nbsp; ; &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; ofn.nMaxFileTitle &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; = &nbsp; MAX_PATH &nbsp; ; &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; ofn.lpstrInitialDir &nbsp;  &nbsp;  &nbsp; = &nbsp; "c:""" &nbsp; ; &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; ofn.lpstrTitle &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; = &nbsp; "保存到"; &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; ofn.lpstrFile &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; = &nbsp; szFullName &nbsp; ; &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; ofn.nFileExtension &nbsp;  &nbsp;  &nbsp;  &nbsp; = &nbsp; 0 &nbsp; ; &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; ofn.lpstrDefExt &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; = &nbsp; TEXT("txt") &nbsp; ; &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; ofn.lCustData &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; = &nbsp; 0 &nbsp; ; &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; ofn.lpfnHook &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; = &nbsp; NULL &nbsp; ; &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; ofn.lpTemplateName &nbsp;  &nbsp;  &nbsp;  &nbsp; = &nbsp; NULL &nbsp; ; &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; ofn.Flags &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; = &nbsp; OFN_ENABLESIZING &nbsp; | &nbsp; OFN_OVERWRITEPROMPT &nbsp; ; &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; if(!::GetOpenFileName(&amp;ofn)) &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; return; &nbsp; <br />
&nbsp;  &nbsp;  &nbsp; GetDlgItem(IDC_EDIT1)-&gt;SetWindowText(ofn.lpstrFile); &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; <br />
&nbsp; } &nbsp; <br />
&nbsp;  &nbsp; <br />
&nbsp; void &nbsp; CNetSendDlg::OnButton2() &nbsp;  &nbsp; <br />
&nbsp; { &nbsp; <br />
&nbsp; // &nbsp;  &nbsp;  &nbsp;  &nbsp; m_PATH="c:""1.jpg"; &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; GetDlgItem(IDC_EDIT1)-&gt;GetWindowText(m_PATH); &nbsp; <br />
&nbsp;  &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; hwnd_p=this-&gt;m_hWnd; &nbsp; <br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; AfxBeginThread(ThreadA,NULL,THREAD_PRIORITY_IDLE); &nbsp; <br />
&nbsp; } &nbsp; <br />
&nbsp; <br />
<img src ="http://www.blogjava.net/wangxinsh55/aggbug/212354.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/wangxinsh55/" target="_blank">SIMONE</a> 2008-07-03 15:39 <a href="http://www.blogjava.net/wangxinsh55/archive/2008/07/03/212354.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>CAsyncSocket对象不能跨线程之分析</title><link>http://www.blogjava.net/wangxinsh55/archive/2008/07/03/212348.html</link><dc:creator>SIMONE</dc:creator><author>SIMONE</author><pubDate>Thu, 03 Jul 2008 07:22:00 GMT</pubDate><guid>http://www.blogjava.net/wangxinsh55/archive/2008/07/03/212348.html</guid><wfw:comment>http://www.blogjava.net/wangxinsh55/comments/212348.html</wfw:comment><comments>http://www.blogjava.net/wangxinsh55/archive/2008/07/03/212348.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/wangxinsh55/comments/commentRss/212348.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/wangxinsh55/services/trackbacks/212348.html</trackback:ping><description><![CDATA[<div>
<h2>现象</h2>
用多线程方法设计socket程序时，你会发现在跨线程使用CAsyncSocket及其派生类时，会出现程序崩溃。所谓跨线程，是指该对象在一个线程中
调用Create/AttachHandle/Attach函数，然后在另外一个线程中调用其他成员函数。下面的例子就是一个典型的导致崩溃的过程：
<pre>CAsyncSocket Socket;<br />
UINT Thread(LPVOID)<br />
{<br />
Socket.Close ();<br />
return 0;<br />
}<br />
void CTestSDlg::OnOK() <br />
{<br />
// TODO: Add extra validation here<br />
Socket.Create(0);<br />
AfxBeginThread(Thread,0,0,0,0,0);<br />
}<br />
</pre>
<p>其中Socket对象在主线程中被调用，在子线程中被关闭。
</p>
<h2>跟踪分析</h2>
<p>这个问题的原因可以通过单步跟踪(F11)的方法来了解。我们在Socket.Create(0)处设断点，跟踪进去会发现下面的函数被调用：
</p>
<pre>void PASCAL CAsyncSocket::AttachHandle(<br />
SOCKET hSocket, CAsyncSocket* pSocket, BOOL bDead)<br />
{<br />
_AFX_SOCK_THREAD_STATE* pState = _afxSockThreadState;<br />
BOOL bEnable = AfxEnableMemoryTracking(FALSE);<br />
if (!bDead)<br />
{<br />
ASSERT(CAsyncSocket::LookupHandle(hSocket, bDead) == NULL);<br />
if (pState-&gt;m_pmapSocketHandle-&gt;IsEmpty())<br />
{<br />
ASSERT(pState-&gt;m_pmapDeadSockets-&gt;IsEmpty());<br />
ASSERT(pState-&gt;m_hSocketWindow == NULL);<br />
CSocketWnd* pWnd = new CSocketWnd;<br />
pWnd-&gt;m_hWnd = NULL;<br />
if (!pWnd-&gt;CreateEx(0, AfxRegisterWndClass(0),<br />
_T("Socket Notification Sink"),<br />
WS_OVERLAPPED, 0, 0, 0, 0, NULL, NULL))<br />
{<br />
TRACE0("Warning: unable to create socket notify window!"n");<br />
AfxThrowResourceException();<br />
}<br />
ASSERT(pWnd-&gt;m_hWnd != NULL);<br />
ASSERT(CWnd::FromHandlePermanent(pWnd-&gt;m_hWnd) == pWnd);<br />
pState-&gt;m_hSocketWindow = pWnd-&gt;m_hWnd;<br />
}<br />
pState-&gt;m_pmapSocketHandle-&gt;SetAt((void*)hSocket, pSocket);<br />
}<br />
else<br />
{<br />
int nCount;<br />
if (pState-&gt;m_pmapDeadSockets-&gt;Lookup((void*)hSocket, (void*&amp;)nCount))<br />
nCount++;<br />
else<br />
nCount = 1;<br />
pState-&gt;m_pmapDeadSockets-&gt;SetAt((void*)hSocket, (void*)nCount);<br />
}<br />
AfxEnableMemoryTracking(bEnable);<br />
}<br />
</pre>
<p>在这个函数的开头，首先获得了一个pState的指针指向_afxSockThreadState对象。从名字可以看出，这似乎是一个和线程相关的变量，实际上它是一个宏，定义如下：</p>
<pre>#define _afxSockThreadState AfxGetModuleThreadState()<br />
</pre>
<p>我们没有必要去细究这个指针的定义是如何的，只要知道它是和当前线程密切关联的，其他线程应该也有类似的指针，只是指向不同的结构。</p>
<p>在这个函数中，CAsyncSocket创建了一个窗口，并把如下两个信息加入到pState所管理的结构中：
</p>
<pre>    pState-&gt;m_pmapSocketHandle-&gt;SetAt((void*)hSocket, pSocket);<br />
pState-&gt;m_pmapDeadSockets-&gt;SetAt((void*)hSocket, (void*)nCount);<br />
pState-&gt;m_hSocketWindow = pWnd-&gt;m_hWnd;<br />
pState-&gt;m_pmapSocketHandle-&gt;SetAt((void*)hSocket, pSocket);<br />
</pre>
<p>当调用Close时，我们再次跟踪，就会发现在KillSocket中，下面的函数出现错误:
</p>
<pre>    void PASCAL CAsyncSocket::KillSocket(SOCKET hSocket, CAsyncSocket* pSocket)<br />
{<br />
ASSERT(CAsyncSocket::LookupHandle(hSocket, FALSE) != NULL);<br />
</pre>
<p>我们在这个ASSERT处设置断点，跟踪进LookupHandle，会发现这个函数定义如下：
</p>
<pre>CAsyncSocket* PASCAL CAsyncSocket::LookupHandle(SOCKET hSocket, BOOL bDead)<br />
{<br />
CAsyncSocket* pSocket;<br />
_AFX_SOCK_THREAD_STATE* pState = _afxSockThreadState;<br />
if (!bDead)<br />
{<br />
pSocket = (CAsyncSocket*)<br />
pState-&gt;m_pmapSocketHandle-&gt;GetValueAt((void*)hSocket);<br />
if (pSocket != NULL)<br />
return pSocket;<br />
}<br />
else<br />
{<br />
pSocket = (CAsyncSocket*)<br />
pState-&gt;m_pmapDeadSockets-&gt;GetValueAt((void*)hSocket);<br />
if (pSocket != NULL)<br />
return pSocket;<br />
}<br />
return NULL;<br />
}<br />
</pre>
<p>显然，这个函数试图从当前线程查询关于这个 socket的信息，可是这个信息放在创建这个socket的线程中，因此这种查询显然会失败，最终返回NULL。
</p>
<p>有人会问，既然它是ASSERT出错，是不是Release就没问题了。这只是自欺欺人。ASSERT/VERIFY都是检验一些程序正常运行必须正确的条件。如果ASSERT都失败，在Release中也许不会显现，但是你的程序肯定运行不正确，啥时候出错就不知道了。</p>
<h2>如何在多线程之间传递socket</h2>
<p>有些特殊情况下，可能需要在不同线程之间传递socket。当然我不建议在使用CAsyncSOcket的时候这么做，因为这增加了出错的风险（尤其当出现拆解包问题时，有人称为粘包，我基本不认同这种称呼）。如果一定要这么做，方法应该是：
</p>
<ol type="1">
    <li>当前拥有这个socket的线程调用Detach方法，这样socket句柄和C++对象及当前线程脱离关系
    </li>
    <li>当前线程把这个对象传递给另外一个线程
    </li>
    <li>另外一个线程创建新的CAsyncSocket对象，并调用Attach
    </li>
</ol>
<p>上面的例子，我稍微做修改，就不会出错了：
</p>
<pre>CAsyncSocket Socket;<br />
UINT Thread(LPVOID sock)<br />
{<br />
Socket.Attach((SOCKET)sock);<br />
Socket.Close ();<br />
return 0;<br />
}<br />
void CTestSDlg::OnOK() <br />
{<br />
// TODO: Add extra validation here<br />
Socket.Create(0);<br />
SOCKET hSocket = Socket.Detach ();<br />
AfxBeginThread(Thread,(LPVOID)hSocket,0,0,0,0);<br />
}<br />
</pre>
</div>
<img src ="http://www.blogjava.net/wangxinsh55/aggbug/212348.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/wangxinsh55/" target="_blank">SIMONE</a> 2008-07-03 15:22 <a href="http://www.blogjava.net/wangxinsh55/archive/2008/07/03/212348.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Demo1 for socket programing(3)</title><link>http://www.blogjava.net/wangxinsh55/archive/2008/07/03/212347.html</link><dc:creator>SIMONE</dc:creator><author>SIMONE</author><pubDate>Thu, 03 Jul 2008 07:21:00 GMT</pubDate><guid>http://www.blogjava.net/wangxinsh55/archive/2008/07/03/212347.html</guid><wfw:comment>http://www.blogjava.net/wangxinsh55/comments/212347.html</wfw:comment><comments>http://www.blogjava.net/wangxinsh55/archive/2008/07/03/212347.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/wangxinsh55/comments/commentRss/212347.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/wangxinsh55/services/trackbacks/212347.html</trackback:ping><description><![CDATA[<div>
<h2>sockutil.cpp</h2>
<pre><font color="#0000ff"><strong>#include</strong></font> "stdafx.h"<br />
<font color="#0000ff"><strong>#include</strong></font> &lt;iostream.h&gt;<br />
<font color="#0000ff"><strong>#include</strong></font> &lt;winsock2.h&gt;<br />
<font color="#0000ff"><strong>#include</strong></font> "sockutil.h"<br />
<font color="#0000ff"><strong>void</strong></font> ShowError(unsigned <font color="#0000ff"><strong>int</strong></font> nError)<br />
{<br />
<font color="#0000ff"><strong>void</strong></font>* lpMsgBuf;<br />
FormatMessage(<br />
FORMAT_MESSAGE_ALLOCATE_BUFFER | <br />
FORMAT_MESSAGE_FROM_SYSTEM,<br />
NULL,<br />
nError,<br />
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),<br />
(LPTSTR) &amp;lpMsgBuf,<br />
0, NULL );<br />
<br />
cout &lt;&lt;"(" &lt;&lt; nError  &lt;&lt; "):" &lt;&lt; lpMsgBuf;<br />
LocalFree(lpMsgBuf);<br />
}<br />
BOOL ErrorHandle(<font color="#0000ff"><strong>const</strong></font> <font color="#0000ff"><strong>char</strong></font> * position, BOOL condition, <font color="#0000ff"><strong>const</strong></font> <font color="#0000ff"><strong>char</strong></font> * file, unsigned <font color="#0000ff"><strong>int</strong></font> line)<br />
{<br />
<font color="#0000ff"><strong>if</strong></font>(!condition)<br />
{<br />
<font color="#0000ff"><strong>return</strong></font> condition;<br />
}<br />
cout &lt;&lt;file &lt;&lt; "(" &lt;&lt; line &lt;&lt; ")" &lt;&lt; endl;<br />
cout &lt;&lt;position&lt;&lt; endl;<br />
unsigned <font color="#0000ff"><strong>int</strong></font> nError = GetLastError();<br />
ShowError(nError);<br />
<font color="#0000ff"><strong>return</strong></font> condition;<br />
}<br />
<font color="#0000ff"><strong>void</strong></font> InitializeAddress(DWORD ip, UINT port, sockaddr_in &amp; addr)<br />
{<br />
memset(&amp;addr,0,<font color="#0000ff"><strong>sizeof</strong></font>(addr));<br />
addr.sin_family  = AF_INET;<br />
addr.sin_addr.s_addr= ip;<br />
addr.sin_port       = htons(port);<br />
}<br />
<font color="#0000ff"><strong>int</strong></font> SendData(SOCKET hSocket, <font color="#0000ff"><strong>const</strong></font> <font color="#0000ff"><strong>char</strong></font> * data, <font color="#0000ff"><strong>int</strong></font> length)<br />
{<br />
<font color="#0000ff"><strong>int</strong></font> result;<br />
<font color="#0000ff"><strong>int</strong></font> pos = 0;<br />
<font color="#0000ff"><strong>while</strong></font>(pos &lt; length)<br />
{<br />
result = send(hSocket, data + pos, length - pos , 0);<br />
<font color="#0000ff"><strong>if</strong></font>(result &gt; 0 )<br />
{<br />
pos += result;<br />
}<font color="#0000ff"><strong>else</strong></font>{<br />
<font color="#0000ff"><strong>return</strong></font> result;<br />
}<br />
}<br />
<font color="#0000ff"><strong>return</strong></font> length;<br />
}<br />
</pre>
<h2>demo1.cpp</h2>
<pre>// demo1.cpp : Defines the entry point for the console application.<br />
//<br />
<font color="#0000ff"><strong>#include</strong></font> "stdafx.h"<br />
<font color="#0000ff"><strong>#include</strong></font> &lt;stdio.h&gt;<br />
<font color="#0000ff"><strong>#include</strong></font> &lt;winsock2.h&gt;<br />
<font color="#0000ff"><strong>#pragma</strong></font> comment(lib,"ws2_32")<br />
<font color="#0000ff"><strong>#include</strong></font> "sockutil.h"<br />
<font color="#0000ff"><strong>int</strong></font> main(<font color="#0000ff"><strong>int</strong></font> argc, <font color="#0000ff"><strong>char</strong></font>* argv[])<br />
{<br />
unsigned <font color="#0000ff"><strong>short</strong></font> wVersion;<br />
WSADATA wsa;<br />
wVersion = MAKEWORD(2,2);<br />
<font color="#0000ff"><strong>if</strong></font>(ERRORHANDLE(WSAStartup(wVersion, &amp;wsa) != 0))<br />
{<br />
<font color="#0000ff"><strong>return</strong></font> -1;<br />
}<br />
SOCKET hSocket;<br />
<font color="#0000ff"><strong>int</strong></font> a = PROTO_ICMP;<br />
hSocket = socket(AF_INET,SOCK_STREAM,0);<br />
<font color="#0000ff"><strong>if</strong></font>(ERRORHANDLE(hSocket == INVALID_SOCKET))<br />
{<br />
WSACleanup();<br />
<font color="#0000ff"><strong>return</strong></font> -1;<br />
}<br />
sockaddr_in addr;<br />
InitializeAddress(INADDR_ANY, 2000, addr);<br />
<font color="#0000ff"><strong>if</strong></font>(ERRORHANDLE(SOCKET_ERROR == bind(hSocket, (<font color="#0000ff"><strong>const</strong></font> sockaddr*) &amp; addr, <font color="#0000ff"><strong>sizeof</strong></font>(addr))))<br />
{<br />
closesocket(hSocket);<br />
WSACleanup();<br />
<font color="#0000ff"><strong>return</strong></font> -1;<br />
}<br />
<font color="#0000ff"><strong>if</strong></font>(ERRORHANDLE(SOCKET_ERROR == listen(hSocket,5)))<br />
{<br />
closesocket(hSocket);<br />
WSACleanup();<br />
<font color="#0000ff"><strong>return</strong></font> -1;<br />
}<br />
SOCKET hClient;<br />
<font color="#0000ff"><strong>int</strong></font> size;<br />
<font color="#0000ff"><strong>char</strong></font> buffer[2048];<br />
<font color="#0000ff"><strong>int</strong></font> length;<br />
size = <font color="#0000ff"><strong>sizeof</strong></font>(addr);<br />
<font color="#0000ff"><strong>while</strong></font>(INVALID_SOCKET != (hClient = accept(hSocket,(sockaddr*)&amp;addr, &amp; size)))<br />
{<br />
size = <font color="#0000ff"><strong>sizeof</strong></font>(addr);<br />
<font color="#0000ff"><strong>while</strong></font>((length = recv(hClient, buffer, <font color="#0000ff"><strong>sizeof</strong></font>(buffer),0)) &gt; 0)<br />
{<br />
SendData(hClient,buffer, length);<br />
}<br />
closesocket(hClient);<br />
}<br />
closesocket(hSocket);<br />
WSACleanup();<br />
<font color="#0000ff"><strong>return</strong></font> 0;<br />
}<br />
</pre>
</div>
<img src ="http://www.blogjava.net/wangxinsh55/aggbug/212347.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/wangxinsh55/" target="_blank">SIMONE</a> 2008-07-03 15:21 <a href="http://www.blogjava.net/wangxinsh55/archive/2008/07/03/212347.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>socket 程序设计(4) － 服务端套接字demo1</title><link>http://www.blogjava.net/wangxinsh55/archive/2008/07/03/212345.html</link><dc:creator>SIMONE</dc:creator><author>SIMONE</author><pubDate>Thu, 03 Jul 2008 07:19:00 GMT</pubDate><guid>http://www.blogjava.net/wangxinsh55/archive/2008/07/03/212345.html</guid><wfw:comment>http://www.blogjava.net/wangxinsh55/comments/212345.html</wfw:comment><comments>http://www.blogjava.net/wangxinsh55/archive/2008/07/03/212345.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/wangxinsh55/comments/commentRss/212345.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/wangxinsh55/services/trackbacks/212345.html</trackback:ping><description><![CDATA[根据前面一节的说明，服务端套接字应该按照如下顺序建立：
<ol type="a">
    <li>初始化
    </li>
    <li>创建套接字
    </li>
    <li>绑定本地地址
    </li>
    <li>进入侦听状态
    </li>
    <li>处理接受循环 </li>
</ol>
<p>下面首先创建一个例子来演示服务端套接字的实现，并在以后的各节中优化这个设计。
</p>
<p>这个设计实现的功能如下：允许客户端（实际上就是telnet程序）登陆，并对客户端的输入回显。
</p>
<h2>4.1 准备工程</h2>
<p>为了实现这个demo，我打算使用Visual Studio 6.0提供的对话框模板来实现，请按照下述步骤准备工程：
</p>
<ol type="a">
    <li>启动Visual C++ 6.0
    </li>
    <li>选择File/New/Project
    </li>
    <li>选择MFC AppWizard(exe)
    </li>
    <li>在Project name中输入demo1, Next
    </li>
    <li>选择Dialog Base, Next
    </li>
    <li>在Windows Sockets前打钩
    </li>
    <li>其他都保持缺省值，点击Next完成向导
    </li>
    <li>在工程中加入两个文件：sockutil.h和sockutil.cpp：这两个文件将保存公共的函数，避免以后重复编写。 </li>
</ol>
<p>这样创建的工程会自动加入WinSock2支持，具体的内容包括：
</p>
<ol type="a">
    <li>在stdafx.h中加入#include &lt;afxsock.h&gt;,该头文件包含如下语句载入对应LIB: <br />
    <font color="#0000ff"><strong>#pragma comment(lib</strong></font>, "wsock32.lib")
    </li>
    <li>在InitInstance中加入如下代码：
    <pre><font color="#0000ff"><strong>if</strong></font>(!AfxSocketInit())<br />
    {<br />
    AfxMessageBox(IDP_SOCKETS_INIT_FAILED);<br />
    <font color="#0000ff"><strong>return</strong></font> FALSE;<br />
    }<br />
    </pre>
    </li>
    <li>在资源中定义字符串资源IDP_SOCKETS_INIT_FAILED:Windows通讯端口初始化失败</li>
</ol>
<p>如果大家创建工程时没有加入对应的sock支持，我们可以参照上述列表手工加入。
</p>
<p>对于前文所述的sockutil.h文件，加入如下初始代码： </p>
<pre><font color="#0000ff"><strong>#if</strong></font> !defined(__SOCKET_UTILITY_HEADER__)<br />
<font color="#0000ff"><strong>#define</strong></font> __SOCKET_UTILITY_HEADER__<br />
<font color="#0000ff"><strong>#if</strong></font> _MSC_VER &gt; 1000<br />
<font color="#0000ff"><strong>#pragma</strong></font> once<br />
<font color="#0000ff"><strong>#endif</strong></font> // _MSC_VER &gt; 1000<br />
<font color="#0000ff"><strong>#endif</strong></font> <br />
</pre>
<p>对于sockutil.cpp文件，则加入如下初始代码： </p>
<pre><font color="#0000ff"><strong>#include</strong></font> "stdafx.h"<br />
<font color="#0000ff"><strong>#include</strong></font> "sockutil.h"<br />
<font color="#0000ff"><strong>#ifdef</strong></font> _DEBUG<br />
<font color="#0000ff"><strong>#define</strong></font> <font color="#0000ff"><strong>new</strong></font> DEBUG_NEW<br />
<font color="#0000ff"><strong>#undef</strong></font> THIS_FILE<br />
<font color="#0000ff"><strong>static</strong></font> <font color="#0000ff"><strong>char</strong></font> THIS_FILE[] = __FILE__;<br />
<font color="#0000ff"><strong>#endif</strong></font><br />
<br />
</pre>
<h2>4.2 准备错误处理方式</h2>
<p>在编制每个程序之前，我习惯是为错误处理定制一个统一的处理方式。在以后的例子中，我会按照如下的方式处理错误：在一个log文件中记录错误发生的位置（文件、行号)，错误号和字符串解释。为了实现这个目的，我在sockutil.cpp定义如下的函数： </p>
<pre><font color="#0000ff"><strong>bool</strong></font> ErrorHandle(LPCTSTR expression, <font color="#0000ff"><strong>bool</strong></font> bFalse, LPCTSTR file, UINT line)<br />
{<br />
<font color="#0000ff"><strong>if</strong></font>(!bFalse)<br />
{//没有错误，直接返回<br />
<font color="#0000ff"><strong>return</strong></font> <font color="#0000ff"><strong>false</strong></font>;<br />
}<br />
FILE * fp;<br />
fp = fopen("demo.log","at");<br />
<font color="#0000ff"><strong>if</strong></font>(NULL == fp)<br />
{//如果文件打开失败，放弃记录<br />
<font color="#0000ff"><strong>return</strong></font> <font color="#0000ff"><strong>true</strong></font>;<br />
}<br />
//获得错误码<br />
DWORD ErrorCode = GetLastError();<br />
//格式化成字符串格式<br />
LPVOID lpMsgBuf;<br />
FormatMessage( <br />
FORMAT_MESSAGE_ALLOCATE_BUFFER | <br />
FORMAT_MESSAGE_FROM_SYSTEM | <br />
FORMAT_MESSAGE_IGNORE_INSERTS,<br />
NULL,<br />
ErrorCode ,<br />
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language<br />
(LPTSTR) &amp;lpMsgBuf,<br />
0,<br />
NULL <br />
);<br />
//输出到文件<br />
fprintf(fp,_T("file=%s,line=%u"n%d:%s"n"),file,line,ErrorCode, (LPCTSTR)lpMsgBuf);<br />
// 释放空间，该空间由FormatMessage分配<br />
LocalFree( lpMsgBuf );<br />
//关闭文件<br />
fclose(fp);<br />
<br />
<font color="#0000ff"><strong>return</strong></font> <font color="#0000ff"><strong>true</strong></font>;<br />
}<br />
</pre>
<p>在sockutil.h中，添加如下代码： </p>
<pre><font color="#0000ff"><strong>bool</strong></font> ErrorHandle(LPCTSTR expression, <font color="#0000ff"><strong>bool</strong></font> bFalse, LPCTSTR file, UINT line);<br />
<font color="#0000ff"><strong>#define</strong></font> ERRORHANDLE(expression) ErrorHandle(#expression,(expression),__FILE__,__LINE__)<br />
</pre>
<h2>4.3 核心代码</h2>
<p>根据前文，设计该服务端套接字主函数如下： </p>
<pre><font color="#0000ff"><strong>void</strong></font> sockmain(LPCTSTR ip, UINT port)<br />
{<br />
<br />
SOCKET hSocket;<br />
hSocket = socket(AF_INET,SOCK_STREAM,0);<br />
<font color="#0000ff"><strong>if</strong></font>(ERRORHANDLE(hSocket == INVALID_SOCKET))<br />
{<br />
<font color="#0000ff"><strong>return</strong></font>;<br />
}<br />
sockaddr_in addr;<br />
InitializeAddress(inet_addr(ip), port, addr);<br />
<font color="#0000ff"><strong>if</strong></font>(ERRORHANDLE(SOCKET_ERROR == bind(hSocket, (<font color="#0000ff"><strong>const</strong></font> sockaddr*) &amp; addr, <font color="#0000ff"><strong>sizeof</strong></font>(addr))))<br />
{<br />
closesocket(hSocket);<br />
<font color="#0000ff"><strong>return</strong></font>;<br />
}<br />
<font color="#0000ff"><strong>if</strong></font>(ERRORHANDLE(SOCKET_ERROR == listen(hSocket,5)))<br />
{<br />
closesocket(hSocket);<br />
<font color="#0000ff"><strong>return</strong></font>;<br />
}<br />
SOCKET hClient;<br />
<font color="#0000ff"><strong>int</strong></font> size;<br />
<font color="#0000ff"><strong>char</strong></font> buffer[2048];<br />
<font color="#0000ff"><strong>int</strong></font> length;<br />
size = <font color="#0000ff"><strong>sizeof</strong></font>(addr);<br />
<font color="#0000ff"><strong>while</strong></font>(INVALID_SOCKET != (hClient = accept(hSocket,(sockaddr*)&amp;addr, &amp; size)))<br />
{<br />
size = <font color="#0000ff"><strong>sizeof</strong></font>(addr);<br />
<font color="#0000ff"><strong>while</strong></font>((length = recv(hClient, buffer, <font color="#0000ff"><strong>sizeof</strong></font>(buffer),0)) &gt; 0)<br />
{<br />
SendData(hClient,buffer, length);<br />
}<br />
closesocket(hClient);<br />
}<br />
closesocket(hSocket);<br />
<br />
<font color="#0000ff"><strong>return</strong></font>;<br />
}<br />
</pre>
<p>其中，InitializeAddress定义如下： </p>
<pre><font color="#0000ff"><strong>void</strong></font> InitializeAddress(DWORD ip, UINT port, sockaddr_in &amp; addr)<br />
{<br />
memset(&amp;addr,0,<font color="#0000ff"><strong>sizeof</strong></font>(addr));<br />
addr.sin_family  = AF_INET;<br />
addr.sin_addr.s_addr= ip;<br />
addr.sin_port       = htons(port);<br />
}<br />
</pre>
SendData定义如下：
<pre><font color="#0000ff"><strong>int</strong></font> SendData(SOCKET hSocket, <font color="#0000ff"><strong>const</strong></font> <font color="#0000ff"><strong>char</strong></font> * data, <font color="#0000ff"><strong>int</strong></font> length)<br />
{<br />
<font color="#0000ff"><strong>int</strong></font> result;<br />
<font color="#0000ff"><strong>int</strong></font> pos = 0;<br />
<font color="#0000ff"><strong>while</strong></font>(pos &lt; length)<br />
{<br />
result = send(hSocket, data + pos, length - pos , 0);<br />
<font color="#0000ff"><strong>if</strong></font>(result &gt; 0 )<br />
{<br />
pos += result;<br />
}<font color="#0000ff"><strong>else</strong></font>{<br />
<font color="#0000ff"><strong>return</strong></font> result;<br />
}<br />
}<br />
<font color="#0000ff"><strong>return</strong></font> length;<br />
}<br />
</pre>
<h2>4.4 启动该任务</h2>
<p>为了启动服务端套接字，我们可以在对话框资源的OK按钮上双击，然后在OnOK中添加如下代码 </p>
<pre>   sockmain("0.0.0.0",2000);<br />
</pre>
<p>当我们启动该工程，并点击OK按钮，就可以通过telnet来测试是否有回显功能了。</p>
<img src ="http://www.blogjava.net/wangxinsh55/aggbug/212345.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/wangxinsh55/" target="_blank">SIMONE</a> 2008-07-03 15:19 <a href="http://www.blogjava.net/wangxinsh55/archive/2008/07/03/212345.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>socket 程序设计(3) － 服务端套接字</title><link>http://www.blogjava.net/wangxinsh55/archive/2008/07/03/212344.html</link><dc:creator>SIMONE</dc:creator><author>SIMONE</author><pubDate>Thu, 03 Jul 2008 07:17:00 GMT</pubDate><guid>http://www.blogjava.net/wangxinsh55/archive/2008/07/03/212344.html</guid><wfw:comment>http://www.blogjava.net/wangxinsh55/comments/212344.html</wfw:comment><comments>http://www.blogjava.net/wangxinsh55/archive/2008/07/03/212344.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/wangxinsh55/comments/commentRss/212344.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/wangxinsh55/services/trackbacks/212344.html</trackback:ping><description><![CDATA[<div>
<p>服务端套接字是编程最简单的一个部分，甚至在各种环境下都可以用类似的代码。对于一个服务端套接字而言，他的基本工作包括：</p>
<ol>
    <li>初始化
    </li>
    <li>创建套接字
    </li>
    <li>给套接字捆绑一个本地地址
    </li>
    <li>【可选】设置套接字属性
    </li>
    <li>调用listen函数
    </li>
    <li>进入accept循环，接受来自客户端的请求
    </li>
    <li>对PCS进行管理
    </li>
    <li>释放服务端套接字所占用的资源 </li>
</ol>
<h2>3.1 初始化</h2>
<p>对于每个需要处理套接字的程序，在调用任何其他套接字函数之前，必须首先调用<a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winsock/winsock/wsastartup_2.asp">WSAStartup</a>函数。如果不调用它，其他函数调用会失败，并返回WSANOTINITIALISED错误码，表示WinSock库还没有初始化。对于除了其他操作系统，初始化的方法会不一样，请参见对应的文档找到初始化方法。</p>
<p><a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winsock/winsock/wsastartup_2.asp">WSAStartup</a>的函数原型为： </p>
<pre><strong><font color="#0000ff" size="4">int</font></strong> <a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winsock/winsock/wsastartup_2.asp">WSAStartup</a>(<br />
WORD wVersionRequested,<br />
LPWSADATA lpWSAData<br />
);</pre>
<p>其中，各个参数的含义如下：
<table border="0">
    <tbody>
        <tr>
            <td>wVersionRequested:
            </td>
            <td>本程序所需要的最低版本号。请注意，MSDN中所说的是本程序可能用到的最高版本的函数，其含义和我所说的一样。</td>
        </tr>
        <tr>
            <td>lpWSAData
            </td>
            <td>返回<a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winsock/winsock/wsadata_2.asp">WSADATA</a>结构，说明WinSock库当前的实现细节</td>
        </tr>
    </tbody>
</table>
</p>
<p>该函数成功时返回0，否则可能返回如下一些错误码：
<table border="0">
    <tbody>
        <tr>
            <td>WSASYSNOTREADY
            </td>
            <td>底层网络系统未准备好
            </td>
        </tr>
        <tr>
            <td>WSAVERNOTSUPPORTED
            </td>
            <td>所要求版本号本实现不支持
            </td>
        </tr>
        <tr>
            <td>WSAEINPROGRESS
            </td>
            <td>一个阻塞性套接字操作未完成
            </td>
        </tr>
        <tr>
            <td>WSAEPROCLIM
            </td>
            <td>达到当前实现所支持的最大任务数
            </td>
        </tr>
        <tr>
            <td>WSAEFAULT
            </td>
            <td>lpWSAData是一个非法指针 </td>
        </tr>
    </tbody>
</table>
</p>
<p>一般用户并不关心实现细节，只要当前实现库满足最低版本需求即可。常见代码为： </p>
<pre><font size="4"> WORD wVersion = MAKEWORD(2,2);//最低版本2.2<br />
WSADATA WSAData;<br />
<font color="#0000ff"><strong>int</strong></font> nResult;<br />
<font color="#0000ff"><strong>if</strong></font>(ERROR_SUCCESS != (nResult = <a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winsock/winsock/wsastartup_2.asp"><font size="3">WSAStartup</font></a>(wVersion,&amp;WSAData)))<br />
{<br />
ReportError("WSAStartup", nResult);<br />
<font color="#0000ff"><strong>return</strong></font> -1;<br />
}</font></pre>
<h2>3.2 创建套接字</h2>
<p>每个套接字任务都从创建套接字开始。我们可以用<a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winsock/winsock/socket_2.asp">socket</a>函数来创建套接字，该函数的原型为： </p>
<pre>SOCKET <a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winsock/winsock/socket_2.asp">socket</a>(<br />
<strong><font color="#0000ff" size="4">int</font></strong> af,<br />
<strong><font color="#0000ff" size="4">int</font></strong> type,<br />
<strong><font color="#0000ff" size="4">int</font></strong> protocol<br />
)<br />
</pre>
其中，各个参数的含义为：
协议号，说明该套接字所处理的协议。他的可选值随前面两个参数不同而不同。似乎在RAW协议中用的比较多，大家可以在ROUTPROT.h中找到类似定义。
<table border="0">
    <tbody>
        <tr>
            <td>af</td>
            <td>地址族，说明该socket支持的地址类型。我们可以在winsock2.h中找到所支持的地址族。不过一般来说，对于TCP/IP编程，我们都会设置为AF_INET</td>
        </tr>
        <tr>
            <td>type
            </td>
            <td>协议类型，Winsock2.h中列出了5种类型，我们一般会使用其中的三种，SOCK_STREAM表示流协议，SOCK_DGRAM表示数据报协议，SOCK_RAW表示原始套接字。我会在数据传输部分详细解释这些内容</td>
        </tr>
        <tr>
            <td>protocol</td>
        </tr>
    </tbody>
</table>
<p>用于侦听的套接字需要是流套接字，下面代码会创建这样的套接字： </p>
<pre>    SOCKET hSocket;<br />
<font color="#0000ff"><strong>int</strong></font> a = PROTO_ICMP;<br />
hSocket = <a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winsock/winsock/socket_2.asp">socket</a>(AF_INET,SOCK_STREAM,0);<br />
<font color="#0000ff"><strong>if</strong></font>(ERRORHANDLE(hSocket == INVALID_SOCKET))<br />
{<br />
WSACleanup();<br />
<font color="#0000ff"><strong>return</strong></font> -1;<br />
}<br />
</pre>
<h2>3.3 捆绑本地地址</h2>
<p>每个套接字必须有一个地址才能和对方通讯。<a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winsock/winsock/bind_2.asp">bind</a>函数用于捆绑地址，它的函数原型为： </p>
<pre><strong><font color="#0000ff" size="4">int</font></strong> <a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winsock/winsock/bind_2.asp">bind</a>(<br />
SOCKET s,<br />
<strong><font color="#0000ff" size="4">const</font></strong> <strong><font color="#0000ff" size="4">struct</font></strong> sockaddr* name,<br />
<strong><font color="#0000ff" size="4">int</font></strong> namelen<br />
);<br />
</pre>
<p>各个参数含义如下：<br />
<table border="0">
    <tbody>
        <tr>
            <td>s
            </td>
            <td>套接字号</td>
        </tr>
        <tr>
            <td>name
            </td>
            <td>地址信息：需要注意的是，套接字接口是给多种协议共享的，sockaddr结构只是一个占位符，不同协议使用不同的地址结构，例如，TCP/IP编程使用的结构是sockaddr_in</td>
        </tr>
        <tr>
            <td>namelen</td>
            <td>地址结构的长度，加入这个参数的原因也就是因为不同协议有不同的结构</td>
        </tr>
    </tbody>
</table>
</p>
<p>需要注意的，bind函数只能给socket绑定本机的IP地址，如果你给出的地址信息是其他机器的，则必然会失败。此时该函数返回SOCKET_ERROR，WSAGetLastError则返回WSAEADDRNOTAVAIL。
</p>
<p>如果没有特殊需求，应该设置该结构的IP地址为INADDR_ANY。对于端口，服务端套接字需要指定一个端口，而客户端端口最好设置为0，让系统选择一个可用端口。
</p>
<p>下面代码初始化一个地址结构：</p>
<pre><font color="#0000ff"><strong>void</strong></font> InitializeAddress(DWORD ip, UINT port, sockaddr_in &amp; addr)<br />
{ <br />
memset(&amp;addr,0,<font color="#0000ff"><strong>sizeof</strong></font>(addr)); <br />
addr.sin_family  = AF_INET; <br />
addr.sin_addr.s_addr= ip; <br />
addr.sin_port       = htons(port);<br />
}</pre>
<p>下面代码则把一个套接字绑定到本机2000端口上：</p>
<pre><font color="#0000ff"><strong>if</strong></font>(ERRORHANDLE(SOCKET_ERROR == <a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winsock/winsock/bind_2.asp">bind</a>(hSocket, (<font color="#0000ff"><strong>const</strong></font> sockaddr*) &amp; addr, <font color="#0000ff"><strong>sizeof</strong></font>(addr)))) <br />
{  <br />
closesocket(hSocket);  <br />
WSACleanup();  <br />
<font color="#0000ff"><strong>return</strong></font> -1; <br />
}</pre>
<h2>3.4 进入侦听状态</h2>
<p>当我们创建一个套接字，并绑定了地址后，我们需要设置这个套接字进入侦听状态，进入侦听状态后，该套接字就可以处理来自客户端的链接请求。</p>
<p>listen函数设置套接字进入侦听状态，其函数原型为：</p>
<pre><font color="#0000ff"><strong>int</strong></font> <a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winsock/winsock/listen_2.asp">listen</a>(<br />
SOCKET s,<br />
<font color="#0000ff"><strong>int</strong></font> backlog<br />
);</pre>
<p>对于刚开始编程的人，最容易误解的是backlog参数。许多人以为这就是该套接字最多能接收的链接的数目。实际上，一个套接字能接受的链接的数目不受这个参数控制，它只受系统资源的限制。例如对于linux，套接字用文件句柄实现，那么它可能受最大文件句柄数的限制。
</p>
<p>这个参数的含义是最多未决连接的数目，也就是连接请求已经到了服务端套接字，但是用户还没有调用accept的套接字数目。对于WinSock2，这个参数最大值为5。
</p>
<p>下面示例代码说明了如何调用listen：</p>
<pre><font color="#0000ff"><strong>if</strong></font>(ERRORHANDLE(SOCKET_ERROR == <a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winsock/winsock/listen_2.asp">listen</a>(hSocket,5))) <br />
{  <br />
closesocket(hSocket);  <br />
WSACleanup();  <br />
<font color="#0000ff"><strong>return</strong></font> -1; <br />
}</pre>
<h2>3.5 accept循环</h2>
<p>当一个套接字处于侦听状态以后，我们就可以循环调用<a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winsock/winsock/accept_2.asp">accept</a>来接受新连接。accept函数的原型如下：</p>
<pre>SOCKET <a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winsock/winsock/accept_2.asp">accept</a>(<br />
SOCKET s,<br />
<font color="#0000ff"><strong>struct</strong></font> sockaddr* addr,<br />
<font color="#0000ff"><strong>int</strong></font>* addrlen<br />
);<br />
</pre>
<p>这个函数的参数说明和前面bind的一样。需要说明的是，在MSDN中说后面两个参数都是out参数，经过我的测试，结论并不一样。对于
addrlen参数，应该是一个in/out参数，也就是说，如果第二个参数是一个结构指针，则第三个参数必须是一个整型变量的指针，该整型变量还必须被
设置为该结构的长度。 </p>
<h2>3.6 PCS管理</h2>
<p>由于一个一个服务端套接字可能接收无数个PCS，如何管理这些PCS就成为一个问题。不同的程序员有自己不同的管理方式，在此我就不准备细讲了。</p>
</div>
<img src ="http://www.blogjava.net/wangxinsh55/aggbug/212344.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/wangxinsh55/" target="_blank">SIMONE</a> 2008-07-03 15:17 <a href="http://www.blogjava.net/wangxinsh55/archive/2008/07/03/212344.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>socket 程序设计(2) － 地址</title><link>http://www.blogjava.net/wangxinsh55/archive/2008/07/03/212342.html</link><dc:creator>SIMONE</dc:creator><author>SIMONE</author><pubDate>Thu, 03 Jul 2008 07:16:00 GMT</pubDate><guid>http://www.blogjava.net/wangxinsh55/archive/2008/07/03/212342.html</guid><wfw:comment>http://www.blogjava.net/wangxinsh55/comments/212342.html</wfw:comment><comments>http://www.blogjava.net/wangxinsh55/archive/2008/07/03/212342.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/wangxinsh55/comments/commentRss/212342.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/wangxinsh55/services/trackbacks/212342.html</trackback:ping><description><![CDATA[<div>
<a href="http://blog.vckbase.com/arong/archive/2005/10/06/12914.html">说明</a>&nbsp;<a href="http://blog.vckbase.com/arong/archive/2005/10/02/12768.html">前一篇</a>
<p><br />
所有的WinSock函数都使用sockaddr结构来传递地址信息，该结构定义如下：
</p>
<pre>struct sockaddr {<blockquote><br />
u_short sa_family; /* address family */<br />
char    sa_data[14];/* up to 14 bytes of direct address */<br />
</blockquote>};</pre>
<p>需要注意的是，socket并不只是为TCP服务的，它支持多种协议，而各种协议的地址格式又大相径庭。因此，我们在socket相关的API中不
可能用同样的地址结构来描述地址信息，这里的sockaddr只是一个占位符的角色，我们在实际编程中必须替换乘合适的地址类型。</p>
<p>对于TCP/IP族，我们需要用的结构类型是sockaddr_in，该结构定义如下： </p>
<pre>struct sockaddr_in {<blockquote><br />
short   sin_family;<br />
u_short sin_port;<br />
struct  in_addr sin_addr;<br />
char    sin_zero[8];</blockquote><br />
};<br />
</pre>
其中in_addr定义为：
<pre>struct in_addr {<br />
union {<br />
struct { u_char s_b1,s_b2,s_b3,s_b4; } S_un_b;<br />
struct { u_short s_w1,s_w2; } S_un_w;<br />
u_long S_addr;<br />
} S_un;<br />
#define s_addr  S_un.S_addr<br />
/* can be used for most tcp &amp; ip code */<br />
#define s_host  S_un.S_un_b.s_b2<br />
/* host on imp */<br />
#define s_net   S_un.S_un_b.s_b1<br />
/* network */<br />
#define s_imp   S_un.S_un_w.s_w2<br />
/* imp */<br />
#define s_impno S_un.S_un_b.s_b4<br />
/* imp # */<br />
#define s_lh    S_un.S_un_b.s_b3<br />
/* logical host */<br />
};<br />
</pre>
<p>需要注意的是，这个sockaddr_in结构和sockaddr结构尺寸一样，我不清楚这是巧合还是必须遵守的一个准则。在我看来，这个结构不一样也是可以的。
</p>
<p>我不打算一一介绍各个宏和域的含义，因为绝大多数人都不会记住这个。我只想简要介绍一下如何初始化这个地址信息</p>
<ol type="1">
    <li>sa_family：这个域描述了地址族信息。对于TCP/IP，这个值必须设置为AF_INET。有兴趣的朋友可以到WinSock.H中找找看它还支持哪些值。
    </li>
    <li>sin_port：端口号，对于我们提供的端口号，必须用htons转换一下再赋值，方法是：<br />
    addr.sin_port = htons(port);
    </li>
    <li>sin_addr：地址，这里应该是IP地址。我们可以用inet_addr函数从点分式IP地址转换得到这个IP地址，方法是：<br />
    addr.sin_addr.s_addr = inet_addr("100.101.102.103");<br />
    注意：这里使用了宏s_addr，该宏的定义请参考上文。
    </li>
    <li>sin_zero：填充信息，必须设置为0。初学编程的人往往忘记初始化这个域，根据我的经验，这会导致函数调用失败。 </li>
</ol>
<p>由于API中都使用sockaddr结构，因此在使用时必须进行强制类型转换，并提供结构尺寸信息。下面就是accept函数调用时的例子： </p>
<pre>sockaddr_in addr;<br />
memset(&amp;addr, 0, sizeof(addr));<br />
addr.sa_family = AF_INET;<br />
int size = sizeof(addr);<br />
SOCKET sd = accept(serversd, (sockaddr*)&amp;addr, &amp;size);<br />
</pre>
</div>
<img src ="http://www.blogjava.net/wangxinsh55/aggbug/212342.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/wangxinsh55/" target="_blank">SIMONE</a> 2008-07-03 15:16 <a href="http://www.blogjava.net/wangxinsh55/archive/2008/07/03/212342.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>socket 程序设计(1) － 开篇：主机的角色</title><link>http://www.blogjava.net/wangxinsh55/archive/2008/07/03/212341.html</link><dc:creator>SIMONE</dc:creator><author>SIMONE</author><pubDate>Thu, 03 Jul 2008 07:15:00 GMT</pubDate><guid>http://www.blogjava.net/wangxinsh55/archive/2008/07/03/212341.html</guid><wfw:comment>http://www.blogjava.net/wangxinsh55/comments/212341.html</wfw:comment><comments>http://www.blogjava.net/wangxinsh55/archive/2008/07/03/212341.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/wangxinsh55/comments/commentRss/212341.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/wangxinsh55/services/trackbacks/212341.html</trackback:ping><description><![CDATA[<div>
<a href="http://blog.vckbase.com/arong/archive/2005/10/06/12914.html">说明</a> <a href="http://blog.vckbase.com/arong/archive/2005/10/06/12913.html">下一篇</a> <br />
<em>由于我对TCP稍微熟悉，所以本系列文章只描述socket（套接字）接口的TCP编程</em> <br />
<p>在IT领域中，大家经常听说Client/Server的概念，这个概念是描述了提供服务的一方（服务器）和接受服务的一方（客户端）之间的拓扑结构。举例来说，<a href="http://www.vckbase.com/">http://www.vckbase.com</a>这个网站提供大家交流和娱乐的服务，他们的计算机对于我们而言就是服务器，而我们的计算机则是客户端。一般而言，服务器功能比较强大，一个服务器能提供服务给多个客户端。
</p>
<p>对于socket设计而言，我们往往也提到一个服务器端和客户端的概念，但是它的概念和前面而言基本是不一样的。这里的概念其实是指在开始通讯时谁先发起连接的过程。</p>
<p>对于通讯的双方而言，存在一个建立对话通道的过程，该过程的建立必然是一方主动发起的。我们称呼主动建立链路的一方为客户端，而另外一方为服务器端。(至少我个人这么称呼，不知道业界是不是都这么说)</p>
<p>在通讯过程中，服务器端必须在某个预先约定的端口等待其他主机建立链路，这个过程称为侦听(Listen)。客户端主动建立链路的过程成为连接
(Connect)。当服务器端套接字接到一个连接请求后，会生成一个新的套接字。服务器端主机就通过这个套接字和客户端主机通讯。</p>
<p>在整个过程中，涉及到三个套接字，他们分别是服务器端套接字（我一般称呼它为server
socket)、客户端套接字（一般我称呼它为client
socket）和服务器端套接字创建出来的套接字。在编程过程中，第三种套接字除了不会主动建立链路外，功能和client
socket完全一致，因此我也把它称为client socket。为了区别，对于客户端的client
socket，大家可以称呼它为主动client socket(Active Client Socket,
ACS)，而对服务器端的那个客户端套接字，则称为被动client socket(Passive Client Socket,
PCS)。一般情况下，我们没有必要区分ACS和PCS，因为PCS的功能是ACS的一个部分，ACS只多一项功能而已。在后文中，我将不区分这两种
client socket</p>
<p>对于server socket, 它有如下功能：
</p>
<ol type="1">
    <li>等待客户端建立连接(listen)
    </li>
    <li>当客户端建立发送连接请求时，能接受请求，完成链路建立(accept)
    </li>
    <li>关闭(close) </li>
</ol>
<p>对于client socket，它有如下功能:
</p>
<ol type="1">
    <li>建立链路(connect)
    </li>
    <li>发送数据(send)
    </li>
    <li>接收数据(recv)
    </li>
    <li>关闭(close) </li>
</ol>
<p>一个简单的通讯过程应该这样：
</p>
<ul>
    <li>server socket开始侦听(listen)
    </li>
    <li>client socket开始连接(connect)
    </li>
    <li>server socket接受连接(accept)
    </li>
    <li>ACS和PCS开始互相发送数据(send/recv)
    </li>
    <li>ACS或PCS关闭链路(close)
    </li>
    <li>server socket关闭(close) </li>
</ul>
<p>本系列将根据以上过程介绍socket编程的方方面面。由于阻塞套接字相对简单，我会先从阻塞套接字（也就是伯可力套接字）编程开始，之间会穿插一些多线程的知识。很多方面我也没用过，所以有些东西只能边试边写，和大家探讨。</p>
</div>
<img src ="http://www.blogjava.net/wangxinsh55/aggbug/212341.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/wangxinsh55/" target="_blank">SIMONE</a> 2008-07-03 15:15 <a href="http://www.blogjava.net/wangxinsh55/archive/2008/07/03/212341.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>MFC多线程编程注意事项</title><link>http://www.blogjava.net/wangxinsh55/archive/2008/05/28/203464.html</link><dc:creator>SIMONE</dc:creator><author>SIMONE</author><pubDate>Wed, 28 May 2008 05:08:00 GMT</pubDate><guid>http://www.blogjava.net/wangxinsh55/archive/2008/05/28/203464.html</guid><wfw:comment>http://www.blogjava.net/wangxinsh55/comments/203464.html</wfw:comment><comments>http://www.blogjava.net/wangxinsh55/archive/2008/05/28/203464.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/wangxinsh55/comments/commentRss/203464.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/wangxinsh55/services/trackbacks/203464.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: MFC多线程编程注意事项PeterLee整理 2008-05-261.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 表现——错误示例关于启动线程时传输窗口对象（指针？句柄？）的问题： &nbsp; &nbsp; &nbsp; &nbsp; 在选择菜单中的开始线程后： &nbsp; &nbsp; void &nbsp; cmainfra...&nbsp;&nbsp;<a href='http://www.blogjava.net/wangxinsh55/archive/2008/05/28/203464.html'>阅读全文</a><img src ="http://www.blogjava.net/wangxinsh55/aggbug/203464.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/wangxinsh55/" target="_blank">SIMONE</a> 2008-05-28 13:08 <a href="http://www.blogjava.net/wangxinsh55/archive/2008/05/28/203464.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>共享内存封装类 </title><link>http://www.blogjava.net/wangxinsh55/archive/2008/05/16/200807.html</link><dc:creator>SIMONE</dc:creator><author>SIMONE</author><pubDate>Fri, 16 May 2008 02:36:00 GMT</pubDate><guid>http://www.blogjava.net/wangxinsh55/archive/2008/05/16/200807.html</guid><wfw:comment>http://www.blogjava.net/wangxinsh55/comments/200807.html</wfw:comment><comments>http://www.blogjava.net/wangxinsh55/archive/2008/05/16/200807.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/wangxinsh55/comments/commentRss/200807.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/wangxinsh55/services/trackbacks/200807.html</trackback:ping><description><![CDATA[<div>http://blog.chinaunix.net/u1/59687/showart_496412.html<br />
<br />
本文介绍一个共享内存封装类，使共享内存的使用更简单化，特别适合更懒的程序员使用:-)<br />
<br />
<strong><img height="16" src="http://vckbase.com/document/image/paragraph.gif" width="14"  alt="" /> 一、实现目标：</strong>简单化使用共享内存<br />
<br />
<strong><img height="16" src="http://vckbase.com/document/image/paragraph.gif" width="14"  alt="" /> 二、使用说明</strong>：<br />
<br />
<strong>1. 创建共享内存CSFMServer对象</strong>, 需要为CSFMServer对象指定专用的名字，只要<br />
系统中存在一个这样的对象，就可以在其他程序中简单方便地使用该共享内存。
<pre>CSFMServer(char *szFileName, char *szMapName, DWORD dwSize);
Create(char *szFileName, char *szMapName, DWORD dwSize); </pre>
参数1:NULL或指定的文件(将创建或打开并读写/麻烦) <br />
参数2:要创建的共享内存对象名 <br />
参数3:要创建的共享内存对象大小 <br />
<br />
例如
<pre>m_SFMS.Create(NULL, "_ZZZ_OBJ_", 1);</pre>
<strong>2. 本地使用共享内存</strong> <br />
使用 LPVOID GetBuffer() 返回共享内存地址,例如
<pre>char *p = (char*)m_SFMS.GetBuffer();
if (p)
strcpy(p, "1234567890");</pre>
<strong>3. 创建共享内存CSFMClient对象</strong>，也需要为CSFMClient对象指定专用的名字（上一步使用的那个），即可使用共享内存。
<pre>CSFMClient(DWORD dwAccess, char *szMapName);
Open(DWORD dwAccess, char *szMapName);
</pre>
参数1:共享内存对象访问方式(FILE_MAP_READ|FILE_MAP_WRITE)<br />
参数2:共享内存对象名<br />
<br />
例如:
<pre>CSFMClient *pCSFMC = new CSFMClient(FILE_MAP_READ, "_OBJ_ZZZ_");</pre>
<strong>4. 本地使用共享内存</strong><br />
使用 LPVOID GetBuffer() 返回共享内存地址，例如
<pre>char *p = (char*)pCSFMC-&gt;GetBuffer();
if (p) strcpy(p, "1234567890");
</pre>
<br />
<strong><img height="16" src="http://vckbase.com/document/image/paragraph.gif" width="14"  alt="" /> 三、该类的具体实现代码</strong>如下:<br />
<br />
<font color="#009900">//------------------------------------------------<br />
// 2002/07/05 <br />
// awzzz <br />
// SFMMem.h: interface for the CSFMServer class. <br />
//------------------------------------------------</font>
<pre>#if !defined(AFX_SFMSERVER_H__2D76A439_6388_4B07_AE7A_C82F458642ED__INCLUDED_)
#define AFX_SFMSERVER_H__2D76A439_6388_4B07_AE7A_C82F458642ED__INCLUDED_
#if _MSC_VER &gt; 1000
#pragma once
#endif // _MSC_VER &gt; 1000
#define DEFAULT_FILENAME NULL
#define DEFAULT_MAPNAME  "_SFM_OBJ_"
#define DEFAULT_MAPSIZE  (0xFFFF + 1)
</pre>
<font color="#009900">// Shared FileMap Server </font>
<pre>class CSFMServer
{
public:
CSFMServer();
virtual ~CSFMServer();
CSFMServer(char *szFileName, char *szMapName, DWORD dwSize);
protected:
HANDLE m_hFile;
HANDLE m_hFileMap;
LPVOID m_lpFileMapBuffer;
char *m_pFileName;
char *m_pMapName;
DWORD m_dwSize;
int  m_iCreateFlag;
private:
void _Init();
void _Destory();
public:
void Create(char *szFileName, char *szMapName, DWORD dwSize);
LPVOID GetBuffer();
DWORD GetSize();
};
</pre>
<font color="#009900">// Shared FileMap Client<br />
</font>
<pre>class CSFMClient
{
public:
CSFMClient();
virtual ~CSFMClient();
CSFMClient(DWORD dwAccess, char *szMapName);
protected:
HANDLE m_hFileMap;
LPVOID m_lpFileMapBuffer;
char *m_pMapName;
int  m_iOpenFlag;
private:
void _Init();
void _Destory();
public:
void Open(DWORD dwAccess, char *szMapName);
LPVOID GetBuffer();
DWORD GetSize();
};
#endif // !defined(AFX_SFMSERVER_H__2D76A439_6388_4B07_AE7A_C82F458642ED__INCLUDED_)
</pre>
<font color="#009900">//------------------------------------------------------<br />
// SFMMem.cpp: implementation of the CSFMServer class. <br />
//------------------------------------------------------</font><br />
<pre>#include "stdafx.h"
#include "SFMMem.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
<font color="#009900">// Construction/Destruction</font>
CSFMServer::CSFMServer()
{
_Init();
//
Create(DEFAULT_FILENAME, DEFAULT_MAPNAME, DEFAULT_MAPSIZE);
}
CSFMServer::~CSFMServer()
{
_Destory();
}
CSFMServer::CSFMServer(char *szFileName, char *szMapName, DWORD dwSize)
{
_Init();
//
Create(szFileName, szMapName, dwSize);
}
void CSFMServer::_Init()
{
m_hFile = NULL;
m_hFileMap = NULL;
m_lpFileMapBuffer = NULL;
m_pFileName = NULL;
m_pMapName = NULL;
m_dwSize = 0;
m_iCreateFlag = 0;
}
void CSFMServer::_Destory()
{
if (m_lpFileMapBuffer)
{
UnmapViewOfFile(m_lpFileMapBuffer);
m_lpFileMapBuffer = NULL;
}
if (m_hFileMap)
{
CloseHandle(m_hFileMap);
m_hFileMap = NULL;
}
if (m_hFile &amp;&amp; m_hFile != INVALID_HANDLE_VALUE)
{
CloseHandle(m_hFile);
m_hFile = NULL;
}
if (m_pFileName)
{
free(m_pFileName);
m_pFileName = NULL;
}
if (m_pMapName)
{
free(m_pMapName);
m_pMapName = NULL;
}
_Init();
}
void CSFMServer::Create(char *szFileName, char *szMapName, DWORD dwSize)
{
if (m_iCreateFlag)
_Destory();
if (szFileName)
m_pFileName = _strdup(szFileName);
//else m_pFileName = NULL;
if (szMapName)
m_pMapName = _strdup(szMapName);
else m_pMapName = _strdup(DEFAULT_MAPNAME);
if (dwSize &gt; 0)
m_dwSize = dwSize;
else m_dwSize = DEFAULT_MAPSIZE;
if (m_pFileName)
{
// file
m_hFile = CreateFile(
m_pFileName,
GENERIC_READ|GENERIC_WRITE,
FILE_SHARE_READ|FILE_SHARE_WRITE,
NULL,
OPEN_ALWAYS,//OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL
);
}
else
{
// system
m_hFile = (HANDLE)0xFFFFFFFF;
}
if (m_hFile)
{
m_hFileMap = CreateFileMapping(
m_hFile,
NULL,
PAGE_READWRITE,
0,
m_dwSize,
m_pMapName
);
//使只有一个CSFMServer对象能操作内存对象
//if (m_hFileMap != NULL &amp;&amp; ERROR_ALREADY_EXISTS == GetLastError())
//{
// CloseHandle(m_hFileMap);
// m_hFileMap = NULL;
//}
}
if (m_hFileMap)
{
m_lpFileMapBuffer = MapViewOfFile(
m_hFileMap,
FILE_MAP_ALL_ACCESS,//FILE_MAP_WRITE|FILE_MAP_READ,
0,
0,
m_dwSize
);
}
m_iCreateFlag = 1;
}
LPVOID CSFMServer::GetBuffer()
{
return (m_lpFileMapBuffer)?(m_lpFileMapBuffer):(NULL);
}
DWORD CSFMServer::GetSize()
{
return m_dwSize;
}
<font color="#009900">// Construction/Destruction</font>
CSFMClient::CSFMClient()
{
_Init();
//
Open(FILE_MAP_READ, DEFAULT_MAPNAME);
}
CSFMClient::~CSFMClient()
{
_Destory();
}
CSFMClient::CSFMClient(DWORD dwAccess, char *szMapName)
{
_Init();
//
Open(dwAccess, szMapName);
}
void CSFMClient::Open(DWORD dwAccess, char *szMapName)
{
if (m_iOpenFlag)
_Destory();
if (szMapName)
m_pMapName = _strdup(szMapName);
else m_pMapName = _strdup(DEFAULT_MAPNAME);
m_hFileMap = OpenFileMapping(
dwAccess,
TRUE,
m_pMapName
);
if (m_hFileMap)
{
m_lpFileMapBuffer = MapViewOfFile(
m_hFileMap,
dwAccess,
0,
0,
0
);
}
m_iOpenFlag = 1;
}
void CSFMClient::_Init()
{
m_hFileMap = NULL;
m_lpFileMapBuffer = NULL;
m_pMapName = NULL;
m_iOpenFlag = 0;
}
void CSFMClient::_Destory()
{
if (m_lpFileMapBuffer)
{
UnmapViewOfFile(m_lpFileMapBuffer);
m_lpFileMapBuffer = NULL;
}
if (m_hFileMap)
{
CloseHandle(m_hFileMap);
m_hFileMap = NULL;
}
if (m_pMapName)
{
free(m_pMapName);
m_pMapName = NULL;
}
_Init();
}
LPVOID CSFMClient::GetBuffer()
{
return (m_lpFileMapBuffer)?(m_lpFileMapBuffer):(NULL);
}
DWORD CSFMClient::GetSize()
{
// unnable use
return 0;
}
</pre>
测试环境：Win2K+VC6+普通应用程序<br />
未对服务程序/ISAPI等其他应用进行测试，应该也是可以的<br />
</div>
<!-- 广告开始 -->
<img src ="http://www.blogjava.net/wangxinsh55/aggbug/200807.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/wangxinsh55/" target="_blank">SIMONE</a> 2008-05-16 10:36 <a href="http://www.blogjava.net/wangxinsh55/archive/2008/05/16/200807.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Socket基础</title><link>http://www.blogjava.net/wangxinsh55/archive/2008/05/15/200596.html</link><dc:creator>SIMONE</dc:creator><author>SIMONE</author><pubDate>Thu, 15 May 2008 03:29:00 GMT</pubDate><guid>http://www.blogjava.net/wangxinsh55/archive/2008/05/15/200596.html</guid><wfw:comment>http://www.blogjava.net/wangxinsh55/comments/200596.html</wfw:comment><comments>http://www.blogjava.net/wangxinsh55/archive/2008/05/15/200596.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/wangxinsh55/comments/commentRss/200596.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/wangxinsh55/services/trackbacks/200596.html</trackback:ping><description><![CDATA[<p class="MsoNormal" style="margin: 0cm 0cm 0pt"><font size="3"><span style="font-family: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">一．</span><span lang="EN-US"><font face="Times New Roman">socket</font></span><span style="font-family: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">的一些基本结构</span></font></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt"><font size="3"><span lang="EN-US"><font face="Times New Roman">1</font></span><span style="font-family: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">．</span><span lang="EN-US"><font face="Times New Roman">32</font></span><span style="font-family: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">位的</span><span lang="EN-US"><font face="Times New Roman">IP</font></span><span style="font-family: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">地址：</span></font></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-indent: 21.75pt"><span lang="EN-US"><font face="Times New Roman" size="3">struct in_addr</font></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-indent: 21.75pt"><span lang="EN-US"><font face="Times New Roman" size="3">{</font></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-indent: 21.75pt"><span lang="EN-US"><font face="Times New Roman"><font size="3"><span style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp; </span>unsigned long s_addr;</font></font></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-indent: 21.75pt"><span lang="EN-US"><font face="Times New Roman" size="3">}</font></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt"><span lang="EN-US"><O:P><font face="Times New Roman" size="3">&nbsp;</font></O:P></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt"><font size="3"><span lang="EN-US"><font face="Times New Roman">2</font></span><span style="font-family: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">．</span><span lang="EN-US"><font face="Times New Roman">TCP/IP</font></span><span style="font-family: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">所在的网际通信域使用的套接字地址格式：</span></font></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-indent: 21pt"><span lang="EN-US"><font face="Times New Roman" size="3">struct sockaddr_in</font></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-indent: 21pt"><span lang="EN-US"><font face="Times New Roman" size="3">{</font></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-indent: 21pt"><font size="3"><span lang="EN-US"><font face="Times New Roman"><span style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp; </span>short int sin_family;<span style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp; </span>//</font></span><span style="font-family: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">表示所属地址簇，</span><span lang="EN-US"><font face="Times New Roman">TCP/IP</font></span><span style="font-family: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">必须是</span><span lang="EN-US"><font face="Times New Roman">AF_INET</font></span></font></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-indent: 21pt"><font size="3"><span lang="EN-US"><font face="Times New Roman"><span style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp; </span>unsigned short int sin_port;<span style="mso-spacerun: yes">&nbsp;&nbsp; </span>//</font></span><span style="font-family: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">表示端口号</span></font></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-indent: 21pt"><font size="3"><span lang="EN-US"><font face="Times New Roman"><span style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp; </span>struct in_addr sin_addr; <span style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span>//</font></span><span style="font-family: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">表示</span><span lang="EN-US"><font face="Times New Roman">32</font></span><span style="font-family: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">位的</span><span lang="EN-US"><font face="Times New Roman">IP</font></span><span style="font-family: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">地址，用</span><span lang="EN-US"><font face="Times New Roman">in_addr</font></span><span style="font-family: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">结构表示</span></font></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-indent: 21pt"><font size="3"><span lang="EN-US"><font face="Times New Roman"><span style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp; </span>unsigned char sin_zero[8];<span style="mso-spacerun: yes">&nbsp;&nbsp; </span>//</font></span><span style="font-family: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">表示全部填充</span><span lang="EN-US"><font face="Times New Roman">0</font></span><span style="font-family: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">，保证和</span><span lang="EN-US"><font face="Times New Roman">sockaddr</font></span><span style="font-family: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">大小相同</span></font></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-indent: 21pt"><span lang="EN-US"><font face="Times New Roman" size="3">}</font></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt"><span lang="EN-US"><O:P><font face="Times New Roman" size="3">&nbsp;</font></O:P></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt"><font size="3"><span style="font-family: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">二．</span><span lang="EN-US"><font face="Times New Roman">socket</font></span><span style="font-family: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">的一些辅助函数</span></font></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt"><font size="3"><span lang="EN-US"><font face="Times New Roman">1</font></span><span style="font-family: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">．字节序转换函数：</span></font></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt"><font size="3"><span lang="EN-US"><span style="mso-spacerun: yes"><font face="Times New Roman">&nbsp; </font></span></span><span lang="EN-US" style="font-family: 宋体"><span style="mso-spacerun: yes">&nbsp; </span></span><span style="font-family: 宋体">&#183;<span lang="EN-US">htons : host to network byte order , short (unsigned) integer<O:P></O:P></span></span></font></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt"><font size="3"><span lang="EN-US" style="font-family: 宋体"><span style="mso-spacerun: yes">&nbsp;&nbsp; </span></span><span style="font-family: 宋体">&#183;<span lang="EN-US">htonl : host to network byte order , long (unsigned) integer<O:P></O:P></span></span></font></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt"><font size="3"><span lang="EN-US" style="font-family: 宋体"><span style="mso-spacerun: yes">&nbsp;&nbsp; </span></span><span style="font-family: 宋体">&#183;<span lang="EN-US">ntohs : network to host byte order , short (unsigned) integer<O:P></O:P></span></span></font></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt"><font size="3"><span lang="EN-US" style="font-family: 宋体"><span style="mso-spacerun: yes">&nbsp;&nbsp; </span></span><span style="font-family: 宋体">&#183;<span lang="EN-US">ntohl : network to host byte order , long (unsigned) integer<O:P></O:P></span></span></font></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-indent: 21pt"><span style="font-family: 宋体"><font size="3">记忆方法：<span lang="EN-US"><O:P></O:P></span></font></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-indent: 21pt"><font size="3"><span lang="EN-US" style="font-family: 宋体"><span style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp; </span>h</span><span style="font-family: 宋体">表示<span lang="EN-US">host</span>，<span lang="EN-US">n</span>表示<span lang="EN-US">network</span>，<span lang="EN-US">l</span>表示<span lang="EN-US">long</span>，<span lang="EN-US">s</span>表示<span lang="EN-US">short<O:P></O:P></span></span></font></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-indent: 21pt"><span style="font-family: 宋体"><font size="3">例如：<span lang="EN-US"><O:P></O:P></span></font></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-indent: 21pt"><span lang="EN-US" style="font-family: 宋体"><font size="3"><span style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp; </span>num = htons(Port_NUM);<O:P></O:P></font></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-indent: 21pt"><font size="3"><span lang="EN-US" style="font-family: 宋体"><span style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp; </span></span><span style="font-family: 宋体">表示将一个名叫<span lang="EN-US">Port_NUM</span>的端口号转换成网络字节顺序并赋值给<span lang="EN-US">num</span>变量<span lang="EN-US"><O:P></O:P></span></span></font></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt"><span lang="EN-US" style="font-family: 宋体"><O:P><font size="3">&nbsp;</font></O:P></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt"><font size="3"><span lang="EN-US" style="font-family: 宋体">2</span><span style="font-family: 宋体">．<span lang="EN-US">IP</span>地址转换函数：<span lang="EN-US"><O:P></O:P></span></span></font></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt"><font size="3"><span lang="EN-US" style="font-family: 宋体"><span style="mso-spacerun: yes">&nbsp;&nbsp; </span></span><span style="font-family: 宋体">&#183;<span lang="EN-US">inet_addr()<O:P></O:P></span></span></font></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt 26.25pt; text-indent: -26.25pt; mso-char-indent-count: -2.5"><font size="3"><span lang="EN-US" style="font-family: 宋体"><span style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="font-family: 宋体">将一个用点分十进制表示的<span lang="EN-US">IP</span>地址字符串转换成<span lang="EN-US">32</span>位无符号整数。此整数已经是</span></font></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt 26.25pt; text-indent: -26.25pt; mso-char-indent-count: -2.5"><font size="3"><span style="font-family: 宋体">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;网络字节顺序，无需再调用<span lang="EN-US">htonl()<O:P></O:P></span></span></font></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt 26.25pt; text-indent: -26.25pt; mso-char-indent-count: -2.5"><font size="3"><span lang="EN-US" style="font-family: 宋体"><span style="mso-spacerun: yes">&nbsp;</span><span style="mso-spacerun: yes">&nbsp;</span><span style="mso-spacerun: yes">&nbsp;</span></span><span style="font-family: 宋体">&#183;<span lang="EN-US">inet_ntoa()<O:P></O:P></span></span></font></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt 26.25pt; text-indent: -26.25pt; mso-char-indent-count: -2.5"><font size="3"><span lang="EN-US" style="font-family: 宋体"><span style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="font-family: 宋体">将一个<span lang="EN-US">32</span>位无符号整数转换成一个点分十进制表示的<span lang="EN-US">IP</span>地址字符串，此函数接受</span></font></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt 26.25pt; text-indent: -26.25pt; mso-char-indent-count: -2.5"><font size="3"><span style="font-family: 宋体">&nbsp;&nbsp;&nbsp;&nbsp; 一个<span lang="EN-US">in_addr</span>结构作为参数，将返回的字符串存储再一个<span lang="EN-US">static</span>的缓冲区内，因</span></font></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt 26.25pt; text-indent: -26.25pt; mso-char-indent-count: -2.5"><font size="3"><span style="font-family: 宋体">&nbsp;&nbsp;&nbsp;&nbsp; 此，下次调用此函数时，将改变上次调用的结果。<span lang="EN-US"><O:P></O:P></span></span></font></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt 26.25pt; text-indent: -26.25pt; mso-char-indent-count: -2.5"><span lang="EN-US" style="font-family: 宋体"><O:P><font size="3">&nbsp;</font></O:P></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt 26.25pt; text-indent: -26.25pt; mso-char-indent-count: -2.5"><font size="3"><span lang="EN-US" style="font-family: 宋体">3</span><span style="font-family: 宋体">．查找主机信息函数：<span lang="EN-US"><O:P></O:P></span></span></font></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt 26.25pt; text-indent: -26.25pt; mso-char-indent-count: -2.5"><span lang="EN-US" style="font-family: 宋体"><font size="3"><span style="mso-spacerun: yes">&nbsp;&nbsp; </span>struct hostent* gethostbyname(const char *name);<O:P></O:P></font></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt 26.25pt; text-indent: -26.25pt; mso-char-indent-count: -2.5"><font size="3"><span lang="EN-US" style="font-family: 宋体"><span style="mso-spacerun: yes">&nbsp;&nbsp; </span></span><span style="font-family: 宋体">参数：输入参数时需要解析的主机名，也可以是域名<span lang="EN-US"><O:P></O:P></span></span></font></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt 26.25pt; text-indent: -26.25pt; mso-char-indent-count: -2.5"><font size="3"><span lang="EN-US" style="font-family: 宋体"><span style="mso-spacerun: yes">&nbsp;&nbsp; </span></span><span style="font-family: 宋体">返回值：返回一个描述主机信息的结构<span lang="EN-US">hostent</span>的指针<span lang="EN-US"><O:P></O:P></span></span></font></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt 26.25pt; text-indent: -26.25pt; mso-char-indent-count: -2.5"><span lang="EN-US" style="font-family: 宋体"><font size="3"><span style="mso-spacerun: yes">&nbsp;&nbsp; </span>struct hostent<O:P></O:P></font></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt 26.25pt; text-indent: -26.25pt; mso-char-indent-count: -2.5"><span lang="EN-US" style="font-family: 宋体"><font size="3"><span style="mso-spacerun: yes">&nbsp;&nbsp; </span>{<O:P></O:P></font></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt 26.25pt; text-indent: -26.25pt; mso-char-indent-count: -2.5"><font size="3"><span lang="EN-US" style="font-family: 宋体"><span style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>char *h_name;<span style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>//</span><span style="font-family: 宋体">主机的正式名称<span lang="EN-US"><O:P></O:P></span></span></font></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt 26.25pt; text-indent: -26.25pt; mso-char-indent-count: -2.5"><font size="3"><span lang="EN-US" style="font-family: 宋体"><span style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>char **h_aliases;<span style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>//</span><span style="font-family: 宋体">主机的别名<span lang="EN-US"><O:P></O:P></span></span></font></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt 26.25pt; text-indent: -26.25pt; mso-char-indent-count: -2.5"><font size="3"><span lang="EN-US" style="font-family: 宋体"><span style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>int h_addrtype;<span style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>//</span><span style="font-family: 宋体">主机地址类型 <span lang="EN-US"><O:P></O:P></span></span></font></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt 26.25pt; text-indent: -26.25pt; mso-char-indent-count: -2.5"><font size="3"><span lang="EN-US" style="font-family: 宋体"><span style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>int h_length;<span style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>//</span><span style="font-family: 宋体">地址长度<span lang="EN-US"><O:P></O:P></span></span></font></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt 26.25pt; text-indent: -26.25pt; mso-char-indent-count: -2.5"><font size="3"><span lang="EN-US" style="font-family: 宋体"><span style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>char **h_addr_list;<span style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>//</span><span style="font-family: 宋体">存储主机地址的数组<span lang="EN-US"><O:P></O:P></span></span></font></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt 26.25pt; text-indent: -26.25pt; mso-char-indent-count: -2.5"><font size="3"><span lang="EN-US" style="font-family: 宋体"><span style="mso-spacerun: yes">&nbsp;&nbsp