??xml version="1.0" encoding="utf-8" standalone="yes"?>久久国产精品99精品国产,狠狠色丁香婷综合久久,久久国产精品久久久http://www.shnenglu.com/jjbird/category/704.html奇奇的空?/description>zh-cnTue, 20 May 2008 08:00:39 GMTTue, 20 May 2008 08:00:39 GMT60多屏~程之如何获取显卡信息判断是否ؓ多屏http://www.shnenglu.com/jjbird/articles/15701.html奇奇奇奇Mon, 27 Nov 2006 08:18:00 GMThttp://www.shnenglu.com/jjbird/articles/15701.htmlhttp://www.shnenglu.com/jjbird/comments/15701.htmlhttp://www.shnenglu.com/jjbird/articles/15701.html#Feedback0http://www.shnenglu.com/jjbird/comments/commentRss/15701.htmlhttp://www.shnenglu.com/jjbird/services/trackbacks/15701.html
在stdafx.h
中加入:
#undef WINVER
#define WINVER 0x0500

*************************************************************

#ifndef SM_CMONITORS

typedef HANDLE HMONITOR;

#endif
#ifndef DISPLAY_DEVICE_PRIMARY_DEVICE

typedef struct _DISPLAY_DEVICE {
DWORD cb;
TCHAR DeviceName[32];
TCHAR DeviceString[128];
DWORD StateFlags;
} DISPLAY_DEVICE, *PDISPLAY_DEVICE, *LPDISPLAY_DEVICE;
#define DISPLAY_DEVICE_ATTACHED_TO_DESKTOP 0x00000001
#define DISPLAY_DEVICE_MULTI_DRIVER 0x00000002
#define DISPLAY_DEVICE_PRIMARY_DEVICE 0x00000004
#define DISPLAY_DEVICE_VGA 0x00000010

#endif

typedef BOOL (WINAPI* pEnumDisplayDevices)(PVOID,DWORD,PVOID,DWORD);
typedef BOOL (WINAPI* pEnumDisplaySettings)(PVOID,DWORD,PVOID);

pEnumDisplayDevices pStartEnumDisplayDevices;
pEnumDisplaySettings pStartEnumDisplaySettings;


*********************************************************************


int iCount;

pStartEnumDisplayDevices = (pEnumDisplayDevices)GetProcAddress(LoadLibrary("USER32"), "EnumDisplayDevicesA");
pStartEnumDisplaySettings = (pEnumDisplaySettings)GetProcAddress(LoadLibrary("USER32"), "EnumDisplaySettingsA");


if (pStartEnumDisplayDevices && pStartEnumDisplaySettings)
{
DISPLAY_DEVICE dd;
DEVMODE dv;

ZeroMemory(&dv, sizeof(dv));
ZeroMemory(&dd, sizeof(dd));

dv.dmSize = sizeof(dv);
dd.cb = sizeof(dd);

for (iCount=0; (*pStartEnumDisplayDevices)(NULL, iCount, &dd, 0); iCount++)
{
(*pStartEnumDisplaySettings)(dd.DeviceName,ENUM_CURRENT_SETTINGS,&dv);
if((dd.StateFlags & DISPLAY_DEVICE_ATTACHED_TO_DESKTOP)
&&(dd.StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE))
{
CString strDispName,strScreen,strColor,strFreq;

strDispName.Format(_T("Device Name: %s "),dd.DeviceString);
SetDlgItemText(IDC_STATIC_DISP_NAME,strDispName);

strScreen.Format(_T("%d×%d "),dv.dmPelsWidth,dv.dmPelsHeight);
SetDlgItemText(IDC_STATIC_FREQ,strScreen);

strColor.Format(_T("%d Bit"),dv.dmBitsPerPel);
SetDlgItemText(IDC_STATIC_COLOR,strColor);

strFreq.Format(_T("%d Hz"),dv.dmDisplayFrequency);
SetDlgItemText(IDC_STATIC_REFRESH_FREQ,strFreq);
}
}
}


奇奇 2006-11-27 16:18 发表评论
]]>
iocore q箋q行21天后出错问题的分?/title><link>http://www.shnenglu.com/jjbird/articles/15292.html</link><dc:creator>奇奇</dc:creator><author>奇奇</author><pubDate>Fri, 17 Nov 2006 05:08:00 GMT</pubDate><guid>http://www.shnenglu.com/jjbird/articles/15292.html</guid><wfw:comment>http://www.shnenglu.com/jjbird/comments/15292.html</wfw:comment><comments>http://www.shnenglu.com/jjbird/articles/15292.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.shnenglu.com/jjbird/comments/commentRss/15292.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/jjbird/services/trackbacks/15292.html</trackback:ping><description><![CDATA[ <p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt"> <span lang="EN-US">iocore </span> <span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">q箋q行</span> <span lang="EN-US">21</span> <span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">天后E序出错Q地址?/span> <span lang="EN-US">0X10212AD0</span> <span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">Q报错ؓ</span> <span lang="EN-US">“unknown  software  exception  (0X80000003),</span> <span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">位置?/span> <span lang="EN-US">0X10212AD0?/span> <span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">Q经q分析ؓ</span> <span lang="EN-US">new</span> <span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">调用时出错,</span> </p> <p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt"> <span lang="EN-US"> <?xml:namespace prefix = v ns = "urn:schemas-microsoft-com:vml" /?> <v:shapetype id="_x0000_t75" stroked="f" filled="f" path="m@4@5l@4@11@9@11@9@5xe" o:preferrelative="t" o:spt="75" coordsize="21600,21600"> <v:stroke joinstyle="miter"> </v:stroke> <v:formulas> <v:f eqn="if lineDrawn pixelLineWidth 0"> </v:f> <v:f eqn="sum @0 1 0"> </v:f> <v:f eqn="sum 0 0 @1"> </v:f> <v:f eqn="prod @2 1 2"> </v:f> <v:f eqn="prod @3 21600 pixelWidth"> </v:f> <v:f eqn="prod @3 21600 pixelHeight"> </v:f> <v:f eqn="sum @0 0 1"> </v:f> <v:f eqn="prod @6 1 2"> </v:f> <v:f eqn="prod @7 21600 pixelWidth"> </v:f> <v:f eqn="sum @8 21600 0"> </v:f> <v:f eqn="prod @7 21600 pixelHeight"> </v:f> <v:f eqn="sum @10 21600 0"> </v:f> </v:formulas> <v:path o:connecttype="rect" gradientshapeok="t" o:extrusionok="f"> </v:path> <?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /?> <o:lock aspectratio="t" v:ext="edit"> </o:lock> </v:shapetype> <v:shape id="_x0000_i1025" style="WIDTH: 303pt; HEIGHT: 105pt" o:ole="" type="#_x0000_t75"> <v:imagedata o:title="" src="file:///C:/DOCUME~1/ADMINI~1/LOCALS~1/Temp/msoclip1/01/clip_image001.png"> </v:imagedata> </v:shape> </span> </p> <p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt"> <span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">跟踪E序?/span> <span lang="EN-US">_heap_alloc_dbg</span> </p> <p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt"> <span lang="EN-US" style="COLOR: #115e94; FONT-FAMILY: Tahoma">void * __cdecl _heap_alloc_dbg(<br />        size_t nSize,<br />        int nBlockUse,<br />        const char * szFileName,<br />        int nLine<br />        )<br />{<br />        long lRequest;<br />        size_t blockSize;<br />        int fIgnore = FALSE;<br />        _CrtMemBlockHeader * pHead;<br /><br />        /* verify heap before allocation */<br />        if (_crtDbgFlag & _CRTDBG_CHECK_ALWAYS_DF)<br />            _ASSERTE(_CrtCheckMemory());<br /><br />        lRequest = _lRequestCurr;<br /><br />        /* break into debugger at specific memory allocation */<br />        if (lRequest == _crtBreakAlloc)<br />            _CrtDbgBreak();<br />// here is the place were the app stops<br /><br />// ... function continuous<br style="mso-special-character: line-break" /><br style="mso-special-character: line-break" /><o:p></o:p></span> </p> <p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt"> <span lang="EN-US" style="COLOR: #115e94; FONT-FAMILY: Tahoma"> <o:p></o:p></span> </p> <p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt"> <span lang="EN-US" style="FONT-FAMILY: Tahoma">_crtBreakAlloc </span> <span style="FONT-FAMILY: 宋体; mso-ascii-font-family: Tahoma; mso-hansi-font-family: Tahoma; mso-bidi-font-family: Tahoma">?/span> <span lang="EN-US" style="FONT-FAMILY: Tahoma">-1</span> <span style="FONT-FAMILY: 宋体; mso-ascii-font-family: Tahoma; mso-hansi-font-family: Tahoma; mso-bidi-font-family: Tahoma">?/span> <span lang="EN-US" style="FONT-FAMILY: Tahoma">lRequest</span> <span style="FONT-FAMILY: 宋体; mso-ascii-font-family: Tahoma; mso-hansi-font-family: Tahoma; mso-bidi-font-family: Tahoma">?/span> <span lang="EN-US" style="FONT-FAMILY: Tahoma">long</span> <span style="FONT-FAMILY: 宋体; mso-ascii-font-family: Tahoma; mso-hansi-font-family: Tahoma; mso-bidi-font-family: Tahoma">型,?/span> <span lang="EN-US" style="FONT-FAMILY: Tahoma">new</span> <span style="FONT-FAMILY: 宋体; mso-ascii-font-family: Tahoma; mso-hansi-font-family: Tahoma; mso-bidi-font-family: Tahoma">一ơ,</span> <span lang="EN-US" style="FONT-FAMILY: Tahoma">_lRequestCurr</span> <span style="FONT-FAMILY: 宋体; mso-ascii-font-family: Tahoma; mso-hansi-font-family: Tahoma; mso-bidi-font-family: Tahoma">每调用一?/span> <span lang="EN-US" style="FONT-FAMILY: Tahoma">new</span> <span style="FONT-FAMILY: 宋体; mso-ascii-font-family: Tahoma; mso-hansi-font-family: Tahoma; mso-bidi-font-family: Tahoma">Q自动加</span> <span lang="EN-US" style="FONT-FAMILY: Tahoma">1</span> <span style="FONT-FAMILY: 宋体; mso-ascii-font-family: Tahoma; mso-hansi-font-family: Tahoma; mso-bidi-font-family: Tahoma">Q当</span> <span lang="EN-US" style="FONT-FAMILY: Tahoma">2147483647</span> <span style="FONT-FAMILY: 宋体; mso-ascii-font-family: Tahoma; mso-hansi-font-family: Tahoma; mso-bidi-font-family: Tahoma">再加</span> <span lang="EN-US" style="FONT-FAMILY: Tahoma">1</span> <span style="FONT-FAMILY: 宋体; mso-ascii-font-family: Tahoma; mso-hansi-font-family: Tahoma; mso-bidi-font-family: Tahoma">变成</span> <span lang="EN-US" style="FONT-FAMILY: Tahoma">-2147483648</span> <span style="FONT-FAMILY: 宋体; mso-ascii-font-family: Tahoma; mso-hansi-font-family: Tahoma; mso-bidi-font-family: Tahoma">Q一直篏加到</span> <span lang="EN-US" style="FONT-FAMILY: Tahoma">-1</span> <span style="FONT-FAMILY: 宋体; mso-ascii-font-family: Tahoma; mso-hansi-font-family: Tahoma; mso-bidi-font-family: Tahoma">Q然后调?/span> <span lang="EN-US" style="FONT-FAMILY: Tahoma">_CrtDbgBreak()</span> <span style="FONT-FAMILY: 宋体; mso-ascii-font-family: Tahoma; mso-hansi-font-family: Tahoma; mso-bidi-font-family: Tahoma">Q出错。看似是q个原因Qؓ了进一步确认,~写试E序</span> <span lang="EN-US" style="FONT-FAMILY: Tahoma"> <o:p> </o:p> </span> </p> <p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt"> <span lang="EN-US" style="FONT-FAMILY: Tahoma">class AA<o:p></o:p></span> </p> <p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt"> <span lang="EN-US" style="FONT-FAMILY: Tahoma">{<o:p></o:p></span> </p> <p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt"> <span lang="EN-US" style="FONT-FAMILY: Tahoma"> <span style="mso-tab-count: 1">       </span>char aa1[10];<o:p></o:p></span> </p> <p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt"> <span lang="EN-US" style="FONT-FAMILY: Tahoma"> <span style="mso-tab-count: 1">       </span>char aa2[12];<o:p></o:p></span> </p> <p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt"> <span lang="EN-US" style="FONT-FAMILY: Tahoma">};<o:p></o:p></span> </p> <p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt"> <span lang="EN-US" style="FONT-FAMILY: Tahoma"> <o:p></o:p></span> </p> <p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt"> <span lang="EN-US" style="FONT-FAMILY: Tahoma">int main(int argc, char* argv[])<o:p></o:p></span> </p> <p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt"> <span lang="EN-US" style="FONT-FAMILY: Tahoma">{<o:p></o:p></span> </p> <p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt"> <span lang="EN-US" style="FONT-FAMILY: Tahoma"> <span style="mso-tab-count: 1">       </span>AA *pp;<o:p></o:p></span> </p> <p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt"> <span lang="EN-US" style="FONT-FAMILY: Tahoma"> <span style="mso-tab-count: 1">       </span>while(1)<o:p></o:p></span> </p> <p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt"> <span lang="EN-US" style="FONT-FAMILY: Tahoma"> <span style="mso-tab-count: 1">       </span>{<o:p></o:p></span> </p> <p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt"> <span lang="EN-US" style="FONT-FAMILY: Tahoma"> <span style="mso-tab-count: 2">              </span>pp=new AA;<o:p></o:p></span> </p> <p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt"> <span lang="EN-US" style="FONT-FAMILY: Tahoma"> <span style="mso-tab-count: 2">              </span>delete pp;<o:p></o:p></span> </p> <p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt"> <span lang="EN-US" style="FONT-FAMILY: Tahoma"> <span style="mso-tab-count: 1">       </span>}<o:p></o:p></span> </p> <p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt"> <span lang="EN-US" style="FONT-FAMILY: Tahoma">}<o:p></o:p></span> </p> <p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt"> <span style="FONT-FAMILY: 宋体; mso-ascii-font-family: Tahoma; mso-hansi-font-family: Tahoma; mso-bidi-font-family: Tahoma">几个时后复C此现象?/span> <br /> <br />|上查找<span lang="EN-US">0X10212AD0</span> 有如下线索:<br /><a >http://www.experts-exchange.com/Programming/Programming_Languages/MFC/Q_21088390.html</a></p> <img src ="http://www.shnenglu.com/jjbird/aggbug/15292.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/jjbird/" target="_blank">奇奇</a> 2006-11-17 13:08 <a href="http://www.shnenglu.com/jjbird/articles/15292.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Z防止发生内存泄漏遵循的~程规范http://www.shnenglu.com/jjbird/articles/11602.html奇奇奇奇Wed, 23 Aug 2006 02:21:00 GMThttp://www.shnenglu.com/jjbird/articles/11602.htmlhttp://www.shnenglu.com/jjbird/comments/11602.htmlhttp://www.shnenglu.com/jjbird/articles/11602.html#Feedback0http://www.shnenglu.com/jjbird/comments/commentRss/11602.htmlhttp://www.shnenglu.com/jjbird/services/trackbacks/11602.html

