??xml version="1.0" encoding="utf-8" standalone="yes"?>青青热久久国产久精品,欧美亚洲色综久久精品国产,要久久爱在线免费观看http://www.shnenglu.com/zhengxf/archive/2013/06/01/200736.html郑兴?/dc:creator>郑兴?/author>Sat, 01 Jun 2013 02:04:00 GMThttp://www.shnenglu.com/zhengxf/archive/2013/06/01/200736.htmlhttp://www.shnenglu.com/zhengxf/comments/200736.htmlhttp://www.shnenglu.com/zhengxf/archive/2013/06/01/200736.html#Feedback0http://www.shnenglu.com/zhengxf/comments/commentRss/200736.htmlhttp://www.shnenglu.com/zhengxf/services/trackbacks/200736.html

本文主要讨论如何一个win32目Q移植到android上面Q网上很多文章说的不一P因ؓcocos2d-x的android目配置Ҏ好像修改q几ơ(好像Q我没用q老版的)Q本文提供一U简单的Ҏ?/span>

W零步:配置android工程生成?/strong>
#1用ue之类的编辑器打开cocos2d-x目录下的create-android-project.bat

#2~辑q三个变?/span>

意思太明白了,׃解释?/span>


W一步:建立android工程

#1q行cocos2d-x目录下的create-android-project.bat

#2然后首先输入包名和项目名?/span>
注意有坑Q这会删除和覆盖你在cocos2d-x安装目录下同名文件夹Q如果你建立了一个同名项目(有的话一般是win32的)的话?/span>
本地囄Q请重新上传
#3然后输入支持pȝ版本Qandroid是向下兼容的。我q里?Q也是android2.1-update1
本地囄Q请重新上传
然后目徏立好了,你会发现在cocos2d-x安装目录下,多了个Test文g?/span>

W二步:导入代码和资?/strong>

#1打开Test