奇奇 2006-08-23 10:21 发表评论
]]>
VC Studio 使用技巧、VC目文g说明http://www.shnenglu.com/jjbird/articles/11597.html奇奇奇奇Wed, 23 Aug 2006 01:02:00 GMThttp://www.shnenglu.com/jjbird/articles/11597.htmlhttp://www.shnenglu.com/jjbird/comments/11597.htmlhttp://www.shnenglu.com/jjbird/articles/11597.html#Feedback0http://www.shnenglu.com/jjbird/comments/commentRss/11597.htmlhttp://www.shnenglu.com/jjbird/services/trackbacks/11597.html 1.程序中的括h否匹?/font>   把光标移动到需要检的括号Q如大括号{}、方括号[]、圆括号Q)和尖括号<>Q前面,键入快捷键“CtrlQ]”。如果括号匹配正,光标p到匹配的括号处,否则光标不移动,q且机箱喇叭q会发出一声警告声?/td> 2.查看一个宏Q或变量、函敎ͼ的宏定义   把光标移动到你想知道的一个宏上,比如说最常见的DECLARE_MAP_MESSAGE上按一下F12(或右键菜单中的Go To Defition Of ?,如果没有建立Browse filesQ会出现提示对话框,定Q然后就会蟩到定义那些东西的地方?/td> 3.格式化一Dؕ七八p的源代?/font>   选中那段源代码,按ATL+F8?/td> 4.在编辑状态下发现成员变量或函C能显C?/font>   删除该项目扩展名?ncb文gQ重新打开该项目?/td> 5.如何整理ClassView视图中大量的c?/font>   可以在classview 视图中右键新建文件夹Qnew folderQ,再把h相近性质的类拖到对应的文件夹中,使整个视囄上去清晰明了. 6.定位预处理指?/font> 在源文g中定位光标到对称?if, #endif,使用Ctrl+K. 7.如何dpȝ中Lib到当前项?/font>   在Project | Settings | Link | Object/library modulesQ输入Lib名称Q不同的Lib之间用空格格开. 8.如何dpȝ中的头文?.h)到当前项?   #include <FileName.h>,告诉~译到VCpȝ目录L;使用#include "FileName.h"Q告诉编译在当前目录? 9.如何在Studio使用汇编调试   在WorkBench的Debugger状态下按CTRL+F7. 10.怎样处理ClassZiard找不到的pȝ消息   如果要在ClassWizard中处理WM_NCHITTEST{系l消息,请在ClassWizard中Class Info中Message filter改ؓWindow有? 11.如何q净的删除一个类   先从Workspace中的FileView中删除对应的.h?cpp文g,再关闭项目,从实际的文g夹中删除对应?h?cpp文g?clw文g?/td> 12.如果让控制台应用E序支持mfccd   可以在控制台应用E序中include 来引入mfc库,但是控制台应用程序缺省是单线E的Qmfc是多U程的,册矛盾Q在project setting->c/c++ 选项Q选择code generation,在use run-time library 下拉框中选择debug multithread?/td> 13.如何汉化只有可执行代码的.exe 文g   在nt 下利用vc open file 以resources方式打开*.exe 文gQ直接修改资源文Ӟ然后保存卛_?/td> 附:VC目文g说明
.opt 工程关于开发环境的参数文g。如工具条位|等信息Q?/td>
.aps (AppStudio File),资源辅助文g,二进制格?一般不用去他.
.clw ClassWizard信息文g,实际上是INI文g的格?有兴可以研I一?有时候ClassWizard出问?手工修改CLW文g可以解决.如果此文件不存在的话,每次用ClassWizard的时候绘提示你是否重?
.dsp (DeveloperStudio Project):目文g,文本格式,不过不熟悉的话不要手工修?DSW(DeveloperStudio Workspace)是工作区文g,其他特点和DSP差不?
.plg 是编译信息文?~译时的error和warning信息文gQ实际上是一个html文gQ?一般用处不?在Tools->Options里面有个选项可以控制q个文g的生?
.hpj (Help Project)是生成帮助文件的工程,用microsfot  Help Compiler可以处理.
.mdp (Microsoft DevStudio Project)是旧版本的项目文?如果要打开此文件的?会提CZ是否转换成新的DSP格式.
.bsc 是用于浏览项目信息的,如果用Source Brower的话必Lq个文g.如果不用q个功能的话,可以在Project Options里面LGenerate Browse Info File,可以加快~译速度.
.map 是执行文件的映像信息U录文g,除非对系l底层非常熟?q个文g一般用不着.
.pch (Pre-Compiled File)是预~译文g,可以加快~译速度,但是文g非常?
.pdb (Program Database)记录了程序有关的一些数据和调试信息,在调试的时候可能有?
.exp 只有在编译DLL的时候才会生?记录了DLL文g中的一些信?一般也没什么用.
.ncb 无编译浏览文?no compile browser)。当自动完成功能出问题时可以删除此文件。build后会自动生成?/td>




奇奇 2006-08-23 09:02 发表评论
]]>
ZIP Multicast的传输和实现http://www.shnenglu.com/jjbird/articles/6334.html奇奇奇奇Wed, 26 Apr 2006 09:33:00 GMThttp://www.shnenglu.com/jjbird/articles/6334.htmlhttp://www.shnenglu.com/jjbird/comments/6334.htmlhttp://www.shnenglu.com/jjbird/articles/6334.html#Feedback1http://www.shnenglu.com/jjbird/comments/commentRss/6334.htmlhttp://www.shnenglu.com/jjbird/services/trackbacks/6334.html

ZIP Multicast的传输和实现

 

周承?汪志?唐昆 杜文


  摘要Q设计ƈ实现了一个基于IP Multicast技术的q程数字韌频监控系l,提出了分布式韌频接入共享的解决ҎQ能够有效地节省|络带宽Q针对视频、音频语韛_控制数据的不同传输特点,对其所采用的传输技术作了详l探讨,l出了具体实现方法?
  关键词:监控pȝ 分布式接入共?|络传输 IPl播 Windows套接?
  随着计算机网l技术、多媒体技术、计机视觉与模式识别技术的发燕服Q一U以数字化、智能化为特点的多媒体远E数字监控系l应q而生Q即ZIP的数字监控系l,实现了由传统的模拟监控到数字监控质的飞跃。与传统的模拟监控系l相比较Q数字远E监控系l几个最主要的优势是Q可以借助|络实现q程监控Q在q程不同地点的分控中心或同个分控中心可同时调看某一个或者几个监控现场的韌频数据,从而实现分布式的音频频接入和音视频数据׃nQ同Ӟ可以与监控现Zh员进行对Ԍ可以对远E监控现场的云台、摄像机{外围设备进行控制。视频、音频的实时、分布式传输及控制指令的可靠传输是远E数字监控系l的一个关键问题。本文设计ƈ实现了远E数字音频频监控pȝQ采用IP Multicast技术作为分布式韌频执着入和׃n的解x案,q对视频、音频语韛_控制数据不同的特点,对其所采用的不同传输技术进行了探讨Q给Z具体实现Ҏ?


  1 pȝ的Ml构


  q程监控pȝ一般包括三部分Q前端监控现场、通信讑֤和后端分控中心。整个系l基于Client/ServerQ客h/服务器)模式。Ml构如图1所C?



  Q?Q前端监控现场由监控现场L及一些外围设备组成。外围设备包括摄像机、电动镜头、云台、防护罩、监视器、多功能解码器及报警器。监控现Z行客户前端YӞ实现视频、音频数据的实时采集、压~、解压羃Q音频)Q视频传?单向的,音频传输是双向的Q及打包传送;对压~的视(韻I频数据进行经存储Q也可在分近中心q行Q。存储方式ؓ循环存储、定时存储、手动存储及q动视频启动存储。接收来自分控中心的控制指oQ也可在本地实施Q,对云台动作(上、下、左、右及自动)电动镜头的三可变Q光圈、焦距和聚焦Q?
  Q?Q通信讑֤是指所采用的传输信道和相关讑֤Q通信|络为LAN及WAN?
  Q?Q后端设备由若干分控中心计算机组成。各分控计算行服务器端YӞ接收来自前端压羃视(韻I频、显C(播放Q;通过|络对前端云台、摄像机q行控制Q采用组播技术,实现分布式视频执着入和分丰式视频共享:每个分控中心L可以同时监控多个前端Q即“一点对多点”;不同分控心也可以同时监控同一前端Q即“多点对一点”?

  2 |络传输模块的设计与实现


  2.1 pȝ传输数据cd的特点及通信协议的选择


  pȝ传输数据有:控制数据、音频、视频数据、后端分控中心通过|络向监控现Z机外围设备云台及摄像机发送控制信P实现云台动作Q上、下、左、右、自动)摄像机光圈、焦距及聚焦三可变,要求控制信号的传输准无误;音频、视频是q箋Q数据量大,允许传输中存在一定的数据错误率及数据丢失率,但实时性要求很高。此外,在监控系l中Q要实现韌频的分布式接入和数据׃nQ必进行音视频的多点传输。样实现上述目标Q首先是通信协议的选择QTCP/IP协议是广泛用的|协议,其网l模型定义了四层Q即|络接口层、网l层、传输层、应用层Q网l通信协议。传输层包含两个协议Q传输控制协议(TCPQ和用户数据报协议(UDPQ。IP是国际互联协议,位于|络层。TCP协议是面向连接的Q提供可靠的服务;UDP是无q接的,提供数据报服务;TCP采用提供认与超旉发、滑动窗口机制等措施来保证传输的可靠性,正是q些措施增加了网l的开销。如果用TCP传输视(韻I频数据,大量的数据容量引起重传。,使得|络负蝲大ƈ会加大gq;UDP协议是最单的传输协议Q不提供可靠性保证,正因为UDP协议不进行数据确认与重传国,大大提高了传输效率,h高效快速的特点QIpv4定义了三UIP数据包的传输Q单播、广播及l播。要pȝ中实现视Q音Q频数据的多点传输,若采用单播,则同L韟뀁视频数据要发送多ơ,q样D发送者负担重、gq长、网l拥塞;若用q播Q网l中的每个站炚w接收到数据Q不该l点否需要数据,增加了非接收者的开销Q组播是一U允怸个或多个发送者(l播源)发送单一的数据包到多个接收者(一ơ的、同时的Q的|络技术。组播源把数据包发送到特定l播l,而只有属于该l播l的地址才能接收到数据包。由于无论有多少个目的地址Q在整个|络的Q何一条链路上都只传送单一的数据包。因此组播提高了|络传输的效率,极大地节省了|络传输。组播方式只适用于UDP。综上所qͼ采用TCP/IP传输控制信号Q即信o通道Q采用UDP/IP传输韌频信Px据通道?
  IPl播依赖一个特D的地址l——“移播址”,即Dcd址。范围在224.0.0.0-239.255.255.255之间Q其?24.0.0.0-224.0.0.255是被保留的地址Q,Dcd址是动态分配和恢复的瞬态地址。组播地址只能作ؓ信宿地址使用Q而不能出现在M信源地址中。每一个组播组对应于动态分?的一个Dcd址。组播的特点Q组播组的成员是动态的Q主机可以Q何时间加入或dl播l,Ll中的成员在位置上和数量 旧没有限制的?


  2.2 Windows下,IPl播的Winsock2实现


  Windows环境下组播通信是基于WindowsSocket的。Windows Socket提供两种不同IPl播的实现方法:Windows Socket提供两种不同的IPl播的实现方法:Winsock1与Winsock2。在Windows2000q_实现VC++6.0开发工P在本pȝ中实CZWinsock2的组播通信~程?
  发送端Q前端、客LQ实现步骤:
  (1)加蝲Winsock2库,完成Winsock2的初始化Q?
  WSAStarup(MAKEWORD(2,2),&wsaData)Q?2)建立本地套接字(UDPQ:
m_socket=WSASocke(AF_INET,SOCK_DGRAM,IPPROTO_UDP,NULL,0,
WSA_FLAG_MULTIPOINT_C_LEAF|WSA_FLAG_MULTIPOINT_D_LEAF);
  //l播通信h两个层面的重要特征:控制层面和数据层面。控制层面决定一个多播组建立通信的方式,数据层面军_通信成员间数据传输的方式。每一个层面有两种形式Q一U是“有限的”,另一U是“无根的”;数据报IPl播在两个层面上都是“无根”的。Q一用户发送的数据都将被传送到l中所有其它成员。最后一个参数表明新创徏的套接字在控制层面与数据层面都是“无根的”?
可以通过setsocket函数讄套接字的属性,如地址重用Q缓冲区是接收还是发送?
  M_localAddr.sin_family = AF_INET;
  M_localAddr.sin_port=m_iPort;//本地端口?
  M_localAddr..sin _addr.S_un.S_addr=m_uLocalIP;//本地IP地址Q?


  Q?Q绑定(新创徏的套字节与本地插口地址q行l定Q:
  bind(m_socket,(PSOCKADDR)&(m_localAddr),sizeof(m_localAddr);


  (4)讄生存旉Q即数据包最多允许\由多个|段Q:
  WSAIoctl(m_socket,SIO_MULTICAST_SCOPE,//讄数据报生存时_
  &iMcastTTL,//生存旉大小Q?
  sizeof(iMcastTTL),NULL,0,&cbRet,NULL,NULL)Q?


  Q?Q配|Loopback,以决定组播数据是否回送:


  int bLoopback=FALSE;
  WSAIoct(m_socket,SIO_MULTIPOINT_LOOPBACK,//允许或禁止组播数据回送;
  &bLoopback,sizeof(bLoopback)QNULL,0,&cbRet,NULL,NULL);


  (6)收发数据Q?


  在发送方Q前端、客LQ响应发送的消息函数中调用下面函敎ͼ
  WSASendTo (m_socket,&stWSABuf,&cbRet,0,(struct sockaddr*)&stDestAddr,//发送的目的地址Q?
  sizeof(struct(sockaddr),NULL,NULL);
  在发送方Q前端、客LQ响应接收消息函C调用下面函数Q?
  WSARecvFrom(m_socket,&stWSABuf,1,& cbRet,&Flag,(struct sockaddr*)&stSrcAddr,//源地址Q?
  &iLenQNULLQNULLQ;


  Q?Q将l播套接字设|ؓ异步I/O工作模式Q在该套节字上接收事件ؓ基础的网l事仉知Q?


  WSAEventSelect(m_socketQm_hNetworkEventQ?/|络事g句柄Q将此套字节与该事g句柄q联在一P
  FD_WRITE|FD_READQ;//发生此两个事件之一Q则m_hNetworkEvent|ؓ有信L态;


  Q?Q在工作U程中设|:


  WSAWaitForMultipleEventQ?Q?/{待事g的个敎ͼQ?
  p->m_eventArray,//存放事g句柄的数l;
  FALSEQWSA_INFINITEQFALSEQ;


  Q?Q关闭组播套字节Q?


  closesocket(m_socket)Q?


  接收端(后端、服务器端)实现步骤Q?


  Q?Q?Q?Q与发送端Q客LQ相同;
  Q?Q调用WSAJLoinLeaf加入l播l:


  SOCKET NetSock=WSAJoinLeaf(sock,//必须为组播标志进行创建,否则调用p|Q?
  QPSOCKADDRQ?amp;Qm_stDestAddr,//l播导址Q与发送方的目的地址相同Q?
  sizeof(m_stDestAddr),UNLL,NULL,NULL,NULL,
  JL_BOTH));//允许接收和发送;


  Q?Q与客户端(6Q相同;Q?Q与客户端(7Q相同;Q?Q与客户端(8Q相同;Q?Q离开l播l;closesocket(NewSock)Q?/NewSock是调用WSAoinLeafQ)q回的套节字?


  2.3 在监控系l中|络传输模块的设?


  |络传输模块程如图2所C?/p>

 
  发送端Q前端监控现Z机、客LQ监控主行客LE序。在ȝE中Q启动视同、音频两个线E分别对视频及音频进行采集,攑օ视(韻I频缓冲区Q视频在本地回放Q同Ӟ监听分控中心的连接请求,收到q接hQTCP三次握手Q徏立TCPq接Q信令通道Q;通过信o通道Q向分控心发送二l组播地址及端口号Q对应视频及音频Q音频两个线E;分别在视Q音Q频U程中完成;利用Winsock2建立视(韻I频数据通道QUDPQ(源码前已q及Q;对视Q音Q频q行压羃~码、组播发送;音频U程接收分控中心的音频数据包Q解码ƈ播放Q实现视频的单向传输和音频的双向传输?
  接收端(后端分控中心、服务器端)分控中心Lq行服务器端E序Q在ȝE中向前端监控现Z机发接请求(CALLQ,三次握手建立TCPq接Q信令通道Q;后端接收到组播地址及端口号后,启动视(韻I频两个线E,完成Q利用Winsock2建立视(韻I频数据通道QUDPQ,加入视(韻I频组播组Q接收压~视Q音Q频包,q解码显C(播放Q;其中音频U程Q还要完成音频数据包解码昄Q播放)Q其中音频线E,q要完成音频数据包的压羃、发送;实现视频的单向传输、音频的双向传输?
  一个后端分控中心可同时监控12路前端视频及音频信号Q在设计服务器端监控E序Ӟ采用多线E技术,每徏立一对前端监控主Z后端分控中心Q服务器Q的TCPq接Q就开两个接收U程Q一个接收视频线E;一个接攉频线E)Q视频线E接收视频数据包q行解压~及回放Q音频线E接攉频数据包q行解压~及播放。对云台及摄像机的控制指令通过信o通道传输?
  本系l运行在Win2000q_上,用VC++6.0开发工具开发?
  在远E数字音视频监控pȝ的传输模块设计中Q根据音频频数据传输及控制信号传输的特点Q运用IPl播技术极大地减轻了网l负担,避免了资源的费Q节省了|络带宽Q利用TCP/IP协议设计了信令通道QTCPQ和数据通道QUDPQ;q用Windows多线E机制实C音频数据的实时、多点传输和控制信号的可靠传Q提高了E序q行的效率。在该系l的基础上进行改造和扩展Q可以应用到q程教学、远E医疗等多种多媒体通信Q因此,q程数字韌频监控系l的设计和实C仅具有监控方面的现实意义Q而且对于许多应用都有借鉴和参考h倹{?


奇奇 2006-04-26 17:33 发表评论
]]>
WSAEventSelectQ开发网l通信E序入门的l?-转自CSDNQ?/title><link>http://www.shnenglu.com/jjbird/articles/6333.html</link><dc:creator>奇奇</dc:creator><author>奇奇</author><pubDate>Wed, 26 Apr 2006 09:30:00 GMT</pubDate><guid>http://www.shnenglu.com/jjbird/articles/6333.html</guid><wfw:comment>http://www.shnenglu.com/jjbird/comments/6333.html</wfw:comment><comments>http://www.shnenglu.com/jjbird/articles/6333.html#Feedback</comments><slash:comments>3</slash:comments><wfw:commentRss>http://www.shnenglu.com/jjbird/comments/commentRss/6333.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/jjbird/services/trackbacks/6333.html</trackback:ping><description><![CDATA[ <table cellspacing="0" cellpadding="0" width="95%" border="0"> <tbody> <tr> <td align="middle" width="100%"> <h2> <b>WSAEventSelectQ开发网l通信E序入门的l?-转自CSDNQ?/b> </h2> </td> </tr> <tr> <td width="100%"> <p> </p> <p>   前面讨论的开发网l通信的经典入门采用的是WSAAsyncSelect的异步I/O模型Q本文将讨论WSAEventSelect异步I/O模型? </p> <p>       WSAEventSelect模型有点cMWSAAsyncSelect模型Q不同的是他不是用消息映的方式来响应网l事Ӟ而是用等待多重事件的方式来响应网l事件。下面是用WSAEventSelect模型和多U程机制做的一个简单的服务器程序的.cpp?h文gQ应用程序基于MFC的标准对话框。实现接受多个客L的连接请求,q记录下所有客L的相关信息,昄在列表框中?/p> <p>// serverDlg.cpp : implementation file<br />//</p> <p>#include "stdafx.h"<br />#include "server.h"<br />#include "serverDlg.h"</p> <p>#ifdef _DEBUG<br />#define new DEBUG_NEW<br />#undef THIS_FILE<br />static char THIS_FILE[] = __FILE__;<br />#endif</p> <p>SOCKET Accept; <a href="file://?"><font color="#336699">file://?/font></a>于新的一个连接通信的套接字<br />WSAEVENT NewEvent; <a href="file://?"><font color="#336699">file://?/font></a>应于新的套接字的C?br />SOCKET Socket[WSA_MAXIMUM_WAIT_EVENTS];  <a href="file://?"><font color="#336699">file://?/font></a>放所有生成的套接?br />WSAEVENT Event[WSA_MAXIMUM_WAIT_EVENTS]; <a href="file://?"><font color="#336699">file://?/font></a>放所有生成的事g对象<br />int EventTotal; <a href="file://?"><font color="#336699">file://?/font></a>建的事gL<br />int Index;      <a href="file://{?"><font color="#336699">file://{?/font></a>待多重事件函数的q回?br />WSANETWORKEVENTS NetworkEvents; <a href="file://?"><font color="#336699">file://?/font></a>于接收套接字上发生的|络事gcd以及可能出现的错<br />误代?/p> <p>/////////////////////////////////////////////////////////////////////////////<br />// CAboutDlg dialog used for App About</p> <p>class CAboutDlg : public CDialog<br />{<br />public:<br /> CAboutDlg();</p> <p>// Dialog Data<br /> <a href="file://{{/"><font color="#336699">file://{{</font></a>AFX_DATA(CAboutDlg)<br /> enum { IDD = IDD_ABOUTBOX };<br /> <a href="file://}}/"><font color="#336699">file://}}</font></a>AFX_DATA</p> <p> // ClassWizard generated virtual function overrides<br /> <a href="file://{{/"><font color="#336699">file://{{</font></a>AFX_VIRTUAL(CAboutDlg)<br /> protected:<br /> virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support<br /> <a href="file://}}/"><font color="#336699">file://}}</font></a>AFX_VIRTUAL</p> <p>// Implementation<br />protected:<br /> <a href="file://{{/"><font color="#336699">file://{{</font></a>AFX_MSG(CAboutDlg)<br /> <a href="file://}}/"><font color="#336699">file://}}</font></a>AFX_MSG<br /> DECLARE_MESSAGE_MAP()<br />};</p> <p>CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)<br />{<br /> <a href="file://{{/"><font color="#336699">file://{{</font></a>AFX_DATA_INIT(CAboutDlg)<br /> <a href="file://}}/"><font color="#336699">file://}}</font></a>AFX_DATA_INIT<br />}</p> <p>void CAboutDlg::DoDataExchange(CDataExchange* pDX)<br />{<br /> CDialog::DoDataExchange(pDX);<br /> <a href="file://{{/"><font color="#336699">file://{{</font></a>AFX_DATA_MAP(CAboutDlg)<br /> <a href="file://}}/"><font color="#336699">file://}}</font></a>AFX_DATA_MAP<br />}</p> <p>BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)<br /> <a href="file://{{/"><font color="#336699">file://{{</font></a>AFX_MSG_MAP(CAboutDlg)<br />  // No message handlers<br /> <a href="file://}}/"><font color="#336699">file://}}</font></a>AFX_MSG_MAP<br />END_MESSAGE_MAP()</p> <p>/////////////////////////////////////////////////////////////////////////////<br />// CServerDlg dialog</p> <p>CServerDlg::CServerDlg(CWnd* pParent /*=NULL*/)<br /> : CDialog(CServerDlg::IDD, pParent)<br />{<br /> <a href="file://{{/"><font color="#336699">file://{{</font></a>AFX_DATA_INIT(CServerDlg)<br />  // NOTE: the ClassWizard will add member initialization here<br /> <a href="file://}}/"><font color="#336699">file://}}</font></a>AFX_DATA_INIT<br /> // Note that LoadIcon does not require a subsequent DestroyIcon in Win32<br /> m_Connectnum = 0;<br /> m_NetworkID = 0;<br /> EventTotal = 0;<br />    for(int i = 0; i < MAX_CLIENT_NUM; i++)<br /> {<br />  ZeroMemory(&m_ClientInfo[i], sizeof(client_info));<br /> }</p> <p> m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);<br />}</p> <p>void CServerDlg::DoDataExchange(CDataExchange* pDX)<br />{<br /> CDialog::DoDataExchange(pDX);<br /> <a href="file://{{/"><font color="#336699">file://{{</font></a>AFX_DATA_MAP(CServerDlg)<br />  // NOTE: the ClassWizard will add DDX and DDV calls here<br /> <a href="file://}}/"><font color="#336699">file://}}</font></a>AFX_DATA_MAP<br />}</p> <p>BEGIN_MESSAGE_MAP(CServerDlg, CDialog)<br /> <a href="file://{{/"><font color="#336699">file://{{</font></a>AFX_MSG_MAP(CServerDlg)<br /> ON_WM_SYSCOMMAND()<br /> ON_WM_PAINT()<br /> ON_WM_QUERYDRAGICON()<br /> ON_WM_TIMER()<br /> <a href="file://}}/"><font color="#336699">file://}}</font></a>AFX_MSG_MAP<br />END_MESSAGE_MAP()</p> <p>/////////////////////////////////////////////////////////////////////////////<br />// CServerDlg message handlers</p> <p>BOOL CServerDlg::OnInitDialog()<br />{<br /> CDialog::OnInitDialog();</p> <p> // Add "About..." menu item to system menu.</p> <p> // IDM_ABOUTBOX must be in the system command range.<br /> ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);<br /> ASSERT(IDM_ABOUTBOX < 0xF000);</p> <p> CMenu* pSysMenu = GetSystemMenu(FALSE);<br /> if (pSysMenu != NULL)<br /> {<br />  CString strAboutMenu;<br />  strAboutMenu.LoadString(IDS_ABOUTBOX);<br />  if (!strAboutMenu.IsEmpty())<br />  {<br />   pSysMenu->AppendMenu(MF_SEPARATOR);<br />   pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);<br />  }<br /> }</p> <p> // Set the icon for this dialog.  The framework does this automatically<br /> //  when the application's main window is not a dialog<br /> SetIcon(m_hIcon, TRUE);   // Set big icon<br /> SetIcon(m_hIcon, FALSE);  // Set small icon<br /> <br /> // TODO: Add extra initialization here</p> <p> WSADATA wsaData;<br /> int ret;</p> <p> ret = WSAStartup(MAKEWORD(2,2), &wsaData);<br /> if(ret != 0)<br /> {<br />  MessageBox("初始化套接字p|!");<br />  return FALSE;<br /> }</p> <p> <a href="file://?"><font color="#336699">file://?/font></a>Z个套接字<br /> m_ListenSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);<br />        if(m_ListenSocket == INVALID_SOCKET)<br /> {<br />  MessageBox("创徏套接字失?");<br />  closesocket(m_ListenSocket);<br />  WSACleanup();<br />  return FALSE;<br /> }</p> <p> <a href="file://l?"><font color="#336699">file://l?/font></a>定到指定的端口上<br /> sockaddr_in localaddr;<br /> localaddr.sin_family = AF_INET;<br /> localaddr.sin_port = htons(1688);<br /> localaddr.sin_addr.s_addr = 0;</p> <p> if(bind(m_ListenSocket, (const struct sockaddr*)&localaddr, sizeof(sockaddr))<br />                                                                 == SOCKET_ERROR)<br /> {<br />  MessageBox("l定地址p|!");<br />  closesocket(m_ListenSocket);<br />  WSACleanup();<br />  return FALSE;<br /> }<br /> <br /> NewEvent = WSACreateEvent(); <a href="file://?"><font color="#336699">file://?/font></a>Z个新的事件对?/p> <p> <a href="file://?"><font color="#336699">file://?/font></a>创徏的事件对象与前面创徏的套接字兌在一?q注册网l事件类?br />        if(WSAEventSelect(m_ListenSocket, NewEvent, FD_ACCEPT | FD_CLOSE) == SOCKET_ERROR)<br /> {<br />  MessageBox("注册|络事gp|!");<br />  closesocket(m_ListenSocket);<br />  WSACleanup();<br />  return FALSE;<br /> }</p> <p> <a href="file://?"><font color="#336699">file://?/font></a>创徏的套接字处于监听状?br /> listen(m_ListenSocket, 5);</p> <p> Event[EventTotal] = NewEvent;<br /> Socket[EventTotal] = m_ListenSocket;<br /> EventTotal++;</p> <p>        <a href="file://?"><font color="#336699">file://?/font></a>|List控g的图象列?br /> HICON hIcon;</p> <p> m_imagelist.Create(16, 16, 0, 4, 4); // 32, 32 for large icons<br /> hIcon = AfxGetApp()->LoadIcon(IDI_CLIENT_INFO);<br /> <br /> m_imagelist.SetBkColor (RGB(248,232,224));<br /> m_imagelist.Add(hIcon);</p> <p> pList = (CListCtrl*)GetDlgItem(IDC_CLIENT_INFO);<br /> pList->SetImageList(&m_imagelist, LVSIL_SMALL);<br /> pList->SetBkColor(RGB(248,232,224));<br /> pList->SetTextBkColor(RGB(248,232,224));</p> <p> pList->InsertColumn(0,"   客户?,LVCFMT_CENTER,90, 0);<br /> pList->InsertColumn(1,"|络ID",LVCFMT_CENTER,50,1);<br /> pList->InsertColumn(2,"IP地址",LVCFMT_CENTER,100,2);<br /> pList->InsertColumn (3,"d旉",LVCFMT_CENTER,120,3);<br /> pList->InsertColumn (4,"在线旉",LVCFMT_CENTER,100,4);</p> <p> SetTimer(1, 1000, NULL);</p> <p> <a href="file://?"><font color="#336699">file://?/font></a>动核心处理线E?br /> AfxBeginThread(KernelWorkThread,this,THREAD_PRIORITY_NORMAL);</p> <p> return TRUE;  // return TRUE  unless you set the focus to a control<br />}</p> <p>void CServerDlg::OnSysCommand(UINT nID, LPARAM lParam)<br />{<br /> if ((nID & 0xFFF0) == IDM_ABOUTBOX)<br /> {<br />  CAboutDlg dlgAbout;<br />  dlgAbout.DoModal();<br /> }<br /> else<br /> {<br />  CDialog::OnSysCommand(nID, lParam);<br /> }<br />}</p> <p>// If you add a minimize button to your dialog, you will need the code below<br />//  to draw the icon.  For MFC applications using the document/view model,<br />//  this is automatically done for you by the framework.</p> <p>void CServerDlg::OnPaint() <br />{<br /> if (IsIconic())<br /> {<br />  CPaintDC dc(this); // device context for painting</p> <p>  SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);</p> <p>  // Center icon in client rectangle<br />  int cxIcon = GetSystemMetrics(SM_CXICON);<br />  int cyIcon = GetSystemMetrics(SM_CYICON);<br />  CRect rect;<br />  GetClientRect(&rect);<br />  int x = (rect.Width() - cxIcon + 1) / 2;<br />  int y = (rect.Height() - cyIcon + 1) / 2;</p> <p>  // Draw the icon<br />  dc.DrawIcon(x, y, m_hIcon);<br /> }<br /> else<br /> {<br />  CDialog::OnPaint();<br /> }<br />}</p> <p>// The system calls this to obtain the cursor to display while the user drags<br />//  the minimized window.<br />HCURSOR CServerDlg::OnQueryDragIcon()<br />{<br /> return (HCURSOR) m_hIcon;<br />}</p> <p> <a href="file://?"> <font color="#336699">file://?/font> </a>心处理线E? 响应q处理各U网l事?br />UINT KernelWorkThread(LPVOID pParam)<br />{<br /> int len = sizeof(sockaddr);</p> <p> CServerDlg* dlg;<br /> dlg = (CServerDlg*)pParam;</p> <p> while(1)<br /> {<br />         Index = WSAWaitForMultipleEvents(EventTotal, Event, FALSE, WSA_INFINITE, FALSE);</p> <p>  WSAEnumNetworkEvents(Socket[Index - WSA_WAIT_EVENT_0], <br />                     Event[Index - WSA_WAIT_EVENT_0],<br />                                     &NetworkEvents);<br /> <br />  if(NetworkEvents.lNetworkEvents & FD_ACCEPT)<br />  <a href="file://q?"><font color="#336699">file://q?/font></a>接事?br />  {<br />   if(NetworkEvents.iErrorCode[FD_ACCEPT_BIT] != 0)<br />   {<br />    dlg->MessageBox("接受q接事gp|!");<br />    break;<br />   }</p> <p>   Accept = accept(Socket[Index - WSA_WAIT_EVENT_0], <br />                                 (struct sockaddr*)&(dlg->clientaddr), &len);<br />   if(Accept == INVALID_SOCKET)<br />   {<br />    dlg->MessageBox("接受q接p|!");<br />    break;<br />   }<br />   <br />   if(EventTotal > WSA_MAXIMUM_WAIT_EVENTS)<br />   {<br />    dlg->MessageBox("q接个数溢出,拒绝接受!");<br />    break;<br />   }</p> <p>   NewEvent = WSACreateEvent();</p> <p>   if(WSAEventSelect(Accept, NewEvent, FD_READ | FD_WRITE | FD_CLOSE)<br />                                                                   == SOCKET_ERROR)<br />   {<br />    dlg->MessageBox("注册|络事gp|!");<br />    closesocket(Accept);<br />    break;<br />   }</p> <p>   Event[EventTotal] = NewEvent;<br />   Socket[EventTotal] = Accept;<br />   EventTotal ++;<br />  }</p> <p>  if(NetworkEvents.lNetworkEvents & FD_READ)<br />  <a href="file://?"><font color="#336699">file://?/font></a>取数据事?br />  {<br />   if(NetworkEvents.iErrorCode[FD_READ_BIT] != 0)<br />   {<br />    dlg->MessageBox("M件失?");<br />    break;<br />   }</p> <p>   if(dlg->OnReceive(Socket[Index - WSA_WAIT_EVENT_0]) == FALSE)<br />   {<br />    dlg->MessageBox("d数据p|!");<br />    break;<br />   }<br />  }</p> <p>  if(NetworkEvents.lNetworkEvents & FD_CLOSE)<br />  <a href="file://?"><font color="#336699">file://?/font></a>闭套接字事g<br />  {<br />   if(NetworkEvents.iErrorCode[FD_CLOSE_BIT] != 0)<br />   {<br />    dlg->MessageBox("关闭事gp|!");<br />    break;<br />   }</p> <p>   if(dlg->OnClose(Socket[Index - WSA_WAIT_EVENT_0]) == FALSE)<br />   {<br />    dlg->MessageBox("关闭套接字失?");<br />    break;<br />   }<br />  }<br /> }</p> <p> return 0;<br />}</p> <p>BOOL CServerDlg::OnClose(SOCKET pSocket)<br />{<br /> int i, exitnum;<br /> <br /> for(i = 0; i < m_Connectnum; i++)<br /> {<br />  if(m_ClientInfo[i].Client_Socket == pSocket)<br />  {<br />   exitnum = i;<br />  }<br /> }<br /> for(i = exitnum; i < m_Connectnum; i++)<br /> {<br />  memcpy(&m_ClientInfo[i], &m_ClientInfo[i+1], sizeof(client_info));<br /> }</p> <p> m_Connectnum --;</p> <p> <a href="file://?"><font color="#336699">file://?/font></a>所有客L发送在U客户信息的报文<br /> cmd_client_info ClientInfo;<br /> ClientInfo.cmd_type = CMD_CLIENT_INFO;<br /> ClientInfo.client_num = m_Connectnum;<br /> <br /> for(i=0; i<=m_Connectnum; i++)<br /> {<br />  ClientInfo.Networks_ID[i] = m_ClientInfo[i].Network_ID;<br />  strcpy(ClientInfo.users_name[i], m_ClientInfo[i].User_Name);<br />  strcpy(ClientInfo.clients_ipaddr[i], inet_ntoa(m_ClientInfo[i].Client_Addr.sin_addr));<br /> }<br /> for(i=0; i<=m_Connectnum; i++)<br /> {<br />  send(m_ClientInfo[i].Client_Socket, (char*)&ClientInfo, sizeof(cmd_client_info), NULL);<br /> }<br /> closesocket(pSocket);</p> <p>        pList->DeleteItem(exitnum);<br /> <br /> return TRUE;<br />}</p> <p>BOOL CServerDlg::OnReceive(SOCKET pSocket)<br />{<br />    static char rcvbuf[65535];   <a href="file://?"><font color="#336699">file://?/font></a>收缓冲区<br />    int ret;<br /> int offset=0;<br /> find_type* pFindType;<br /> int i = 0;<br /> CTime m_current_time=CTime::GetCurrentTime ();<br /> CString strTime = m_current_time.Format("%c");<br /> CString networkid; <a href="file://?"><font color="#336699">file://?/font></a>表框的网lID?/p> <p>    ret = recv(pSocket, rcvbuf, 65535, 0);<br /> if(ret == OPERATION_ERROR)<br />  return FALSE;</p> <p> while(offset < ret)<br /> {<br />  pFindType = (find_type*)(rcvbuf+offset);<br />  switch(pFindType->cmd_type)<br />  {<br />  case CMD_HELLO:  <br />   cmd_hello Hello;<br />   memcpy(&Hello, rcvbuf+offset, sizeof(cmd_hello));<br />   offset+=sizeof(cmd_hello);</p> <p>   cmd_hello_resp HelloResp;<br />   m_NetworkID ++;<br />   HelloResp.cmd_type = CMD_HELLO_RESP;<br />   HelloResp.Network_ID = m_NetworkID;<br />   strcpy(HelloResp.user_name, Hello.user_name);</p> <p>   memcpy((struct sockaddr*)&(m_ClientInfo[m_Connectnum].Client_Addr),<br />    (const struct sockaddr*)&clientaddr, sizeof(sockaddr));<br />   m_ClientInfo[m_Connectnum].Client_Socket = Accept;<br />   strcpy(m_ClientInfo[m_Connectnum].User_Name, HelloResp.user_name);<br />   m_ClientInfo[m_Connectnum].Network_ID = m_NetworkID;<br />   m_ClientInfo[m_Connectnum].Login_Time = m_current_time;<br />   send(pSocket, (char*)&HelloResp, sizeof(cmd_hello_resp), NULL);</p> <p>   <a href="file://?"><font color="#336699">file://?/font></a>d的客L发送回应报?br />   Sleep(200);</p> <p>   cmd_client_info ClientInfo;<br />   ClientInfo.cmd_type = CMD_CLIENT_INFO;<br />   ClientInfo.client_num = m_Connectnum +1;</p> <p>   for(i=0; i<=m_Connectnum; i++)<br />   {<br />    ClientInfo.Networks_ID[i] = m_ClientInfo[i].Network_ID;<br />    strcpy(ClientInfo.users_name[i], m_ClientInfo[i].User_Name);<br />                                strcpy(ClientInfo.clients_ipaddr[i], <br />                                       inet_ntoa(m_ClientInfo[i].Client_Addr.sin_addr));<br />   }</p> <p>   <a href="file://?"><font color="#336699">file://?/font></a>所有在U客L发送在U客户信息报?br />   for(i=0; i<=m_Connectnum; i++)<br />   {<br />    send(m_ClientInfo[i].Client_Socket, (char*)&ClientInfo,<br />                                     sizeof(cmd_client_info), NULL);<br />   }</p> <p>   <a href="file://?"><font color="#336699">file://?/font></a>新客L信息列表<br />   networkid.Format("%d", m_NetworkID);</p> <p>   LVITEM lvinsert;<br />   lvinsert.mask=LVIF_TEXT|LVIF_IMAGE|LVIF_PARAM;<br />   lvinsert.iItem=m_Connectnum;<br />   lvinsert.iSubItem=0;<br />   lvinsert.cchTextMax=20;<br />   lvinsert.pszText=HelloResp.user_name;<br />   lvinsert.iImage = 0;<br />   pList->InsertItem (&lvinsert);<br />   pList->SetItemText (m_Connectnum,1,networkid);<br />   pList->SetItemText(m_Connectnum,2,<br />                               inet_ntoa(m_ClientInfo[m_Connectnum].Client_Addr.sin_addr));<br />   pList->SetItemText (m_Connectnum,3,strTime);</p> <p>   m_Connectnum ++;</p> <p>   break;<br />  case CMD_ASK:<br />   cmd_ask Ask;<br />   cmd_ask_resp AskResp;<br />   memcpy(&Ask,rcvbuf+offset,sizeof(cmd_ask));<br />   offset+=sizeof(cmd_ask);<br />   AskResp.cmd_type = CMD_ASK_RESP;<br />   AskResp.Network_ID = Ask.Network_ID;<br />   for(i=0; i<m_Connectnum; i++)<br />   {<br />    if(m_ClientInfo[i].Network_ID == Ask.Network_ID)<br />    {<br />     strcpy(AskResp.pData1,m_ClientInfo[i].User_Name);<br />     strcat(AskResp.pData1, ":");<br />    }<br />   }<br />   strcpy(AskResp.pData2, Ask.pData);<br />   for(i=0; i<m_Connectnum; i++)<br />   {<br />    send(m_ClientInfo[i].Client_Socket, (char*)&AskResp, sizeof(AskResp), 0);<br />   }</p> <p>   break;<br />  case CMD_GOODBYE:<br />   closesocket(pSocket);<br />   break;<br />  default:<br />   break;<br />  }<br /> }</p> <p> return TRUE;<br />}<br />BOOL CServerDlg::OnSend(SOCKET pSocket)<br />{<br /> return TRUE;<br />}</p> <p>void CServerDlg::OnOK() <br />{<br /> closesocket(m_ListenSocket);<br /> WSACleanup();<br /> CDialog::OnOK();<br />}</p> <p>void CServerDlg::OnTimer(UINT nIDEvent) <br />{<br /> CTime m_current_time = CTime::GetCurrentTime();<br /> CTimeSpan logintimes;<br /> CString login_times;<br /> CString networkid; <a href="file://?"><font color="#336699">file://?/font></a>表框的网lID?br /> <br /> for(int i=0; i<m_Connectnum; i++)<br /> {<br />  logintimes = m_current_time - m_ClientInfo[i].Login_Time;<br />  login_times.Format("%d时%d?dU?, logintimes.GetHours(),<br />                                    logintimes.GetMinutes(),<br />            logintimes.GetSeconds());<br /> <br />  pList->SetItemText (i,4,login_times);<br /> }</p> <p> CDialog::OnTimer(nIDEvent);<br />}</p> <p> <br />// serverDlg.h : header file<br />//</p> <p>#if !defined(AFX_SERVERDLG_H__B0AA0367_C1F4_11D4_AB1C_0080C8D6FEA5__INCLUDED_)<br />#define AFX_SERVERDLG_H__B0AA0367_C1F4_11D4_AB1C_0080C8D6FEA5__INCLUDED_</p> <p>#if _MSC_VER > 1000<br />#pragma once<br />#endif // _MSC_VER > 1000</p> <p>#include "global.h"</p> <p>/////////////////////////////////////////////////////////////////////////////<br />// CServerDlg dialog</p> <p>class CServerDlg : public CDialog<br />{<br /><a href="file://?"><font color="#336699">file://?/font></a>局函数<br />    friend UINT KernelWorkThread(LPVOID pParam);<br />// Construction<br />public:<br /> CListCtrl* pList; <a href="file://?"><font color="#336699">file://?/font></a>L在线信息列表框对?br /> CImageList m_imagelist; </p> <p> SOCKET m_ListenSocket; <a href="file://?"><font color="#336699">file://?/font></a>于监听端口的套接?br /> client_info m_ClientInfo[MAX_CLIENT_NUM]; <a href="file://?"><font color="#336699">file://?/font></a>存在U客L信息的结构体数组<br /> sockaddr_in clientaddr; <a href="file://?"><font color="#336699">file://?/font></a>存发赯接的客户端地址<br /> int m_Connectnum; <a href="file://?"><font color="#336699">file://?/font></a>U客L个数<br /> int m_NetworkID;  <a href="file://q?"><font color="#336699">file://q?/font></a>回给客户端的|络ID?/p> <p> BOOL OnSend(SOCKET pSocket);    <a href="file://?"><font color="#336699">file://?/font></a>送数据网l事件的响应函数 <br /> BOOL OnReceive(SOCKET pSocket); <a href="file://?"><font color="#336699">file://?/font></a>收数据网l事件的响应函数 <br /> BOOL OnClose(SOCKET pSocket);   <a href="file://?"><font color="#336699">file://?/font></a>闭套接字|络事g的响应函?/p> <p> CServerDlg(CWnd* pParent = NULL); // standard constructor</p> <p>// Dialog Data<br /> <a href="file://{{/"><font color="#336699">file://{{</font></a>AFX_DATA(CServerDlg)<br /> enum { IDD = IDD_SERVER_DIALOG };<br />  // NOTE: the ClassWizard will add data members here<br /> <a href="file://}}/"><font color="#336699">file://}}</font></a>AFX_DATA</p> <p> // ClassWizard generated virtual function overrides<br /> <a href="file://{{/"><font color="#336699">file://{{</font></a>AFX_VIRTUAL(CServerDlg)<br /> protected:<br /> virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support<br /> <a href="file://}}/"><font color="#336699">file://}}</font></a>AFX_VIRTUAL</p> <p>// Implementation<br />protected:<br /> HICON m_hIcon;</p> <p> // Generated message map functions<br /> <a href="file://{{/"><font color="#336699">file://{{</font></a>AFX_MSG(CServerDlg)<br /> virtual BOOL OnInitDialog();<br /> afx_msg void OnSysCommand(UINT nID, LPARAM lParam);<br /> afx_msg void OnPaint();<br /> afx_msg HCURSOR OnQueryDragIcon();<br /> virtual void OnOK();<br /> afx_msg void OnTimer(UINT nIDEvent);<br /> <a href="file://}}/"><font color="#336699">file://}}</font></a>AFX_MSG<br /> DECLARE_MESSAGE_MAP()<br />};</p> </td> </tr> </tbody> </table> <img src ="http://www.shnenglu.com/jjbird/aggbug/6333.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/jjbird/" target="_blank">奇奇</a> 2006-04-26 17:30 <a href="http://www.shnenglu.com/jjbird/articles/6333.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>setsockopt()选项改善E序的健壮?/title><link>http://www.shnenglu.com/jjbird/articles/6221.html</link><dc:creator>奇奇</dc:creator><author>奇奇</author><pubDate>Tue, 25 Apr 2006 01:14:00 GMT</pubDate><guid>http://www.shnenglu.com/jjbird/articles/6221.html</guid><wfw:comment>http://www.shnenglu.com/jjbird/comments/6221.html</wfw:comment><comments>http://www.shnenglu.com/jjbird/articles/6221.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.shnenglu.com/jjbird/comments/commentRss/6221.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/jjbird/services/trackbacks/6221.html</trackback:ping><description><![CDATA[写出我在|络~程中的一点心得体会,希望对他(^_^也对大家)有帮?<br />1. 如果在已l处?ESTABLISHED状态下的socket(一般由端口号和标志W区分)调用<br />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 />Note:1.在设|了逗留延时Q用于一个非d的socket是作用不大的Q最好不?<br />2.如果惌E序不经历SO_LINGER需要设|SO_DONTLINGERQ或者设|l_onoff=0Q?br />10.q一个用的比较少的是在SDI或者是Dialog的程序中Q可以记录socket的调试信息:<br />(前不久做q这个函数的试Q调式信息可以保存,包括socket建立时候的参数,采用?br />具体协议Q以及出错的代码都可以记录下来)<br />BOOL bDebug=TRUE;<br />setsockopt(s,SOL_SOCKET,SO_DEBUG,(const char*)&bDebug,sizeof(BOOL));<br />11.附加Q往往通过setsockopt()讄了缓冲区大小Q但q不能满x据的传输需求,<br />我的习惯是自己写个处理网l缓冲的c,动态分配内?下面我将q个cd出,希望?br />初学者有所帮助Q?br /><br />//仿照String 改写而成<br />//==============================================================================<br />// 二进制数据,主要用于收发|络~冲区的数据<br />// CNetIOBuffer ?MFC c?CString 的源代码作ؓ蓝本改写而成Q用法与 CString cMQ?br />// 但是 CNetIOBuffer 中存攄是纯_的二进制数据,'\0' q不作ؓ它的l束标志?br />// 其数据长度可以通过 GetLength() 获得Q缓冲区地址可以通过q算W?LPBYTE 获得?br /><br /><br />//==============================================================================<br />// Copyright (c) All-Vision Corporation. All rights reserved.<br />// Module: NetObject<br />// File: SimpleIOBuffer.h<br />// Author: gdy119<br />// Email : <a href="mailto:8751webmaster@126.com"><font color="#22229c">8751webmaster@126.com</font></a><br />// Date: 2004.11.26<br />//==============================================================================<br />// NetIOBuffer.h<br />#ifndef _NETIOBUFFER_H<br />#define _NETIOBUFFER_H<br />//=============================================================================<br />#define MAX_BUFFER_LENGTH 1024*1024<br />//=============================================================================<br />//主要用来处理|络~冲的数?br />class CNetIOBuffer <br />{<br />protected:<br />LPBYTE m_pbinData;<br />int m_nLength;<br />int m_nTotalLength;<br />CRITICAL_SECTIONm_cs;<br />void Initvalibers();<br />public:<br />CNetIOBuffer();<br />CNetIOBuffer(const LPBYTE lbbyte, int nLength);<br />CNetIOBuffer(const CNetIOBuffer&binarySrc);<br />virtual ~CNetIOBuffer();<br />//=============================================================================<br />BOOL CopyData(const LPBYTE lbbyte, int nLength);<br />BOOL ConcatData(const LPBYTE lbbyte, int nLength);<br />void ResetIoBuffer();<br />int GetLength() const;<br />BOOL SetLength(int nLen);<br />LPBYTE GetCurPos();<br />int GetRemainLen();<br />BOOL IsEmpty() const;<br />operator LPBYTE() const;<br />static GetMaxLength() { return MAX_BUFFER_LENGTH; }<br />const CNetIOBuffer& operator=(const CNetIOBuffer& buffSrc);<br />};<br />#endif // <br />// NetOBuffer.cpp: implementation of the CNetIOBuffer class.<br />//======================================================================<br />#include "stdafx.h"<br />#include "NetIOBuffer.h"<br />//======================================================================<br />//=======================================================================<br />// Construction/Destruction<br />CNetIOBuffer::CNetIOBuffer()<br />{<br />Initvalibers();<br /><br />}<br />CNetIOBuffer::CNetIOBuffer(const LPBYTE lbbyte, int nLength)<br />{<br />Initvalibers();<br />CopyData(lbbyte, nLength);<br />}<br />CNetIOBuffer::~CNetIOBuffer()<br />{<br />delete []m_pbinData;<br />m_pbinData=NULL;<br />DeleteCriticalSection(&m_cs);<br /><br />}<br />CNetIOBuffer::CNetIOBuffer(const CNetIOBuffer&binarySrc)<br />{<br /><br />Initvalibers();<br />CopyData(binarySrc,binarySrc.GetLength());<br /><br />}<br />void CNetIOBuffer::Initvalibers()<br />{<br /><br />m_pbinData = NULL;<br />m_nLength = 0;<br />m_nTotalLength = MAX_BUFFER_LENGTH;<br />if(m_pbinData==NULL)<br />{<br />m_pbinData=new BYTE[m_nTotalLength];<br />ASSERT(m_pbinData!=NULL);<br />}<br />InitializeCriticalSection(&m_cs);<br />}<br />void CNetIOBuffer::ResetIoBuffer()<br />{<br />EnterCriticalSection(&m_cs);<br />m_nLength = 0;<br />memset(m_pbinData,0,m_nTotalLength);<br />LeaveCriticalSection(&m_cs);<br />}<br /><br />BOOL CNetIOBuffer::CopyData(const LPBYTE lbbyte, int nLength)<br />{<br />if( nLength > MAX_BUFFER_LENGTH )<br />return FALSE;<br /><br />ResetIoBuffer();<br />EnterCriticalSection(&m_cs);<br />memcpy(m_pbinData, lbbyte, nLength );<br />m_nLength = nLength;<br />LeaveCriticalSection(&m_cs);<br /><br />return TRUE;<br />}<br /><br />BOOL CNetIOBuffer::ConcatData(const LPBYTE lbbyte, int nLength)<br />{<br />if( m_nLength + nLength > MAX_BUFFER_LENGTH )<br />return FALSE;<br /><br />EnterCriticalSection(&m_cs);<br />memcpy(m_pbinData+m_nLength, lbbyte, nLength );<br />m_nLength += nLength;<br />LeaveCriticalSection(&m_cs);<br /><br />return TRUE;<br />}<br /><br />int CNetIOBuffer::GetLength() const<br />{<br />return m_nLength;<br />}<br /><br />BOOL CNetIOBuffer::SetLength(int nLen)<br />{<br />if( nLen > MAX_BUFFER_LENGTH )<br />return FALSE;<br /><br />EnterCriticalSection(&m_cs);<br />m_nLength = nLen;<br />LeaveCriticalSection(&m_cs);<br /><br />return TRUE;<br />}<br /><br />LPBYTE CNetIOBuffer::GetCurPos()<br />{<br /><br />if( m_nLength < MAX_BUFFER_LENGTH )<br /><br />return (m_pbinData+m_nLength);<br /><br />else<br />return NULL;<br />}<br /><br />CNetIOBuffer:: operator LPBYTE() const<br />{<br />return m_pbinData;<br />}<br /><br />int CNetIOBuffer::GetRemainLen()<br />{<br /><br />return MAX_BUFFER_LENGTH - m_nLength;<br /><br />}<br />BOOL CNetIOBuffer::IsEmpty() const<br />{<br />return m_nLength == 0;<br />}<br /><br />const CNetIOBuffer& CNetIOBuffer:: operator=(const CNetIOBuffer& buffSrc)<br />{<br />if(&buffSrc!=this)<br />{<br />CopyData(buffSrc, buffSrc.GetLength());<br /><br />}<br />return *this;<br /><br />}<br /><br /><br /><br />12.发送数据时候一般是pȝ~冲区满以后才发送,现在讄为只要系l?br />~冲区有数据qd送: <br />BOOL bNodelay=TRUE;<br />SetSockOpt(s,IPPROTO_TCP,TCP_NODELAY,(const char*)&bNodelayt,sizeof(BOOL));<br /><br />附加Q?br />setoptsockQ)q个函数 讄成端口复用的时候,很容易对一些没有进行单独bind模式的程序造成危害?br />比如old?ping icmp doorQ简单的sniffer后,收到包,然后讄setoptsock bind web服务Q然后徏立个cmdq程 bind?0端口?<img src ="http://www.shnenglu.com/jjbird/aggbug/6221.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/jjbird/" target="_blank">奇奇</a> 2006-04-25 09:14 <a href="http://www.shnenglu.com/jjbird/articles/6221.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>回调机制http://www.shnenglu.com/jjbird/articles/3364.html奇奇奇奇Tue, 21 Feb 2006 02:26:00 GMThttp://www.shnenglu.com/jjbird/articles/3364.htmlhttp://www.shnenglu.com/jjbird/comments/3364.htmlhttp://www.shnenglu.com/jjbird/articles/3364.html#Feedback0http://www.shnenglu.com/jjbird/comments/commentRss/3364.htmlhttp://www.shnenglu.com/jjbird/services/trackbacks/3364.html软g模块之间L存在着一定的接口Q从调用方式上,可以把他们分Zc:同步调用、回调和异步调用。同步调用是一U阻塞式调用Q调用方要等待对Ҏ行完毕才q回Q它是一U单向调用;回调是一U双向调用模式,也就是说Q被调用方在接口被调用时也会调用Ҏ的接口;异步调用是一U类似消息或事g的机Ӟ不过它的调用方向刚好相反Q接口的服务在收到某U讯息或发生某种事gӞ会主动通知客户方(卌用客h的接口)。回调和异步调用的关p非常紧密,通常我们使用回调来实现异步消息的注册Q通过异步调用来实现消息的通知。同步调用是三者当中最单的Q而回调又常常是异步调用的基础Q因此,下面我们着重讨论回调机制在不同软g架构中的实现?/BLOCKQUOTE>

1 什么是回调
软g模块之间L存在着一定的接口Q从调用方式上,可以把他们分Zc:同步调用、回调和异步调用。同步调用是一U阻塞式调用Q调用方要等待对Ҏ行完毕才q回Q它是一U单向调用;回调是一U双向调用模式,也就是说Q被调用方在接口被调用时也会调用Ҏ的接口;异步调用是一U类似消息或事g的机Ӟ不过它的调用方向刚好相反Q接口的服务在收到某U讯息或发生某种事gӞ会主动通知客户方(卌用客h的接口)。回调和异步调用的关p非常紧密,通常我们使用回调来实现异步消息的注册Q通过异步调用来实现消息的通知。同步调用是三者当中最单的Q而回调又常常是异步调用的基础Q因此,下面我们着重讨论回调机制在不同软g架构中的实现?


对于不同cd的语aQ如l构化语a和对象语aQ、^収ͼWin32、JDKQ或构架QCORBA、DCOM、WebServiceQ,客户和服务的交互除了同步方式以外Q都需要具备一定的异步通知机制Q让服务方(或接口提供方Q在某些情况下能够主动通知客户Q而回调是实现异步的一个最L途径?

对于一般的l构化语aQ可以通过回调函数来实现回调。回调函C是一个函数或q程Q不q它是一个由调用方自己实玎ͼ供被调用方用的Ҏ函数?

在面向对象的语言中,回调则是通过接口或抽象类来实现的Q我们把实现q种接口的类成ؓ回调c,回调cȝ对象成ؓ回调对象。对于象C++或Object Pascalq些兼容了过E特性的对象语言Q不仅提供了回调对象、回调方法等Ҏ,也能兼容q程语言的回调函数机制?

Windowsq_的消息机制也可以看作是回调的一U应用,我们通过pȝ提供的接口注册消息处理函敎ͼ卛_调函敎ͼQ从而实现接收、处理消息的目的。由于Windowsq_的API是用C语言来构建的Q我们可以认为它也是回调函数的一个特例?

对于分布式组件代理体pCORBAQ异步处理有多种方式Q如回调、事件服务、通知服务{。事件服务和通知服务是CORBA用来处理异步消息的标准服务,他们主要负责消息的处理、派发、维护等工作。对一些简单的异步处理q程Q我们可以通过回调机制来实现?

下面我们集中比较h代表性的语言QC、Object PascalQ和架构QCORBAQ来分析回调的实现方式、具体作用等?

2 q程语言中的回调QCQ?/SPAN>

2.1 函数指针
回调在C语言中是通过函数指针来实现的,通过回调函数的地址传给被调函数从而实现回调。因此,要实现回调,必须首先定义函数指针Q请看下面的例子Q?


void Func(char *s)Q?/ 函数原型
void (*pFunc) (char *);//函数指针

可以看出Q函数的定义和函数指针的定义非常cM?

一般的化,Z化函数指针类型的变量定义Q提高程序的可读性,我们需要把函数指针cd自定义一下?


typedef void(*pcb)(char *);

回调函数可以象普通函C栯E序调用Q但是只有它被当作参C递给被调函数时才能称作回调函数?

被调函数的例子:


void GetCallBack(pcb callback)
{
/*do something*/
}
用户在调用上面的函数Ӟ需要自己实C个pcbcd的回调函敎ͼ
void fCallback(char *s) 
{
/* do something */
} 
然后Q就可以直接把fCallback当作一个变量传递给GetCallBack,
GetCallBackQfCallbackQ?

如果赋了不同的值给该参敎ͼ那么调用者将调用不同地址的函数。赋值可以发生在q行Ӟq样使你能实现动态绑定?

2.2 参数传递规?/SPAN>
到目前ؓ止,我们只讨Z函数指针及回调而没有去注意ANSI C/C++的编译器规范。许多编译器有几U调用规范。如在Visual C++中,可以在函数类型前加_cdeclQ_stdcall或者_pascal来表C其调用规范Q默认ؓ_cdeclQ。C++ Builder也支持_fastcall调用规范。调用规范媄响编译器产生的给定函数名Q参C递的序Q从叛_左或从左到右Q,堆栈清理责QQ调用者或者被调用者)以及参数传递机Ӟ堆栈QCPU寄存器等Q?

调用规范看成是函数cd的一部分是很重要的;不能用不兼容的调用规范将地址赋值给函数指针。例如:


// 被调用函数是以int为参敎ͼ以int回?
__stdcall int callee(int); 

// 调用函数以函数指针ؓ参数
void caller( __cdecl int(*ptr)(int)); 

// 在p中企囑֭储被调用函数地址的非法操?
__cdecl int(*p)(int) = callee; // 出错

指针p和callee()的类型不兼容Q因为它们有不同的调用规范。因此不能将被调用者的地址赋值给指针pQ尽两者有相同的返回值和参数?

2.3 应用举例
C语言的标准库函数中很多地方就采用了回调函数来让用户定制处理过E。如常用的快速排序函数、二分搜索函数等?

快速排序函数原型:


void qsort(void *base, size_t nelem, size_t width, int (_USERENTRY *fcmp)(const void *, const void *));
二分搜烦函数原型Q?
void *bsearch(const void *key, const void *base, size_t nelem,
				 size_t width, int (_USERENTRY *fcmp)(const void *, const void *));

其中fcmp是一个回调函数的变量?

下面l出一个具体的例子Q?


#include <stdio.h>
#include <stdlib.h>

int sort_function( const void *a, const void *b);
int list[5] = { 54, 21, 11, 67, 22 };

int main(void)
{
   int  x;

   qsort((void *)list, 5, sizeof(list[0]), sort_function);
   for (x = 0; x < 5; x++)
      printf("%i\n", list[x]);
   return 0;
}

int sort_function( const void *a, const void *b)
{
   return *(int*)a-*(int*)b;
}

2.4 面向对象语言中的回调QDelphiQ?

Dephi与C++一PZ保持与过E语aPascal的兼Ҏ,它在引入面向对象机制的同Ӟ保留了以前的l构化特性。因此,对回调的实现Q也有两U截然不同的模式Q一U是l构化的函数回调模式Q一U是面向对象的接口模式?

2.4.1 回调函数

回调函数cd定义Q?


type
   TCalcFunc=function (a:integer;b:integer):integer;

按照回调函数的格式自定义函数的实玎ͼ?/P>

function Add(a:integer;b:integer):integer
begin
  result:=a+b;
end;
function Sub(a:integer;b:integer):integer
begin
  result:=a-b;
end;

回调的?/P>

function Calc(calc:TcalcFunc;a:integer;b:integer):integer

下面Q我们就可以在我们的E序里按照需要调用这两个函数?/P>

c:=calc(add,a,b);//c=a+b
c:=calc(sub,a,b);//c=a-b

2.4.2 回调对象

什么叫回调对象呢,它具体用在哪些场合?首先Q让我们把它与回调函数对比一下,回调函数是一个定义了函数的原型,函数体则交由W三Ҏ实现的一U动态应用模式。要实现一个回调函敎ͼ我们必须明确知道几点Q该函数需要那些参敎ͼq回什么类型的倹{同P一个回调对象也是一个定义了对象接口Q但是没有具体实现的抽象c(x口)。要实现一个回调对象,我们必须知道Q它需要实现哪些方法,每个Ҏ中有哪些参数Q该Ҏ需要放回什么倹{?

因此Q在回调对象q种应用模式中,我们会用到接口。接口可以理解成一个定义好了但是没有实现的c,它只能通过l承的方式被别的cd现。Delphi中的接口和COM接口cMQ所有的接口都承与IInterfaceQ等同于IUnknowQ,q且要实C个基本的ҎQueryInterface, _AddRef, 和_Release?

  • 定义一个接?
    
    type IShape=interface(IInterface)
    	procedure Draw;
    end
    
  • 实现回调c?
    
    type TRect=class(TObject,IShape)
    	protected
          function QueryInterface(const IID: TGUID; out Obj): HResult; stdcall;
          function _AddRef: Integer; stdcall;
    function _Release: Integer; stdcall;
        public
    	  procedure Draw;
    end;
    
    type TRound=class(TObject,IShape)
    	protected
          function QueryInterface(const IID: TGUID; out Obj): HResult; stdcall;
          function _AddRef: Integer; stdcall;
    function _Release: Integer; stdcall;
        public
    	  procedure Draw;
    end;
    
  • 使用回调对象
    
    procedure MyDraw(shape:IShape);
    var 
    shape:IShape;
    begin
    shape.Draw; 
    end;
    

如果传入的对象ؓTRectQ那么画矩ŞQ如果ؓTRoundQ那么就为圆形。用户也可以按照自己的意图来实现IShape接口Q画q囑ŞQ?


MyDraw(Trect.Create);
MyDraw(Tround.Create);

2.4.3 回调Ҏ

回调Ҏ(Callback Method)可以看作是回调对象的一部分QDelphi对windows消息的封装就采用了回调方法这个概c在有些场合Q我们不需要按照给定的要求实现整个对象Q而只要实现其中的一个方法就可以了,q是我们׃用到回调Ҏ?

回调Ҏ的定义如下:


TNotifyEvent = procedure(Sender: TObject) of object; 
TMyEvent=procedure(Sender:Tobject;EventId:Integer) of object;

TNotifyEvent 是Delphi中最常用的回调方法,H体、控件的很多事gQ如单击事g、关闭事件等都是采用了TnotifyEvent。回调方法的变量一般通过事g属性的方式来定义,如TCustomForm的创Z件的定义Q?


property OnCreate: TNotifyEvent read FOnCreate write FOnCreate stored IsForm;

我们通过l事件属性变量赋值就可以定制事g处理器?/P>

用户定义对象Q包含回调方法的对象Q:


type TCallback=Class
    procedure ClickFunc(sender:TObject);
end;
procedure Tcallback.ClickFunc(sender:TObject);
begin
  showmessage('the caller is clicked!');
end;

H体对象Q?/P>

type TCustomFrm=class(TForm)
  public
	procedure RegisterClickFunc(cb:procedure(sender:Tobject) of object);
end;

procedure TcustomFrm..RegisterClickFunc(cb:TNotifyEvent);
begin
  self.OnClick=cb;
end;

使用ҎQ?/P>

var
  frm:TcustomFrm;
begin
  frm:=TcustomFrm.Create(Application);
  frm.RegisterClickFunc(Tcallback.Create().ClickFunc);
end;

3 回调在分布式计算中的应用QCORBAQ?/SPAN>

3.1 回调接口模型
CORBA的消息传递机制有很多U,比如回调接口、事件服务和通知服务{。回调接口的原理很简单,CORBA客户和服务器都具有双重角Ԍ卛_当服务器也是客户客户?

回调接口的反向调用与正向调用往往是同时进行的Q如果服务端多次调用该回调接口,那么q个回调接口变成异步接口了。因此,回调接口在CORBA中常常充当事件注册的用途,客户端调用该注册函数Ӟ客户函数是回调函数Q在此后的调用中Q由于不需要客L的主动参与,该函数就是实C一U异步机制?

从CORBA规范我们知道Q一个CORBA接口在服务端和客L有不同的表现形式Q在客户端一般用桩QStubQ文Ӟ服务端则用到框架QSkeletonQ文Ӟ接口的规格采用IDL来定义。而回调函数的引入Q得服务端和客L都需要实C定的桩和框架。下面是回调接口的实现模型:

3.1.1 范例

下面l出了一个用回调的接口文gQ服务端需要实现Server接口的框Ӟ客户端需要实现CallBack的框Ӟ


module cb
{
	interface CallBack;
	interface Server;

interface CallBack 
{
    	void OnEvent(in long Source,in long msg);
};
  	interface Server 
{
    	long RegisterCB(in CallBack cb);
		void UnRegisterCB(in long hCb);
};
};

客户端首先通过同步方式调用服务端的接口RegistCBQ用来注册回调接口CallBack。服务端收到该请求以后,׃保留该接口引用,如果发生某种事g需要向客户端通知的时候就通过该引用调用客h的OnEvent函数Q以便对方及时处理?nbsp; 



奇奇 2006-02-21 10:26 发表评论
]]>
GRID中的事ghttp://www.shnenglu.com/jjbird/articles/3271.html奇奇奇奇Wed, 15 Feb 2006 09:21:00 GMThttp://www.shnenglu.com/jjbird/articles/3271.htmlhttp://www.shnenglu.com/jjbird/comments/3271.htmlhttp://www.shnenglu.com/jjbird/articles/3271.html#Feedback0http://www.shnenglu.com/jjbird/comments/commentRss/3271.htmlhttp://www.shnenglu.com/jjbird/services/trackbacks/3271.html//{{AFX_EVENTSINK_MAP(CDlgUserManager)
 ON_EVENT(CDlgUserManager, IDC_USER_MANAGER_GRID, -600 /* Click */, OnClickUserManagerGrid, VTS_NONE)
 ON_EVENT(CDlgUserManager, IDC_USER_MANAGER_GRID, -601 /* DblClick */, OnDblClickUserManagerGrid, VTS_NONE)
 ON_EVENT(CDlgUserManager, IDC_USER_MANAGER_GRID, -602 /* KeyDown */, OnKeyDownUserManagerGrid, VTS_PI2 VTS_I2)
 ON_EVENT(CDlgUserManager, IDC_USER_MANAGER_GRID, 74 /* Compare */, OnCompareUserManagerGrid, VTS_I4 VTS_I4 VTS_PI2)
 ON_EVENT(CDlgUserManager, IDC_USER_MANAGER_GRID, -603 /* KeyPress */, OnKeyPressUserManagerGrid, VTS_PI2)
 ON_EVENT(CDlgUserManager, IDC_USER_MANAGER_GRID, -605 /* MouseDown */, OnMouseDownUserManagerGrid, VTS_I2 VTS_I2 VTS_I4 VTS_I4)
}}//AFX_EVENTSINK_MAP
END_EVENTSINK_MAP()

奇奇 2006-02-15 17:21 发表评论
]]>
mysql的一些语法和C APIhttp://www.shnenglu.com/jjbird/articles/2993.html奇奇奇奇Mon, 23 Jan 2006 09:36:00 GMThttp://www.shnenglu.com/jjbird/articles/2993.htmlhttp://www.shnenglu.com/jjbird/comments/2993.htmlhttp://www.shnenglu.com/jjbird/articles/2993.html#Feedback0http://www.shnenglu.com/jjbird/comments/commentRss/2993.htmlhttp://www.shnenglu.com/jjbird/services/trackbacks/2993.htmlselect ID,name,zi,hao into outfile "zuozhe.txt" fields optionally enclosed by '""' terminated by ','

from gushizuozhe

load data infile "zuozhe.txt" into table gushizuozhe fields optionally enclosed by '\"' terminated by

',' (ID,name,zi,hao);

grant select on *.* to "public@192.168.%" identified by 'public';

revoke select on *.* from "public@192.168.%"
revoke q不能删除用Pdelete from mysql.user where user like "public%"

flush flush_option[,flush_option]

kill thread_id   unix/linux下进?BR>show processlist
select user()

set password for www@localhost=password("www")

set option_setting

写锁、读?BR>lock tables gushi write,gushizuozhe write;
unlock tables


MYSQL~程接口
MYSQL C API
1、数据类?BR>1)my_ulonglong
2)my_bool
3)MYSQL_FIELD_OFFSET
4)MYSQL
5)MYSQL_RES
6)MYSQL_ROW
7)MYSQL_FIELD
{
char *name;
char *table;
char *def;
enum enum_field_types type;//列的数据cd
unsigned int length;//列定义的长度
unsigned int max_length;//数据实际的最大长?BR>unsigned int flags;//列的属?BR>}
8)unsigned int decimals//数位数

2、函?BR>1)my_bool mysql_change_user(MYSQL *mysql,const char *user,const char *password,const char *db)
2)void mysql_close(MYSQL *mysql)
3)MYSQL *mysql_init(MYSQL *mysql)
4)int mysql_option(MYSQL *mysql,enum mysql_option,const char *arg)指定更精的q接参数选项
5)int mysql_ping(MYSQL *mysql)//查连接是否正?BR>6)MYSQL *mysql_real_connect(MYSQL *mysql,const char *host,const char *user,const char *password,const

char *db,unsiged int port,const char *unix_socket,unsigned int client_flag)
7)int mysql_select_db(MYSQL *mysql,const char *db)//选择数据库db为当前数据库
8)int mysql_query(MYSQL *mysql,const char *query)
9)int mysql_real_query(MYSQL *mysql,const char *query,unsigned int length)
10)char *mysql_info(MYSQL *mysql)//q回最后执行的一ơ操作的有关信息?BR>11)MYSQL_RES *mysql_store_result(MYSQL *mysql)//d一个查询的全部l果?BR>12)MYSQL_RES *mysql_use_result(MYSQL *mysql)//初始化一个结果集Q但是不把结果读到客LQ仍然保留在服务?/P>