本地囄Q请重新上传
#2我们看到有三个文件夹Q其中android是android目文g?/span>
把你win32目里的Classes拯到当前Classes下(注意删除Classes里面的多余的cpp和hQ就是项目自动生成的那些Q?/span>
把你win32目里的Resources拯到当?/span>Resources下(注意删除Classes里面的多余资源,是目自动生成的那些)

W三步:~辑mk

#1注意有坑Qandroid目里有一大堆mkQ而且不同的教E说的mk位置q不一P你编辑错误了Q是无效的(跟你实际使用的mk也有关系Q。在q个例子中,我们使用的是Classes下的mk

本地囄Q请重新上传
#2要修改的地方如下
LOCAL_SRC_FILESQ在q里加入你Classes下的cpp文g
LOCAL_C_INCLUDESQ在q里d你用的库的h文gQ如果有的话
LOCAL_LDLIBSQ在q里d你用的库的lib文gQ如果有的话

q里我用的是,之前?#8220;是男人就坚持20U?#8221;那个例子的代?/span>

注意Q第三方库和额外的库都是要自己添加的。默认生成的mk里没那么全?/span>

W四步:q行build_native.sh脚本Q编辑so?/strong>

#1q行你的cygwin安装目录下的Cygwin.bat

#2q入当前Test\android路径?/span>
本地囄Q请重新上传
注意cygwin下的命o写法Q和win下不?/span>
#3q行build_native.sh脚本
头一ơ编译会长些Q当然图省事你也可以把自己及其他的android目里面的so复制q来Q应该可以把Q哈哈哈Q?/span>
~译?/span>然后你会看到Q在android文g夹下面生成了一大堆东西?/span>

W五步:导入到eclipse

#1注意有坑Q用新建android目下的Create project from existing sourceQ如果你使用的是“导入”有可能无法识别?/span>
#2导入成功Q然后就是编译执行了。cocos2d-x作者推荐用sh~译soQ再用eclipse~译成apk?/div>
本地囄Q请重新上传

其他注意事项Q?/strong>


#1.win32目对资源文件大写不敏感,android敏感Q所以如果出错了Q把l你提供资源的hl打一?/span>
#2.可以直接把win32目里的工程文gQ以及win32文g夹复制进来,目可以和VSq了,当然cocos2d-x也是q么q的
#3.vs用的是gb码,android用的是utf-8Q解x法在vs下用iconvQ另外最好全都{成utf-8Q网上有很多~码扚w转换工具
#4.android的横竖屏问题错ؕQ在android下把
pDirector->setDeviceOrientation(kCCDeviceOrientationLandscapeLeft);
q句用条件编译宏l关?/span>

 

 

 

另外Q关于cocos2d-x在android上添加第三方库的问题Q?网友塞风朔雪写了一个文档,很有参考h倹{我已把它上传到附g中?/p>




]]>
windows下搭建cocos2dx Android开发环?/title><link>http://www.shnenglu.com/zhengxf/archive/2013/06/01/200735.html</link><dc:creator>郑兴?/dc:creator><author>郑兴?/author><pubDate>Sat, 01 Jun 2013 02:02:00 GMT</pubDate><guid>http://www.shnenglu.com/zhengxf/archive/2013/06/01/200735.html</guid><wfw:comment>http://www.shnenglu.com/zhengxf/comments/200735.html</wfw:comment><comments>http://www.shnenglu.com/zhengxf/archive/2013/06/01/200735.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.shnenglu.com/zhengxf/comments/commentRss/200735.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/zhengxf/services/trackbacks/200735.html</trackback:ping><description><![CDATA[<div class="48cwmuo" id="blogDetailDiv" style="font-size: 14px; color: #000000" eventslistuid="e56"> <div id="6444ass" class="blog_details_20120222"> <div> <h3 sizset="21" sizcache="3"><span sizset="21" sizcache="3"> <p>环境winxp + android sdk + ndk r8b+ cygwin 1.7.16-1 + cocos2d-1.0.1-x-0.12.0<br /></p> <p>1.下蝲android sdk、ndk、cygwin</p> <p sizset="33" sizcache="3"><a target="_blank"><a target="_blank">http://dl.google.com/android/android-sdk_r20.0.1-windows.zip</a></a></p> <p sizset="34" sizcache="3"><a target="_blank"><a target="_blank">http://dl.google.com/android/ndk/android-ndk-r8b-windows.zip</a></a></p> <p sizset="35" sizcache="3"><a target="_blank"><a target="_blank">http://cygwin.com/setup.exe</a></a></p> <p>2.android sdk的安装就不多说了Q网上多的是?/p> <p>ndk解压C含空格的目录下,下文?lt;ndk_dir>来表C压后的ndk根目录?/p> <p>下蝲好cygwin后,q行setup.exe。需要安装的lg有:</p> <p>autoconf automake binutils gcc-core gcc-g++ gcc4-core gcc4-g++ gdb pcre pcre-devel gawk make</p> <p>可以在上方search处进行查扑֮装,下文?lt;cyg_dir>表示cygwin的安装目录?/p> <p>3.cygwin安装好后Q在windows下编?lt;cyg_dir>\home\Administrator\.bash_profile文g</p> <p>在文件最后添加如下内?/p> <p> </p> <div sizset="36" sizcache="3"> <div sizset="36" sizcache="3"> <div sizset="36" sizcache="3"><strong>[cpp]</strong> <a title="view plain" target="_blank">view plain</a><a title="copy" target="_blank">copy</a><a title="print" target="_blank">print</a><a title="?" target="_blank">?</a></div></div> <ol><li><span>NDK=/cygdrive/d/<q里是ndk路径>/android-ndk-r8b  </span></li><li><span>export NDK  </span></li></ol></div>NDK=/cygdrive/d/<q里是ndk路径>/android-ndk-r8bexport NDK<br />~辑cocos2dx目录下的create-android-project.bat文gQ分别修改如下几个变量的? <p> </p> <p> </p> <div sizset="40" sizcache="3"> <div sizset="40" sizcache="3"> <div sizset="40" sizcache="3"><strong>[cpp]</strong> <a title="view plain" target="_blank">view plain</a><a title="copy" target="_blank">copy</a><a title="print" target="_blank">print</a><a title="?" target="_blank">?</a></div></div> <ol><li><span>set _CYGBIN=C:\cygwin\bin  </span></li><li><span>set _ANDROIDTOOLS=C:\android-sdk-windows\tools  </span></li><li><span>set _NDKROOT=D:\Tools\Developer\Android\android-ndk-r8b  </span></li></ol></div>set _CYGBIN=C:\cygwin\binset _ANDROIDTOOLS=C:\android-sdk-windows\toolsset _NDKROOT=D:\Tools\Developer\Android\android-ndk-r8b<br />上面是我的系l中使用的\径,同学们需要根据自q实际情况q行修改? <p> </p> <p>q样Q环境基本上搭建好了,下面需要徏一个hello world工程来验证一下环境是否可用?/p> <p>1.q行cocos2dx目录下的create-android-project.bat文gQ根据提C入包名(例如Qcn.wey.androidQ、项目名Uͼ例如Qhello2dxQ、所使用的android sdk版本?/p> <p>2.q行cygwinQ在命oH口中进入刚刚新建的hello2dx目录下的android目录Q运行命?/p> <p> </p> <div sizset="44" sizcache="3"> <div sizset="44" sizcache="3"> <div sizset="44" sizcache="3"><strong>[cpp]</strong> <a title="view plain" target="_blank">view plain</a><a title="copy" target="_blank">copy</a><a title="print" target="_blank">print</a><a title="?" target="_blank">?</a></div></div> <ol><li><span>./build_native.sh  </span></li></ol></div>./build_native.sh<br />对工E进行编译,直到最后正常结束? <p> </p> <p>3.打开eclipseQ导入hello2dx目Q编译ƈq行。即可看到经典的cocos2dx的hello world界面</p></span></h3></div></div></div><img src ="http://www.shnenglu.com/zhengxf/aggbug/200735.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/zhengxf/" target="_blank">郑兴?/a> 2013-06-01 10:02 <a href="http://www.shnenglu.com/zhengxf/archive/2013/06/01/200735.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>有用的网址http://www.shnenglu.com/zhengxf/archive/2011/11/21/160617.html郑兴?/dc:creator>郑兴?/author>Mon, 21 Nov 2011 02:39:00 GMThttp://www.shnenglu.com/zhengxf/archive/2011/11/21/160617.htmlhttp://www.shnenglu.com/zhengxf/comments/160617.htmlhttp://www.shnenglu.com/zhengxf/archive/2011/11/21/160617.html#Feedback0http://www.shnenglu.com/zhengxf/comments/commentRss/160617.htmlhttp://www.shnenglu.com/zhengxf/services/trackbacks/160617.html  http://www.cnblogs.com/andyque/tag/iphone

]]>
Unicode和UTF-8之间的{换详??http://www.shnenglu.com/zhengxf/archive/2011/11/20/160554.html郑兴?/dc:creator>郑兴?/author>Sun, 20 Nov 2011 05:52:00 GMThttp://www.shnenglu.com/zhengxf/archive/2011/11/20/160554.htmlhttp://www.shnenglu.com/zhengxf/comments/160554.htmlhttp://www.shnenglu.com/zhengxf/archive/2011/11/20/160554.html#Feedback0http://www.shnenglu.com/zhengxf/comments/commentRss/160554.htmlhttp://www.shnenglu.com/zhengxf/services/trackbacks/160554.html                        |魂兵 http://xdotnet.cnblogs.com
    UTF-8~码字符理论上可以最多到6个字节长,然?6位BMPQBasic Multilingual PlaneQ字W最多只用到3字节ѝ下面看一下UTF-8~码表:

        U-00000000 - U-0000007F: 0xxxxxxx
        U-00000080 - U-000007FF: 110xxxxx 10xxxxxx
        U-00000800 - U-0000FFFF: 1110xxxx 10xxxxxx 10xxxxxx
        U-00010000 - U-001FFFFF: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
        U-00200000 - U-03FFFFFF: 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
        U-04000000 - U-7FFFFFFF: 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx

    xxx 的位|由字符~码数的二进制表C的位填入, 靠右的 x h少的特D意义,只用最短的那个_表达一个字W编码数的多字节丌Ӏ?注意在多字节串中, W一个字节的开?1"的数目就是整个串中字节的数目。而第一行中?开_是ؓ了兼容ASCII~码Qؓ一个字节,W二行就为双字节字符ԌW三行ؓ3字节Q如汉字属于这U,以此cL?个h认ؓQ其实我们可以简单的把前面的1的个数看成字节数)
                         |魂兵 http://xdotnet.cnblogs.com
    Z要将Unicode转换为UTF-8Q当然要知道他们的区别到底在什么地斏V下面来看一下,在Unicode中的~码是怎样转换成UTF-8的,在UTF-8中,如果一个字W的字节于0x80Q?28Q则为ASCII字符Q占一个字节,可以不用转换Q因为UTF-8兼容ASCII~码。假如在Unicode中汉?#8220;?#8221;的编码ؓ“u4F60”Q把它{换ؓ二进制ؓ100111101100000Q然后按照UTF-8的方法进行{换。可以将Unicode二进制从C往高位取出二进制数字,每次?位,如上q的二进制就可以分别取出为如下所C的格式Q前面按格式填补Q不?位用0填补?br />
      
           unicode:  100111101100000                  4F60

           utf-8:    11100100,10111101,10100000       E4BDA0


    从上面就可以很直观的看出Unicode到UTF-8之间的{换,当然知道了UTF-8的格式后Q就可以q行逆运,是按照格式把它在二q制中的相应位置上取出,然后在{换就是所得到的Unicode字符了(q个q算可以通过“位移”来完成)?br />                      |魂兵 http://xdotnet.cnblogs.com
    如上q的“?#8221;的{换,׃其值大?x800于0x10000Q因此可以判断ؓ三字节存储,则最高位需要向右移“12”位再Ҏ三字节格式的最高位?1100000Q?xE0Q求或(|Q就可以得到最高位的g。同理第二位则是右移“6”位,则还剩下最高位和第二位的二q制|可以通过?11111Q?x3FQ求按位于(&Q操作,再和11000000Q?x80Q求或(|Q。第三位׃用移位了Q只要直接取最后六位(?11111Qox3FQ取&Q,在与11000000(0x80)求或Q|Q。OK了,转换成功Q在VC++中的代码如下所C(Unicode到UTF-8的{换)?br />
        1 const wchar_t pUnicode = L"?;
        2 char utf8[3+1];
        3 memset(utf8,0,4);
        4 utf8[0] = 0xE0|(pUnicode>>12);
        5 utf8[1] = 0x80|((pUnicode>>6)&0x3F);
        6 utf8[2] = 0x80|(pUnicode&0x3F);
        7 utf8[3] = "\0";
        8 //char[4]是UTF-8的字W?#8220;?#8221;了?

    当然在UTF-8到Unicode的{换也是通过UM{来完成的,是把UTF-8那些格式相应的位|的二进制数l揪出来。在上述例子?#8220;?#8221;Z个字节,因此要每个字节进行处理,有高位到低位q行处理。在UTF-8?#8220;?#8221;?1100100,10111101,10100000。从高位起即W一个字?1100100是把其中的"0100"l取出来Q这个很单只要和11111Q?x1FQ取与(&Q,׃字节可以得知最C肯定位于12位之前,因ؓ每次取六位。所以还要将得到的结果左U?2位,最高位也就q样完成?100,000000,000000。而第二位则是要把“111101”l取出来Q则只需第二字?0111101?11111(0x3F)取与Q?amp;Q。在所得到的结果左U?位与最高字节所得的l果取或Q|Q,W二位就q样完成了,得到的结果ؓ0100,111101,000000。以此类推最后一位直接与111111Q?x3FQ取与(&Q,再与前面所得的l果取或Q|Q即可得到结?100,111101,100000。OKQ{换成功!在VC++中的代码如下所C(UTF-8到Unicode的{换)?br />
    1 //UTF-8格式的字W串
    2 const char* utf8 = "?;
    3 wchar_t unicode;
    4 unicode = (utf8[0] & 0x1F) << 12;
    5 unicode |= (utf8[1] & 0x3F) << 6;
    6 unicode |= (utf8[2] & 0x3F);
    7 //unicode is ok!
                            |魂兵 http://xdotnet.cnblogs.com
    当然在编E过E中不可能只转换一个字W,q里需要注意的是字W的长度一定要清楚,不然会带?..以上是我这几天研究的结果,至于Unicode的{换ؓGB2312在MFC中Windows有自带的APIQWideCharToMultiByteQ可以{换。这样也p够将UTF-8格式转换为GB2312了,q里׃再赘qͼ如果大家有更好的Ҏ希望指教?br />

]]>
setsockopt讄socket状?/title><link>http://www.shnenglu.com/zhengxf/archive/2011/11/16/160291.html</link><dc:creator>郑兴?/dc:creator><author>郑兴?/author><pubDate>Wed, 16 Nov 2011 12:57:00 GMT</pubDate><guid>http://www.shnenglu.com/zhengxf/archive/2011/11/16/160291.html</guid><wfw:comment>http://www.shnenglu.com/zhengxf/comments/160291.html</wfw:comment><comments>http://www.shnenglu.com/zhengxf/archive/2011/11/16/160291.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.shnenglu.com/zhengxf/comments/commentRss/160291.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/zhengxf/services/trackbacks/160291.html</trackback:ping><description><![CDATA[1.closesocketQ一般不会立卛_闭而经历TIME_WAIT的过E)后想l箋重用该socketQ?br />BOOL bReuseaddr=TRUE;<br />setsockopt(s,SOL_SOCKET ,SO_REUSEADDR,(const char*)&bReuseaddr,sizeof(BOOL));<br />2. 如果要已l处于连接状态的soket在调用closesocket后强制关闭,不经?br />TIME_WAIT的过E:<br />BOOL bDontLinger = FALSE;<br />setsockopt(s,SOL_SOCKET,SO_DONTLINGER,(const char*)&bDontLinger,sizeof(BOOL));<br />3.在send(),recv()q程中有时由于网l状늭原因Q发收不能预期进?而设|收发时限:<br />int nNetTimeout=1000;//1U?br />//发送时?br />setsockopt(socketQSOL_S0CKET,SO_SNDTIMEOQ?char *)&nNetTimeout,sizeof(int));<br />//接收旉<br />setsockopt(socketQSOL_S0CKET,SO_RCVTIMEOQ?char *)&nNetTimeout,sizeof(int));<br />4.在send()的时候,q回的是实际发送出ȝ字节(同步)或发送到socket~冲区的字节<br />(异步);pȝ默认的状态发送和接收一ơؓ8688字节(Uؓ8.5K)Q在实际的过E中发送数?br />和接收数据量比较大,可以讄socket~冲区,而避免了send(),recv()不断的@环收发:<br />// 接收~冲?br />int nRecvBuf=32*1024;//讄?2K<br />setsockopt(s,SOL_SOCKET,SO_RCVBUF,(const char*)&nRecvBuf,sizeof(int));<br />//发送缓冲区<br />int nSendBuf=32*1024;//讄?2K<br />setsockopt(s,SOL_SOCKET,SO_SNDBUF,(const char*)&nSendBuf,sizeof(int));<br />5. 如果在发送数据的Ӟ希望不经历由pȝ~冲区到socket~冲区的拯而媄?br />E序的性能Q?br />int nZero=0;<br />setsockopt(socketQSOL_S0CKET,SO_SNDBUFQ?char *)&nZero,sizeof(nZero));<br />6.同上在recv()完成上述功能(默认情况是将socket~冲区的内容拯到系l缓冲区)Q?br />int nZero=0;<br />setsockopt(socketQSOL_S0CKET,SO_RCVBUFQ?char *)&nZero,sizeof(int));<br />7.一般在发送UDP数据报的时候,希望该socket发送的数据hq播Ҏ:<br />BOOL bBroadcast=TRUE;<br />setsockopt(s,SOL_SOCKET,SO_BROADCAST,(const char*)&bBroadcast,sizeof(BOOL));<br />8.在clientq接服务器过E中Q如果处于非d模式下的socket在connect()的过E中?br />以设|connect()延时,直到accpet()被呼?本函数设|只有在非阻塞的q程中有显著?br />作用Q在d的函数调用中作用不大)<br />BOOL bConditionalAccept=TRUE;<br />setsockopt(s,SOL_SOCKET,SO_CONDITIONAL_ACCEPT,(const char*)&bConditionalAccept,sizeof(BOOL));<br />9.如果在发送数据的q程?send()没有完成Q还有数据没发?而调用了closesocket(),以前我们<br />一般采取的措施?从容关闭"shutdown(s,SD_BOTH),但是数据是肯定丢׃Q如何设|让E序满具体<br />应用的要?卌没发完的数据发送出d在关闭socket)Q?br />struct linger {<br />u_short l_onoff;<br />u_short l_linger;<br />};<br />linger m_sLinger;<br />m_sLinger.l_onoff=1;//(在closesocket()调用,但是q有数据没发送完毕的时候容讔R留)<br />// 如果m_sLinger.l_onoff=0;则功能和2.)作用相同;<br />m_sLinger.l_linger=5;//(容许逗留的时间ؓ5U?<br />setsockopt(s,SOL_SOCKET,SO_LINGER,(const char*)&m_sLinger,sizeof(linger));<br /> <br />讄套接口的选项?br />   #include <winsock.h><br />   int PASCAL FAR setsockopt( SOCKET s, int level, int optname,<br />   const char FAR* optval, int optlen);<br />   sQ标识一个套接口的描q字?br />   levelQ选项定义的层ơ;目前仅支持SOL_SOCKET和IPPROTO_TCP层次?br />   optnameQ需讄的选项?br />   optvalQ指针,指向存放选项值的~冲区?br />   optlenQoptval~冲区的长度?br />注释Q?br />setsockopt()函数用于Lcd、Q意状态套接口的设|选项倹{尽在不同协议层上存在选项Q但本函C定义了最高的“套接?#8221;层次上的选项。选项影响套接口的操作Q诸如加急数据是否在普通数据流中接Ӟq播数据是否可以从套接口发送等{?br />   有两U套接口的选项Q一U是布尔型选项Q允许或止一U特性;另一U是整Ş或结构选项。允怸个布型选项Q则optval指向非零整Ş敎ͼ止一个选项optval指向一个等于零的整形数。对于布型选项Qoptlen应等于sizeof(int)Q对其他选项Qoptval指向包含所需选项的整形数或结构,而optlen则ؓ整Ş数或l构的长度。SO_LINGER选项用于控制下述情况的行动:套接口上有排队的待发送数据,?closesocket()调用已执行。参见closesocket()函数中关于SO_LINGER选项对closesocket()语义的媄响。应用程序通过创徏一个lingerl构来设|相应的操作Ҏ:<br />   struct linger {<br />int l_onoff;<br />int l_linger;<br />   };<br />   Z允许SO_LINGERQ应用程序应l_onoff设ؓ非零Q将l_linger设ؓ零或需要的时|以秒为单位)Q然后调用setsockopt()。ؓ了允许SO_DONTLINGERQ亦即禁止SO_LINGERQ,l_onoff应设为零Q然后调用setsockopt()?br />   ~省条g下,一个套接口不能与一个已在用中的本地地址捆绑Q参见bind()Q。但有时会需?#8220;重用”地址。因为每一个连接都由本地地址和远端地址的组合唯一定Q所以只要远端地址不同Q两个套接口与一个地址捆绑q无大碍。ؓ了通知WINDOWS套接口实C要因Z个地址已被一个套接口使用׃让它与另一个套接口捆绑Q应用程序可在bind()调用前先讄SO_REUSEADDR选项。请注意仅在bind()调用时该选项才被解释Q故此无需Q但也无宻I一个不会共用地址的套接口讄该选项Q或者在bind()对这个或其他套接口无影响情况下设|或清除q一选项?br />   一个应用程序可以通过打开SO_KEEPALIVE选项Q得WINDOWS套接口实现在TCPq接情况下允怋?#8220;保持zd”包。一个WINDOWS套接口实现ƈ不是必需支持“保持zd”Q但是如果支持的话,具体的语义将与实现有养I应遵守RFC1122“InternetL要求Q通讯?#8221;中第 4.2.3.6节的规范。如果有兌接由?#8220;保持zd”而失效,则进行中的Q何对该套接口的调用都以WSAENETRESET错误q回Q后l的M调用以WSAENOTCONN错误q回?br />   TCP_NODELAY选项止Nagle法。Nagle法通过未认的数据存入缓冲区直到蓄一个包一起发送的ҎQ来减少L发送的零碎数据包的数目。但对于某些应用来说Q这U算法将降低pȝ性能。所以TCP_NODELAY可用来将此算法关闭。应用程序编写者只有在切了解它的效果q确实需要的情况下,才设|TCP_NODELAY选项Q因|后对网l性能有明昄负面影响。TCP_NODELAY是唯一使用IPPROTO_TCP层的选项Q其他所有选项都用SOL_SOCKET层?br />   如果讄了SO_DEBUG选项QWINDOWS套接口供应商被鼓励(但不是必需Q提供输出相应的调试信息。但产生调试信息的机制以及调试信息的形式已超出本规范的讨围?br />setsockopt()支持下列选项。其?#8220;cd”表明optval所指数据的cd?br />选项        cd   意义<br />SO_BROADCAST BOOL 允许套接口传送广播信息?br />SO_DEBUG BOOL 记录调试信息?br />SO_DONTLINER BOOL 不要因ؓ数据未发送就d关闭操作。设|本选项相当于将SO_LINGER的l_onoff元素|ؓ零?br />SO_DONTROUTE BOOL 止选径Q直接传送?br />SO_KEEPALIVE BOOL 发?#8220;保持zd”包?br />SO_LINGER struct linger FAR*   如关闭时有未发送数据,则逗留?br />SO_OOBINLINE BOOL 在常规数据流中接收带外数据?br />SO_RCVBUF int 为接收确定缓冲区大小?br />SO_REUSEADDR BOOL 允许套接口和一个已在用中的地址捆绑Q参见bind()Q?br />SO_SNDBUF int 指定发送缓冲区大小?br />TCP_NODELAY BOOL 止发送合q的Nagle法?br />setsockopt()不支持的BSD选项有:<br />选项?nbsp;   cd 意义<br />SO_ACCEPTCONN BOOL 套接口在监听?br />SO_ERROR int 获取错误状态ƈ清除?br />SO_RCVLOWAT int 接收低水印?br />SO_RCVTIMEO int 接收时?br />SO_SNDLOWAT int 发送低U水印?br />SO_SNDTIMEO int 发送超时?br />SO_TYPE     int 套接口类型?br />IP_OPTIONS    在IP头中讄选项?br />q回|<br />   若无错误发生Qsetsockopt()q回0。否则的话,q回SOCKET_ERROR错误Q应用程序可通过WSAGetLastError()获取相应错误代码?br />错误代码Q?br />   WSANOTINITIALISEDQ在使用此API之前应首先成功地调用WSAStartup()?br />   WSAENETDOWNQWINDOWS套接口实现检到|络子系l失效?br />   WSAEFAULTQoptval不是q程地址I间中的一个有效部分?br />   WSAEINPROGRESSQ一个阻塞的WINDOWS套接口调用正在运行中?br />   WSAEINVALQlevel值非法,或optval中的信息非法?br />   WSAENETRESETQ当SO_KEEPALIVE讄后连接超时?br />   WSAENOPROTOOPTQ未知或不支持选项。其中,SOCK_STREAMcd的套接口不支持SO_BROADCAST选项QSOCK_DGRAM cd的套接口不支持SO_DONTLINGER 、SO_KEEPALIVE、SO_LINGER和SO_OOBINLINE选项?br />   WSAENOTCONNQ当讄SO_KEEPALIVE后连接被复位?br />   WSAENOTSOCKQ描q字不是一个套接口?img src ="http://www.shnenglu.com/zhengxf/aggbug/160291.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/zhengxf/" target="_blank">郑兴?/a> 2011-11-16 20:57 <a href="http://www.shnenglu.com/zhengxf/archive/2011/11/16/160291.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>|游服务器的布局http://www.shnenglu.com/zhengxf/archive/2011/03/22/142494.html郑兴?/dc:creator>郑兴?/author>Tue, 22 Mar 2011 09:38:00 GMThttp://www.shnenglu.com/zhengxf/archive/2011/03/22/142494.htmlhttp://www.shnenglu.com/zhengxf/comments/142494.htmlhttp://www.shnenglu.com/zhengxf/archive/2011/03/22/142494.html#Feedback0http://www.shnenglu.com/zhengxf/comments/commentRss/142494.htmlhttp://www.shnenglu.com/zhengxf/services/trackbacks/142494.html下面q个图描qC|关服务器和其他服务器之间的关系:
     
|关服务器的功能是将: 游戏服务? 客户端和数据库服务器之间的消息进行{? 所以它负责理客户端的q接和服务端的连? q{发他们之间的消息, 同时他还q接到数据库服务器上,{需要数据读取是Ҏ据库q行操作,q{发给相应的请求?  (其实在对数据库的q接q个问题上,有游戏服务器来连接的Q网x务只负责转发和简单的逻辑处理)?br>    我们现在来讨Z|关服务器是怎么实现的:|关服务器要理两个事情Q一个是游戏服务器的q接Q另一个玩家的q接。其实对于网x务器而言Q这两个U类型的q接差别Qƈ不是很大Q可以用一个网路模型来处理收到的消息,q将其{发给相应的接受者?br>    游戏服务器中的地图服务器Q地图服务器相对于网x务器而言Q它更像是一个客LQ它在收到消息的时候处理消息,q将消息l果q回l网养I|关把消息{l相应的q接。只是说因ؓ地图服务器相Ҏ说是处理那些长时间连接,需要不断处理的逻辑的,如用LUdQ状态,补给{,需要实时的消息处理?br>    逻辑服务器的功能是实现如打怪,l队{一些,不经怺互的逻辑的。其实对于一l游戏服务器而言Q大量的聊天信息也是很消耗系l资源的Q有时候要单独建立一个聊天服务器?br>   数据库服务器基本上是存放数据库的Q游戏服务器Q逻辑服务器,在需要是d数据Q进行逻辑处理?br>
   
  














 


]]>
Windowspȝ~程之进E间通信 http://www.shnenglu.com/zhengxf/archive/2011/02/15/140077.html郑兴?/dc:creator>郑兴?/author>Tue, 15 Feb 2011 04:30:00 GMThttp://www.shnenglu.com/zhengxf/archive/2011/02/15/140077.htmlhttp://www.shnenglu.com/zhengxf/comments/140077.htmlhttp://www.shnenglu.com/zhengxf/archive/2011/02/15/140077.html#Feedback0http://www.shnenglu.com/zhengxf/comments/commentRss/140077.htmlhttp://www.shnenglu.com/zhengxf/services/trackbacks/140077.html
Windowspȝ~程之进E间通信
北极?003 当前ȝ


Windows 的IPCQ进E间通信Q机制主要是异步道和命名管道。(至于其他的IPC方式Q例如内存映、邮槽等q里׃介绍了)
道QpipeQ是用于q程间通信的共享内存区域。创建管道的q程UCؓ道服务器,而连接到q个道的进E称为管道客L。一个进E向道写入信息Q而另外一个进E从道d信息?br>异步道是基于字W和半双工的Q即单向Q,一般用于程序输入输出的重定向;命名道则强大地多,它们是面向消息和全双工的Q同时还允许|络通信Q用于创建客L/服务器系l?br>一、异步管?实现比较单,直接通过实例来讲?
实验目标Q当前有sample.cpp, sample.exe, sample.inq三个文Ӟsample.exe为sample.cpp的执行程序,sample.cpp只是一个简单的E序CZQ简单求和)Q如下:
代码:
#include <iostream.h>
int main()
{
  int a, b ;
  while ( cin >> a >> b && ( a || b ) )
    cout << a + b << endl ;
  return 0;
}
Sample.in文g是输入文Ӟ内容Q?br>32 433
542 657
0 0
要求Ҏsample.exe和它的输入数据,把输出数据重定向到sample.out
程分析Q实际这个实验中包含两个部分Q把输入数据重定向到sample.exe 和把输出数据重定向到sample.out。在命o行下可以很简单的实现q个功能“sample <sample.in >sample.out”Q这个命令也是利用管道特性实现的Q现在我们就Ҏ异步道的实现原理自己来实现q个功能?br>道是基于半双工Q单向)的,q里有两个重定向的过E,昄需要创Z个管道,下面l出程图:
 
异步道实现的流E图说明Q?br>1Q。父q程是我们需要实现的Q其中需要创建管道AQ管道BQ和子进E,整个实现程分ؓ4个操作?br>2Q。管道AQ输入管?br>3Q。管道BQ输出管?br>4Q。操作AQ把输入文gsample.in的数据写入输入管道(道AQ?br>5Q。操作BQ子q程从输入管道中d数据Q作q程的加工原料。通常Q程序的输入数据由标准的输入讑֤输入Q这里实现输入重定向Q即把输入管道作入设备?br>6Q。操作CQ子q程把加工后的成品(输出数据Q输出到输出道。通常Q程序的输出数据会输出到标准的输备,一般ؓ屏幕Q这里实现输出重定向Q即把输出管道作备?br>7Q。操作DQ把输出道的数据写入输出文?br>需要注意的是,道的本质只是一个共享的内存区域。这个实验中Q管道区域处于父q程的地址I间中,父进E的作用是提供环境和资源Qƈ协调子进E进行加工?br>E序源码Q?br>
代码:
#include <windows.h> 
#include <iostream.h>
const int BUFSIZE = 4096 ; 
HANDLE  hChildStdinRd, hChildStdinWr, hChildStdinWrDup, 
       hChildStdoutRd,hChildStdoutWr,hChildStdoutRdDup, 
    hSaveStdin,    hSaveStdout; 
BOOL CreateChildProcess(LPTSTR); 
VOID WriteToPipe(LPTSTR); 
VOID ReadFromPipe(LPTSTR); 
VOID ErrorExit(LPTSTR); 
VOID ErrMsg(LPTSTR, BOOL); 
void main( int argc, char *argv[] ) 
{  
  // 处理输入参数
  if ( argc != 4 )
    return ;
  // 分别用来保存命o行,输入文g名(CPP/CQ,输出文g名(保存~译信息Q?
  LPTSTR lpProgram = new char[ strlen(argv[1]) ] ;
  strcpy ( lpProgram, argv[1] ) ;
  LPTSTR lpInputFile = new char[ strlen(argv[2]) ];
  strcpy ( lpInputFile, argv[2] ) ;
  LPTSTR lpOutputFile = new char[ strlen(argv[3]) ] ;
  strcpy ( lpOutputFile, argv[3] ) ;    
  
  SECURITY_ATTRIBUTES saAttr; 
  saAttr.nLength = sizeof(SECURITY_ATTRIBUTES); 
  saAttr.bInheritHandle = TRUE; 
  saAttr.lpSecurityDescriptor = NULL; 
   
  /************************************************
   *    redirecting child process's STDOUT  *
   ************************************************/
  hSaveStdout = GetStdHandle(STD_OUTPUT_HANDLE); 
  
  if (! CreatePipe(&hChildStdoutRd, &hChildStdoutWr, &saAttr, 0)) 
    ErrorExit("Stdout pipe creation failed\n"); 
    
  if (! SetStdHandle(STD_OUTPUT_HANDLE, hChildStdoutWr)) 
    ErrorExit("Redirecting STDOUT failed"); 
  
  BOOL fSuccess = DuplicateHandle(
    GetCurrentProcess(), 
    hChildStdoutRd,
        GetCurrentProcess(), 
    &hChildStdoutRdDup ,
    0,
        FALSE,
        DUPLICATE_SAME_ACCESS);
    if( !fSuccess )
        ErrorExit("DuplicateHandle failed");
    CloseHandle(hChildStdoutRd);
  
  /************************************************
   *    redirecting child process's STDIN    *
   ************************************************/
  hSaveStdin = GetStdHandle(STD_INPUT_HANDLE); 
  if (! CreatePipe(&hChildStdinRd, &hChildStdinWr, &saAttr, 0)) 
    ErrorExit("Stdin pipe creation failed\n"); 
  
  if (! SetStdHandle(STD_INPUT_HANDLE, hChildStdinRd)) 
    ErrorExit("Redirecting Stdin failed"); 
  
  fSuccess = DuplicateHandle(
    GetCurrentProcess(), 
    hChildStdinWr, 
    GetCurrentProcess(),
    &hChildStdinWrDup, 
    0, 
    FALSE,                 
    DUPLICATE_SAME_ACCESS); 
  if (! fSuccess) 
    ErrorExit("DuplicateHandle failed"); 
  CloseHandle(hChildStdinWr);   
  /************************************************
   *      创徏子进E(卛_动SAMPLE.EXEQ?nbsp;   *
   ************************************************/
  fSuccess = CreateChildProcess( lpProgram );
  if ( !fSuccess ) 
    ErrorExit("Create process failed"); 
  
  // 父进E输入输出流的还原设|?
  if (! SetStdHandle(STD_INPUT_HANDLE, hSaveStdin)) 
    ErrorExit("Re-redirecting Stdin failed\n"); 
  if (! SetStdHandle(STD_OUTPUT_HANDLE, hSaveStdout)) 
    ErrorExit("Re-redirecting Stdout failed\n"); 
  WriteToPipe( lpInputFile ) ;
  ReadFromPipe( lpOutputFile ); 
          delete lpProgram ;
          delete lpInputFile ;
          delete lpOutputFile ;
} 
BOOL CreateChildProcess( LPTSTR lpProgram ) 
{ 
  PROCESS_INFORMATION piProcInfo; 
  STARTUPINFO siStartInfo;
  BOOL bFuncRetn = FALSE; 
  
  ZeroMemory( &piProcInfo, sizeof(PROCESS_INFORMATION) );
  ZeroMemory( &siStartInfo, sizeof(STARTUPINFO) );
  siStartInfo.cb = sizeof(STARTUPINFO); 
  
  bFuncRetn = CreateProcess ( NULL, lpProgram, NULL, NULL, TRUE, \
                0, NULL, NULL, &siStartInfo, &piProcInfo);
  if (bFuncRetn == 0) 
  {
    ErrorExit("CreateProcess failed\n");
    return 0;
  } 
  else 
  {
    CloseHandle(piProcInfo.hProcess);
    CloseHandle(piProcInfo.hThread);
    return bFuncRetn;
  }
}
VOID WriteToPipe( LPTSTR lpInputFile ) 
{ 
  HANDLE hInputFile = CreateFile(lpInputFile, GENERIC_READ, 0, NULL, 
    OPEN_EXISTING, FILE_ATTRIBUTE_READONLY, NULL); 
  if (hInputFile == INVALID_HANDLE_VALUE) 
    return ;
  BOOL fSuccess ;
  DWORD dwRead, dwWritten; 
  CHAR chBuf[BUFSIZE] = {0} ; 
  
  for (;;) 
  { 
    fSuccess = ReadFile( hInputFile, chBuf, BUFSIZE, &dwRead, NULL) ;
    if ( !fSuccess || dwRead == 0)
      break; 
    fSuccess = WriteFile( hChildStdinWrDup, chBuf, dwRead, &dwWritten, NULL) ;
    if ( !fSuccess ) 
      break; 
  } 
    
  if (! CloseHandle(hChildStdinWrDup)) 
    ErrorExit("Close pipe failed\n"); 
  CloseHandle ( hInputFile ) ;
} 
VOID ReadFromPipe( LPTSTR lpOutputFile ) 
{ 
  HANDLE hOutputFile = CreateFile( lpOutputFile, GENERIC_READ|GENERIC_WRITE, 
    FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); 
  if (hOutputFile == INVALID_HANDLE_VALUE) 
    return ;
  BOOL fSuccess ;
  DWORD dwRead, dwWritten; 
  CHAR chBuf[BUFSIZE] = { 0 }; 
  
  if (!CloseHandle(hChildStdoutWr)) 
    ErrorExit("Closing handle failed"); 
  
  for (;;) 
  { 
    fSuccess = ReadFile( hChildStdoutRdDup, chBuf, BUFSIZE, &dwRead, NULL) ;
    if( !fSuccess || dwRead == 0) 
    {
      break; 
    }
    fSuccess = WriteFile( hOutputFile, chBuf, dwRead, &dwWritten, NULL) ;
    if ( !fSuccess ) 
      break; 
  } 
  CloseHandle ( hOutputFile ) ;
} 
VOID ErrorExit (LPTSTR lpszMessage) 
{ 
  MessageBox( 0, lpszMessage, 0, 0 ); 
}
二、命名管?br>命名道h以下几个特征Q?br>Q?Q命名管道是双向的,所以两个进E可以通过同一道q行交互?br>Q?Q命名管道不但可以面向字节流Q还可以面向消息Q所以读取进E可以读取写q程发送的不同长度的消息?br>Q?Q多个独立的道实例可以用一个名U来命名。例如几个客L可以使用名称相同的管道与同一个服务器q行q发通信?br>Q?Q命名管道可以用于网l间两个q程的通信Q而其实现的过E与本地q程通信完全一致?br>实验目标Q在客户端输入数据a和bQ然后发送到服务器ƈ计算a+b,然后把计结果发送到客户端。可以多个客L与同一个服务器q行通信?br>界面设计Q?br> http://bbs.pediy.com/upload/2006/41/image/namedpipe.gif 
隄所在:
实现的过E比较简单,但有一个难炏V原本当服务端用ConnectNamedPipe函数后,如果有客Lq接Q就可以直接q行交互。原来我在实现过E中Q当道I闲Ӟ道的线E函C无限QINFINITEQ阻塞。若现在需要停止服务,必ȝ束所有的U程QTernimateThread可以作ؓ一个结束线E的ҎQ但我基本不用这个函数。一旦用这个函C后,目标U程׃立即l束Q但如果此时的目标线E正在操作互斥资源、内核调用、或者是操作׃nDLL的全局变量Q可能会出现互斥资源无法释放、内核异常等现象。这里我用重叠I/0来解册个问题,在创建PIPE时用FILE_FLAG_OVERLAPPED标志Q这样用ConnectNamedPipe后会立即q回Q但U程的阻塞由{待函数WaitForSingleObject来实玎ͼ{待OVERLAPPEDl构的事件对象被讄?br>客户端主要代码:
代码:
void CMyDlg::OnSubmit() 
{
  // 打开道
  HANDLE hPipe = CreateFile("\\\\.\\Pipe\\NamedPipe", GENERIC_READ | GENERIC_WRITE, \
    0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL) ;
  if ( hPipe == INVALID_HANDLE_VALUE )
  {
    this->MessageBox ( "打开道p|Q服务器未启动,或者客L数量q多" ) ;
    return ;
  }
  DWORD nReadByte, nWriteByte ;
  char szBuf[1024] = {0} ;
  // 把两个整?a,b)格式化ؓ字符?
  sprintf ( szBuf, "%d %d", this->nFirst, this->nSecond ) ;
  // 把数据写入管?
  WriteFile ( hPipe, szBuf, strlen(szBuf), &nWriteByte, NULL ) ;
  memset ( szBuf, 0, sizeof(szBuf) ) ;
  // d服务器的反馈信息
  ReadFile ( hPipe, szBuf, 1024, &nReadByte, NULL ) ;
  // 把返回信息格式化为整?
  sscanf ( szBuf, "%d", &(this->nResValue) ) ;
  this->UpdateData ( false ) ;
  CloseHandle ( hPipe ) ;
}
服务端主要代码:
代码:
// 启动服务
void CMyDlg::OnStart() 
{
  CString lpPipeName = "\\\\.\\Pipe\\NamedPipe" ;
  for ( UINT i = 0; i < nMaxConn; i++ )
  {
    // 创徏道实例
    PipeInst[i].hPipe =  CreateNamedPipe ( lpPipeName, PIPE_ACCESS_DUPLEX|FILE_FLAG_OVERLAPPED, \
          PIPE_TYPE_BYTE|PIPE_READMODE_BYTE|PIPE_WAIT, nMaxConn, 0, 0, 1000, NULL ) ;
    if ( PipeInst[i].hPipe == INVALID_HANDLE_VALUE )
    {
      DWORD dwErrorCode = GetLastError () ;
      this->MessageBox ( "创徏道错误Q? ) ;
      return ;
    }
    // 为每个管道实例创Z个事件对象,用于实现重叠IO
    PipeInst[i].hEvent  =  CreateEvent ( NULL, false, false, false ) ;
    // 为每个管道实例分配一个线E,用于响应客户端的h
    PipeInst[i].hTread = AfxBeginThread ( ServerThread, &PipeInst[i], THREAD_PRIORITY_NORMAL ) ;
  }
  
  this->SetWindowText ( "命名道实例之服务器(q行)" ) ;
  this->MessageBox ( "服务启动成功" ) ;
}
// 停止服务
void CMyDlg::OnStop() 
{
  DWORD dwNewMode = PIPE_TYPE_BYTE|PIPE_READMODE_BYTE|PIPE_NOWAIT ;
  for ( UINT i = 0; i < nMaxConn; i++ )
  {
    SetEvent ( PipeInst[i].hEvent ) ;
    CloseHandle ( PipeInst[i].hTread ) ;
    CloseHandle ( PipeInst[i].hPipe ) ;
  }
    
  this->SetWindowText ( "命名道实例之服务器" ) ;
  this->MessageBox ( "停止启动成功" ) ;
}
// U程服务函数
UINT ServerThread ( LPVOID lpParameter )
{
  DWORD  nReadByte = 0, nWriteByte = 0, dwByte = 0 ;  
  char  szBuf[MAX_BUFFER_SIZE] = {0} ;
  PIPE_INSTRUCT  CurPipeInst = *(PIPE_INSTRUCT*)lpParameter ;
  OVERLAPPED OverLapStruct = { 0, 0, 0, 0, CurPipeInst.hEvent } ;
  while ( true )
  {
    memset ( szBuf, 0, sizeof(szBuf) ) ;  
    // 命名道的连接函敎ͼ{待客户端的q接Q只针对NTQ?
    ConnectNamedPipe ( CurPipeInst.hPipe, &OverLapStruct ) ;
    // 实现重叠I/0Q等待OVERLAPPEDl构的事件对?
    WaitForSingleObject ( CurPipeInst.hEvent, INFINITE ) ;
    // I/0是否已经完成Q如果未完成Q意味着该事件对象是人工讄Q即服务需要停?
    if ( !GetOverlappedResult ( CurPipeInst.hPipe, &OverLapStruct, &dwByte, true ) )
      break ;
    // 从管道中d客户端的h信息
    if ( !ReadFile ( CurPipeInst.hPipe, szBuf, MAX_BUFFER_SIZE, &nReadByte, NULL ) )
    {
      MessageBox ( 0, "d道错误Q?, 0, 0 ) ;
      break ;
    }
    
    int a, b ;
    sscanf ( szBuf, "%d %d", &a, &b ) ;
    pMyDlg->nFirst    = a ;
    pMyDlg->nSecond    = b ;
    pMyDlg->nResValue  = a + b ;
    memset ( szBuf, 0, sizeof(szBuf) ) ;
    sprintf ( szBuf, "%d", pMyDlg->nResValue ) ;
    // 把反馈信息写入管?
    WriteFile ( CurPipeInst.hPipe, szBuf, strlen(szBuf), &nWriteByte, NULL ) ;
    pMyDlg->SetDlgItemInt ( IDC_FIRST, a, true ) ;
    pMyDlg->SetDlgItemInt ( IDC_SECOND, b, true ) ;
    pMyDlg->SetDlgItemInt ( IDC_RESULT, pMyDlg->nResValue, true ) ;
    // 断开客户端的q接Q以便等待下一客户的到?
    DisconnectNamedPipe ( CurPipeInst.hPipe ) ;
  }
  return 0 ;
}


]]>
setsockopt()http://www.shnenglu.com/zhengxf/archive/2010/11/04/132435.html郑兴?/dc:creator>郑兴?/author>Thu, 04 Nov 2010 06:32:00 GMThttp://www.shnenglu.com/zhengxf/archive/2010/11/04/132435.htmlhttp://www.shnenglu.com/zhengxf/comments/132435.htmlhttp://www.shnenglu.com/zhengxf/archive/2010/11/04/132435.html#Feedback0http://www.shnenglu.com/zhengxf/comments/commentRss/132435.htmlhttp://www.shnenglu.com/zhengxf/services/trackbacks/132435.htmlsetsockopt()

目录

注释Q?/font>
q回|
用法

  讄套接口的选项?
  #include <winsock.h>
  int PASCAL FAR setsockopt( SOCKET s, int level, int optname,
  const char FAR* optval, int optlen);
  sQ标识一个套接口的描q字?
  levelQ选项定义的层ơ;目前仅支持SOL_SOCKET和IPPROTO_TCP层次?
  optnameQ需讄的选项?
  optvalQ指针,指向存放选项值的~冲区?
  optlenQoptval~冲区的长度?

注释Q?/h2>   setsockopt()函数用于Lcd、Q意状态套接口的设|选项倹{尽在不同协议层上存在选项Q但本函C定义了最高的“套接?#8221;层次上的选项。选项影响套接口的操作Q诸如加急数据是否在普通数据流中接Ӟq播数据是否可以从套接口发送等{?
  有两U套接口的选项Q一U是布尔型选项Q允许或止一U特性;另一U是整Ş或结构选项。允怸个布型选项Q则optval指向非零整Ş敎ͼ止一个选项optval指向一个等于零的整形数。对于布型选项Qoptlen应等于sizeof(int)Q对其他选项Qoptval指向包含所需选项的整形数或结构,而optlen则ؓ整Ş数或l构的长度。SO_LINGER选项用于控制下述情况的行动:套接口上有排队的待发送数据,?a target=_blank>closesocket()调用已执行。参见closesocket()函数中关于SO_LINGER选项对closesocket()语义的媄响。应用程序通过创徏一个lingerl构来设|相应的操作Ҏ:
  struct linger {
  int l_onoff;
  int l_linger;
  };
  Z允许SO_LINGERQ应用程序应l_onoff设ؓ非零Q将l_linger设ؓ零或需要的时|以秒为单位)Q然后调用setsockopt()。ؓ了允许SO_DONTLINGERQ亦即禁止SO_LINGERQ,l_onoff应设为零Q然后调用setsockopt()?
  ~省条g下,一个套接口不能与一个已在用中的本地地址捆绑Q参?a target=_blank>bind()Q。但有时会需?#8220;重用”地址。因为每一个连接都由本地地址和远端地址的组合唯一定Q所以只要远端地址不同Q两个套接口与一个地址捆绑q无大碍。ؓ了通知WINDOWS套接口实C要因Z个地址已被一个套接口使用׃让它与另一个套接口捆绑Q应用程序可在bind()调用前先讄SO_REUSEADDR选项。请注意仅在bind()调用时该选项才被解释Q故此无需Q但也无宻I一个不会共用地址的套接口讄该选项Q或者在bind()对这个或其他套接口无影响情况下设|或清除q一选项?
  一个应用程序可以通过打开SO_KEEPALIVE选项Q得WINDOWS套接口实现在TCPq接情况下允怋?#8220;保持zd”包。一个WINDOWS套接口实现ƈ不是必需支持“保持zd”Q但是如果支持的话,具体的语义将与实现有养I应遵守RFC1122“InternetL要求Q通讯?#8221;中第4.2.3.6节的规范。如果有兌接由?#8220;保持zd”而失效,则进行中的Q何对该套接口的调用都以WSAENETRESET错误q回Q后l的M调用以WSAENOTCONN错误q回?
  TCP_NODELAY选项止Nagle法。Nagle法通过未认的数据存入缓冲区直到蓄一个包一起发送的ҎQ来减少L发送的零碎数据包的数目。但对于某些应用来说Q这U算法将降低pȝ性能。所以TCP_NODELAY可用来将此算法关闭。应用程序编写者只有在切了解它的效果q确实需要的情况下,才设|TCP_NODELAY选项Q因|后对网l性能有明昄负面影响。TCP_NODELAY是唯一使用IPPROTO_TCP层的选项Q其他所有选项都用SOL_SOCKET层?
  如果讄了SO_DEBUG选项QWINDOWS套接口供应商被鼓励(但不是必需Q提供输出相应的调试信息。但产生调试信息的机制以及调试信息的形式已超出本规范的讨围?
  setsockopt()支持下列选项。其?#8220;cd”表明optval所指数据的cd?
  选项 cd 意义
  SO_BROADCAST BOOL 允许套接口传送广播信息?
  SO_DEBUG BOOL 记录调试信息?
  SO_DONTLINER BOOL 不要因ؓ数据未发送就d关闭操作。设|本选项相当于将SO_LINGER的l_onoff元素|ؓ零?
  SO_DONTROUTE BOOL 止选径Q直接传送?
  SO_KEEPALIVE BOOL 发?#8220;保持zd”包?
  SO_LINGER struct linger FAR* 如关闭时有未发送数据,则逗留?
  SO_OOBINLINE BOOL 在常规数据流中接收带外数据?
  SO_RCVBUF int 为接收确定缓冲区大小?
  SO_REUSEADDR BOOL 允许套接口和一个已在用中的地址捆绑Q参见bind()Q?
  SO_SNDBUF int 指定发送缓冲区大小?
  TCP_NODELAY BOOL 止发送合q的Nagle法?
  setsockopt()不支持的BSD选项有:
  选项?cd 意义
  SO_ACCEPTCONN BOOL 套接口在监听?
  SO_ERROR int 获取错误状态ƈ清除?
  SO_RCVLOWAT int 接收低水印?
  SO_RCVTIMEO int 接收时?
  SO_SNDLOWAT int 发送低U水印?
  SO_SNDTIMEO int 发送超时?
  SO_TYPE int 套接口类型?
  IP_OPTIONS 在IP头中讄选项?

q回|

  若无错误发生Qsetsockopt()q回0。否则的话,q回SOCKET_ERROR错误Q应用程序可通过WSAGetLastError()获取相应错误代码?
  错误代码Q?
  WSANOTINITIALISEDQ在使用此API之前应首先成功地调用WSAStartup()?
  WSAENETDOWNQWINDOWS套接口实现检到|络子系l失效?
  WSAEFAULTQoptval不是q程地址I间中的一个有效部分?
  WSAEINPROGRESSQ一个阻塞的WINDOWS套接口调用正在运行中?
  WSAEINVALQlevel值非法,或optval中的信息非法?
  WSAENETRESETQ当SO_KEEPALIVE讄后连接超时?
  WSAENOPROTOOPTQ未知或不支持选项。其中,SOCK_STREAMcd的套接口不支持SO_BROADCAST选项QSOCK_DGRAMcd的套接口不支持SO_DONTLINGER 、SO_KEEPALIVE、SO_LINGER和SO_OOBINLINE选项?
  WSAENOTCONNQ当讄SO_KEEPALIVE后连接被复位?
  WSAENOTSOCKQ描q字不是一个套接口?

用法

  1.讄调用closesocket()?仍可l箋重用该socket。调用closesocket()一般不会立卛_闭socketQ而经历TIME_WAIT的过E?
  BOOL bReuseaddr = TRUE;
  setsockopt( s, SOL_SOCKET, SO_REUSEADDR, ( const char* )&bReuseaddr, sizeof( BOOL ) );
  2. 如果要已l处于连接状态的soket在调用closesocket()后强制关闭,不经历TIME_WAIT的过E:
  BOOL bDontLinger = FALSE;
  setsockopt( s, SOL_SOCKET, SO_DONTLINGER, ( const char* )&bDontLinger, sizeof( BOOL ) );
  3.在send(),recv()q程中有时由于网l状늭原因Q收发不能预期进?可以讄收发旉Q?
  int nNetTimeout = 1000; //1U?
  //发送时?
  setsockopt( socket, SOL_SOCKET, SO_SNDTIMEO, ( char * )&nNetTimeout, sizeof( int ) );
  //接收旉
  setsockopt( socket, SOL_SOCKET, SO_RCVTIMEO, ( char * )&nNetTimeout, sizeof( int ) );
  4.在send()的时候,q回的是实际发送出ȝ字节(同步)或发送到socket~冲区的字节(异步)Q系l默认的状态发送和接收一ơؓ8688字节(U?
  ?.5K)Q在实际的过E中如果发送或是接收的数据量比较大Q可以设|socket~冲区,避免send(),recv()不断的@环收发:
  // 接收~冲?
  int nRecvBuf = 32 * 1024; //讄?2K
  setsockopt( s, SOL_SOCKET, SO_RCVBUF, ( const char* )&nRecvBuf, sizeof( int ) );
  //发送缓冲区
  int nSendBuf = 32*1024; //讄?2K
  setsockopt( s, SOL_SOCKET, SO_SNDBUF, ( const char* )&nSendBuf, sizeof( int ) );
  5.在发送数据的Ӟ不执行由pȝ~冲区到socket~冲区的拯Q以提高E序的性能Q?
  int nZero = 0;
  setsockopt( socket, SOL_S0CKET, SO_SNDBUF, ( char * )&nZero, sizeof( nZero ) );
  6.在接收数据时Q不执行socket~冲区的内容拯到系l缓冲区Q?
  int nZero = 0;
  setsockopt( s, SOL_S0CKET, SO_RCVBUF, ( char * )&nZero, sizeof( int ) );
  7.一般在发送UDP数据报的时候,希望该socket发送的数据hq播Ҏ:
  BOOL bBroadcast = TRUE;
  setsockopt( s, SOL_SOCKET, SO_BROADCAST, ( const char* )&bBroadcast, sizeof( BOOL ) );
  8.在clientq接服务器过E中Q如果处于非d模式下的socket在connect()的过E中可以讄connect()延时,直到accpet()被调?此设|只
  有在非阻塞的q程中有显著的作用,在阻塞的函数调用中作用不?
  BOOL bConditionalAccept = TRUE;
  setsockopt( s, SOL_SOCKET, SO_CONDITIONAL_ACCEPT, ( const char* )&bConditionalAccept, sizeof( BOOL ) );
  9.如果在发送数据的q程中send()没有完成Q还有数据没发送,而调用了closesocket(),以前一般采取的措施是shutdown(s,SD_BOTH),但是?
  据将会丢失?
  某些具体E序要求待未发送完的数据发送出d再关闭socketQ可通过讄让程序满求:
  struct linger {
  u_short l_onoff;
  u_short l_linger;
  };
  linger m_sLinger;
  m_sLinger.l_onoff = 1; //在调用closesocket()时还有数据未发送完Q允许等?
  // 若m_sLinger.l_onoff=0;则调用closesocket()后强制关?
  m_sLinger.l_linger = 5; //讄{待旉?U?
  setsockopt( s, SOL_SOCKET, SO_LINGER, ( const char* )&m_sLinger, sizeof( linger ) );


]]>
ioctlsockethttp://www.shnenglu.com/zhengxf/archive/2010/11/04/132418.html郑兴?/dc:creator>郑兴?/author>Thu, 04 Nov 2010 04:13:00 GMThttp://www.shnenglu.com/zhengxf/archive/2010/11/04/132418.htmlhttp://www.shnenglu.com/zhengxf/comments/132418.htmlhttp://www.shnenglu.com/zhengxf/archive/2010/11/04/132418.html#Feedback0http://www.shnenglu.com/zhengxf/comments/commentRss/132418.htmlhttp://www.shnenglu.com/zhengxf/services/trackbacks/132418.html#include <winsock.h>   int PASCAL FAR ioctlsocket( SOCKET s, long cmd, u_long FAR* argp);   
sQ一个标识套接口的描q字?  
cmdQ对套接口s的操作命令?  
argpQ指向cmd命o所带参数的指针?  
注释Q?  本函数可用于M状态的M套接口。它用于获取与套接口相关的操作参敎ͼ而与具体协议或通讯子系l无兟뀂支持下列命令:   FIONBIOQ允许或止套接口s的非d模式。argp指向一个无W号长整型。如允许非阻塞模式则非零Q如止非阻塞模式则为零。当创徏一个套接口Ӟ它就处于d模式Q也是说非d模式被禁止)。这与BSD套接口是一致的。WSAAsynSelect()函数套接口自动讄为非d模式。如果已对一个套接口q行了WSAAsynSelect() 操作Q则M用ioctlsocket()来把套接口重新设|成d模式的试囑ְ以WSAEINVALp|。ؓ了把套接口重新设|成d模式Q应用程序必首先用WSAAsynSelect()调用QIEvent参数|ؓ0Q来至WSAAsynSelect()?  FIONREADQ确定套接口s自动d的数据量。argp指向一个无W号长整型,其中存有ioctlsocket()的返回倹{如果s是SOCKET_STREAMcdQ则FIONREADq回在一ơrecv()中所接收的所有数据量。这通常与套接口中排队的数据总量相同。如果S是SOCK_DGRAM 型,则FIONREADq回套接口上排队的第一个数据报大小?  SIOCATMARKQ确实是否所有的带外数据都已被读入。这个命令仅适用于SOCK_STREAMcd的套接口Q且该套接口已被讄为可以在U接收带外数据(SO_OOBINLINEQ。如无带外数据等待读入,则该操作q回TRUE真。否则的话返回FALSE假,下一个recv()或recvfrom()操作检?#8220;标记”前一些或所有数据。应用程序可用SIOCATMARK操作来确定是否有数据剩下。如果在“紧?#8221;Q带外)数据前有常规数据Q则按序接收q些数据Q请注意Qrecv()和recvfrom()操作不会在一ơ调用中h常规数据与带外数据)。argp指向一个BOOL型数Qioctlsocket()在其中存入返回倹{?  兼容性:   本函CؓBerkeley套接口函数ioctl()的一个子集。其中没有与FIOASYNC{h的命令,SIOCATMARK是套接口层次支持的唯一命o?  q回|   成功后,ioctlsocket()q回0。否则的话,q回SOCKET_ERROR错误Q应用程序可通过WSAGetLastError()获取相应错误代码?  错误代码Q?  WSANOTINITIALISEDQ在使用此API之前应首先成功地调用WSAStartup()?  WSAENETDOWNQWINDOWS套接口实现检到|络子系l失效?  WSAEINVALQcmd为非法命令,或者argp所指参C适用于该cmd命oQ或者该命o   不适用于此U类型的套接口?  WSAEINPROGRESSQ一个阻塞的WINDOWS套接口调用正在运行中?  WSAENOTSOCKQ描q字不是一个套接口?  参见Q?  socket(), setsockopt(), getsockopt(), WSAAsyncSelect().   该命?nbsp;    不适用于此U类型的套接口?nbsp;    WSAEINPROGRESSQ一个阻塞的WINDOWS套接口调用正在运行中?nbsp;    WSAENOTSOCKQ描q字不是一个套接口?

]]>
一个通信模块,希望大家指点不.http://www.shnenglu.com/zhengxf/archive/2010/10/21/130775.html郑兴?/dc:creator>郑兴?/author>Thu, 21 Oct 2010 09:51:00 GMThttp://www.shnenglu.com/zhengxf/archive/2010/10/21/130775.htmlhttp://www.shnenglu.com/zhengxf/comments/130775.htmlhttp://www.shnenglu.com/zhengxf/archive/2010/10/21/130775.html#Feedback0http://www.shnenglu.com/zhengxf/comments/commentRss/130775.htmlhttp://www.shnenglu.com/zhengxf/services/trackbacks/130775.html 
通信模块?br>

  
  通信关系?br> 
其中有不的地方, 希望朋友们提出意?



]]>
91鶹Ʒ91þþ| 99þþþ| ҹƷþþþþëƬ| ˾þô߽AV| þþƷ| ޹˾ƷŮ˾þþ | 97þþþ޾Ʒר| þþþѿӰƬ| 99þùۺϾƷԭ| þþƷ޸| պƷþþþþ| ˾þ91| 99þۺϹƷ| þþƷ99Ӱ | www.þ.com| Ʒþþþa| þ㽶ۺɫһۺɫ88| þ¶ݺɫ| Ʒþþþһ| þþþAVר| ŷۺϾþͼƬ| ھƷþþþþ99 | 㽶aaþëƬ| ŷƷ˾þ| Ʒþþþá| þӰԺۺϾƷ| þóСƵ| Ұ¾þһ| ĻƷþþþþ3Dն | ˺ݺۺϾþ88| þþþĸ| þþƷһAV| ޹Ƶþ| 㽶þAһ| ݺݾþۺ˲| 91鶹Ʒ91þþþþ| Ưޱ˾þþƷ| 97Ʒ˾þþô߽97| þĻƷһ| þþƷ2020| ˳ɾƷþþþ|