?BR>13)void mysql_free_result(MYSQL_RES *result)//释放l果集用的内存?BR>14)my_ulonglong mysql_affected_rows(MYSQL *mysql)//q回最后一个update,delete,insert操作影响的记录数?BR>15)my_ulonglong mysql_num_rows(MYSQL *mysql)//mysql_store_result()q回的结果集中的记录数?BR>16)MYSQL_ROW_OFFSET mysql_row_seek(MYSQL_RES *result,MYSQL_ROW_OFFSET offset)
17)MYSQL_ROW_OFFSET mysql_row_tell(MYSQL_RES *result)//当前光标位置
18)MYSQL_ROW_OFFSET mysql_data_seek(MYSQL_RES *result,unsigned long long offset)
19)MYSQL_ROW mysql_fetch_row(MYSQL_RES *result)//l果集中的下一条记?BR>20)unsigned int mysql_fetch_lengths(MYSQL_RES *result)//l果集中当前记录的长?BR>21)unsigned int mysql_num_fields(MYSQL_RES *result)//l果集中列的数目
22)MYSQL_FIELD_OFFSET mysql_field_seek(MYSQL_RES *result,MYSQL_FIELD_OFFSET offset)
23)MYSQL_FIELD_OFFSET mysql_field_tell(MYSQL_RES *result)//当前光标位置
24)MYSQL_FIELD *mysql_fetch_field(MYSQL_RES *result)//l果集中当前列信?BR>25)MYSQL_FIELD *mysql_fetch_fields(MYSQL_RES *result)//l果集中所有列信息
26)MYSQL_RES *mysql_list_dbs(MYSQL *mysql,const char *wild)//与wild正则表达式匹配的数据库信?BR>27)MYSQL_RES *mysql_list_tables(MYSQL *mysql,const char *wild)//与wild正则表达式匹配的表信?BR>28)MYSQL_RES *mysql_list_fields(MYSQL *mysql,const char * table,const char *wild)//与当前表Q匹配wild?/P>

则表辑ּ的所有列名的l果?BR>29)MYSQL_RES *mysql_list_processes(MYSQL *mysql)
30)char *mysql_stat(MYSQL *mysql)//当前服务器的信息
31)char *mysql_get_server_info(MYSQL *mysql)
32)char *mysql_get_client_info(MYSQL *mysql)
33)char *mysql_get_host_info(MYSQL *mysql)
34)char *mysql_get_proto_info(MYSQL *mysql)
35)unsiged long mysql_thread_id(MYSQL *mysql)
36)int mysql_kill(MYSQL *mysql,unsiged long pid)
37)int mysql_shutdown(MYSQL *mysql)
38)void mysql_debug(char *debug)
39)int mysql_dump_debug_info(char *debug)
40)unsigned int mysql_errno(MYSQL *mysql)
41)char *mysql_error(MYSQL *mysql)



奇奇 2006-01-23 17:36 发表评论
]]>
攉的一些技?/title><link>http://www.shnenglu.com/jjbird/articles/2936.html</link><dc:creator>奇奇</dc:creator><author>奇奇</author><pubDate>Fri, 20 Jan 2006 09:01:00 GMT</pubDate><guid>http://www.shnenglu.com/jjbird/articles/2936.html</guid><wfw:comment>http://www.shnenglu.com/jjbird/comments/2936.html</wfw:comment><comments>http://www.shnenglu.com/jjbird/articles/2936.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.shnenglu.com/jjbird/comments/commentRss/2936.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/jjbird/services/trackbacks/2936.html</trackback:ping><description><![CDATA[<P>ReverseFind用法<BR>// Example for CString::ReverseFind<BR>CString s( "abcabc" );<BR>ASSERT( s.ReverseFind( 'b' ) == 4 );</P> <P>得到工具栏尺?BR>CSize sizeBar;<BR>CToolBar m_wndToolBar;<BR>m_wndToolBar.GetToolBarCtrl().GetMaxSize(&sizeBar);</P> <P>在工h上添加编辑框 <BR>CRect rect;<BR>m_wndToolBar.SetButtonInfo(9,ID_SEPARATOR,TBBS_SEPARATOR,100);<BR>m_wndToolBar.GetItemRect(9,&rect);</P> <P>m_wndComboBox.Create(CBS_DROPDOWN|WS_VISIBLE|WS_VSCROLL|CBS_AUTOHSCROLL,rect, &m_wndToolBar,105);</P> <P>格式化一D|代码<BR>Alt+F8</P> <P>定位预处?ifQ?endif<BR>Ctrl+K</P> <P>层H口的实?BR>在PreCreateWindow()中加?BR>cs.dwExStyle=WS_EX_TOPMOST</P><img src ="http://www.shnenglu.com/jjbird/aggbug/2936.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/jjbird/" target="_blank">奇奇</a> 2006-01-20 17:01 <a href="http://www.shnenglu.com/jjbird/articles/2936.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss> <footer> <div class="friendship-link"> <p>лǵվܻԴȤ</p> <a href="http://www.shnenglu.com/" title="精品视频久久久久">精品视频久久久久</a> <div class="friend-links"> </div> </div> </footer> <a href="http://www.anfubbs.cn" target="_blank">þ</a>| <a href="http://www.dyph.net.cn" target="_blank">AVþþƷ </a>| <a href="http://www.xkart.cn" target="_blank">ĻþӰԺ</a>| <a href="http://www.jhgppeizi.com.cn" target="_blank">鶹wwwþùƷ</a>| <a href="http://www.iido.org.cn" target="_blank">ɫۺϺϾþۿ</a>| <a href="http://www.myloveshop.com.cn" target="_blank">޹Ʒ۲ӰԺþ </a>| <a href="http://www.fddyc.cn" target="_blank">þ޹vwww</a>| <a href="http://www.shjinhuashiye.cn" target="_blank">Ʒþۺ</a>| <a href="http://www.5ihubei.cn" target="_blank">Ʒŷһþþ</a>| <a href="http://www.nn75.cn" target="_blank">ձ޿һþ</a>| <a href="http://www.flznzb.cn" target="_blank">ľþþþר</a>| <a href="http://www.elishe.cn" target="_blank">þù</a>| <a href="http://www.gay4u.cn" target="_blank">AVɫۺϾþAVɫۺ</a>| <a href="http://www.fzcxpc.cn" target="_blank">þþþ18</a>| <a href="http://www.juruse.com.cn" target="_blank">һþþƷ</a>| <a href="http://www.motorbook.com.cn" target="_blank">þþþƷþþþɫӰ</a>| <a href="http://www.bjxisaa.cn" target="_blank">þۺϸϾþù</a>| <a href="http://www.yhlj.net.cn" target="_blank">þݺҹҹ2020츾 </a>| <a href="http://www.qysf88.cn" target="_blank">޾ƷþþþĻ</a>| <a href="http://www.gotovision.com.cn" target="_blank">þҹɫƷ鶹</a>| <a href="http://www.sai-shang.cn" target="_blank">ɫۺϾþĻۺ</a>| <a href="http://www.hhlou.com.cn" target="_blank">þ99Ʒ99þ</a>| <a href="http://www.ghzu.cn" target="_blank">þþþav</a>| <a href="http://www.zuk4.cn" target="_blank">պʮ˽һþ </a>| <a href="http://www.aqbfrmi.cn" target="_blank">ھƷþþþþҰ</a>| <a href="http://www.lkmheatlock.com.cn" target="_blank">һaɫƬþ</a>| <a href="http://www.cnpump.com.cn" target="_blank">ƷѾþ</a>| <a href="http://www.zhangjiaying.cn" target="_blank">72ŷþþþôƽ</a>| <a href="http://www.566wan.cn" target="_blank">þAAAƬ69</a>| <a href="http://www.xxysw.com.cn" target="_blank">պŷһþþþ</a>| <a href="http://www.ysaoyx.cn" target="_blank">ȾþֻоƷ</a>| <a href="http://www.7-go.cn" target="_blank">þþþþþۺ</a>| <a href="http://www.hnzzwl.cn" target="_blank">þþƷŷպƷ</a>| <a href="http://www.010tk.cn" target="_blank">ɫۺϾþĻ</a>| <a href="http://www.voos.org.cn" target="_blank">2021ھƷþþþþӰԺ</a>| <a href="http://www.ikdianying.cn" target="_blank">Ʒŷһþþ</a>| <a href="http://www.y7816.cn" target="_blank">99þùۺϾƷӰԺ</a>| <a href="http://www.cate365.cn" target="_blank">˾þü91</a>| <a href="http://www.panxl.cn" target="_blank">þþƷ99͵</a>| <a href="http://www.hwxldw.cn" target="_blank">þþƷһ</a>| <a href="http://www.bwgwdl.cn" target="_blank">칫ҾþþƷ</a>| <script> (function(){ var bp = document.createElement('script'); var curProtocol = window.location.protocol.split(':')[0]; if (curProtocol === 'https') { bp.src = 'https://zz.bdstatic.com/linksubmit/push.js'; } else { bp.src = 'http://push.zhanzhang.baidu.com/push.js'; } var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(bp, s); })(); </script> </body>