自定义博客皮肤VIP专享

*博客头图:

格式为PNG、JPG,宽度*高度大于1920*100像素,不超过2MB,主视觉建议放在右侧,请参照线上博客头图

请上传大于1920*100像素的图片!

博客底图:

图片格式为PNG、JPG,不超过1MB,可上下左右平铺至整个背景

栏目图:

图片格式为PNG、JPG,图片宽度*高度为300*38像素,不超过0.5MB

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

-+
  • 博客(0)
  • 资源 (39)
  • 收藏
  • 关注

空空如也

一款硬件检测网络找驱动软件

通过硬件检测寻找驱动并下载安装,绿色无安装版,给那些重装系统无驱动用户解决后顾之忧..绝对顶好软件

2009-05-12

内核和用户空间通信—netlink源码

一、imp2源码 整个源码包含三个文件:imp2_k.c, imp2_u.c和imp2.h. 其中imp2_k.c为内核模块的源代码,imp2_u.c为应用程序,即测试代码,imp2.h为两个源文件都需要引用的头文件。其整体的功能是:注册一种新的netlink协议,并注册一个新的NF hook函数。当有ping包发往当前主机或者经过当前主机转发时,内核向用户发送ping包的源IP和目的IP。各个文件的简单分析见下文。 1. imp2.h 该文件主要是定义了一种新的Netlink协议类型NL_IMP2(31)。新的协议类型的选值不能和当前内核中已经定义的netlink协议类型重复。定义了基于该协议类型的消息类型,内核根据接收到消息的不同类型,进行不同的处理:IMP2_U_PID和IMP2_CLOSE分别为请求和关闭。IMP2_K_MSG代表内核空间发送的消息。 该头文件的源码如下: 2. imp2_k.c 该程序为内核模块程序。其完成的功能如下: (1)创建一种新的Netlink协议NL_IMP2,并注册该协议的回调函数kernel_receive。但用户空间通过建立且协议类型为NL_IMP2的socket套接字并调用sendto,sendmsg函数发送数据时,传送到内核空间的数据由kernel_receive进行处理。该函数主要是记录用户进程的ID,用于随后发送数据的时候指定目的。 (2)在Netfilter的hook点NF_IP_PRE_ROUTING注册hook函数get_icmp,对经过该hook点的ping包进行处理。get_icmp首先判断是否是ping包,如果不是,直接Accept。如果是,则记录该包的源IP和目的IP,然后调用send_to_user,将记录的信息发送给kernel_recieve函数中记录的用户进程ID。 该文件的源码如下: 3. imp2_u.c 该程序为用户空间的测试程序。该程序包括以下功能: (1)生成NL_IMP2协议的socket.然后通过调用sendto发送IMP2_U_PID类型的请求信息给内核。然后等待接受内核发回的信息。记住:仅当有ping包经过内核的NF时,内核才会向用户进程发送信息。 (2)当用户进程通过Ctrl+C来结束该程序时,调用信号处理函数sig_int,向内核发送IMP2_CLOSE的消息,结束socket。 该文件的源码如下: 二、编译和测试 1. 整个源文件编译的Makefile如下: all: gcc -O2 -DMODULE -D__KERNEL__ -W -Wstrict-prototypes -Wmissing-prototypes -isystem /lib/modules/`uname -r`/build/include -c -o imp2_k.o imp2_k.c gcc imp2_u.c -o imp2_u install: insmod imp2_k.o uninstall: rmmod imp2_k clean: rm -f imp2_k.o imp2_u 2. 加载内核模块,并执行测试程序。 #make install #./imp2_u 当没有ping包时,终端一直处于等待输出状态。通过另一台主机(192.168.1.100)向当前主机(192.168.1.101)发送ping包,则终端已经有输出: #./imp2_u [root@localhost imp2]# ./imp2_u src: 192.168.1.100, dest: 192.168.1.101 src: 192.168.1.100, dest: 192.168.1.101 src: 192.168.1.100, dest: 192.168.1.101 src: 192.168.1.100, dest: 192.168.1.101

2009-05-12

著名游戏异教徒源代码

// P_doors.c #include "DoomDef.h" #include "P_local.h" #include "soundst.h" //================================================================== //================================================================== // // VERTICAL DOORS // //================================================================== //================================================================== //================================================================== // // T_VerticalDoor // //================================================================== void T_VerticalDoor(vldoor_t *door) { result_e res; switch(door->direction) { case 0: // WAITING if(!--door->topcountdown) switch(door->type) { case normal: door->direction = -1; // time to go back down S_StartSound((mobj_t *) &door->sector->soundorg, sfx_doropn); break; case close30ThenOpen: door->direction = 1; S_StartSound((mobj_t *) &door->sector->soundorg, sfx_doropn); break; default: break; } break; case 2: // INITIAL WAIT if(!--door->topcountdown) { switch(door->type) { case raiseIn5Mins: door->direction = 1; door->type = normal; S_StartSound((mobj_t *) &door->sector->soundorg, sfx_doropn); break; default: break; } } break; case -1: // DOWN res = T_MovePlane(door->sector, door->speed, door->sector->floorheight, false, 1, door->direction); if(res == pastdest) { switch(door->type) { case normal: case close: door->sector->specialdata = NULL; P_RemoveThinker(&door->thinker); // unlink and free S_StartSound((mobj_t *) &door->sector->soundorg, sfx_dorcls); break; case close30ThenOpen: door->direction = 0; door->topcountdown = 35*30; break; default: break; } } else if(res == crushed) { switch(door->type) { case close: // DON'T GO BACK UP! break; default: door->direction = 1; S_StartSound((mobj_t *) &door->sector->soundorg,sfx_doropn); break; } } break; case 1: // UP res = T_MovePlane(door->sector, door->speed, door->topheight, false, 1, door->direction); if(res == pastdest) { switch(door->type) { case normal: door->direction = 0; // wait at top door->topcountdown = door->topwait; break; case close30ThenOpen: case open: door->sector->specialdata = NULL; P_RemoveThinker (&door->thinker); // unlink and free S_StopSound((mobj_t *)&door->sector->soundorg); break; default: break; } } break; } } //---------------------------------------------------------------------------- // // EV_DoDoor // // Move a door up/down // //---------------------------------------------------------------------------- int EV_DoDoor(line_t *line, vldoor_e type, fixed_t speed) { int secnum; int retcode; sector_t *sec; vldoor_t *door; secnum = -1; retcode = 0; while((secnum = P_FindSectorFromLineTag(line, secnum)) >= 0) { sec = §ors[secnum]; if(sec->specialdata) { continue; } // Add new door thinker retcode = 1; door = Z_Malloc(sizeof(*door), PU_LEVSPEC, 0); P_AddThinker(&door->thinker); sec->specialdata = door; door->thinker.function = T_VerticalDoor; door->sector = sec; switch(type) { case close: door->topheight = P_FindLowestCeilingSurrounding(sec); door->topheight -= 4*FRACUNIT; door->direction = -1; S_StartSound((mobj_t *)&door->sector->soundorg, sfx_doropn); break; case close30ThenOpen: door->topheight = sec->ceilingheight; door->direction = -1; S_StartSound((mobj_t *)&door->sector->soundorg, sfx_doropn); break; case normal: case open: door->direction = 1; door->topheight = P_FindLowestCeilingSurrounding(sec); door->topheight -= 4*FRACUNIT; if(door->topheight != sec->ceilingheight) { S_StartSound((mobj_t *)&door->sector->soundorg, sfx_doropn); } break; default: break; } door->type = type; door->speed = speed; door->topwait = VDOORWAIT; } return(retcode); } //================================================================== // // EV_VerticalDoor : open a door manually, no tag value // //================================================================== void EV_VerticalDoor(line_t *line, mobj_t *thing) { player_t *player; int secnum; sector_t *sec; vldoor_t *door; int side; side = 0; // only front sides can be used // // Check for locks // player = thing->player; switch(line->special) { case 26: // Blue Lock case 32: if(!player) { return; } if(!player->keys[key_blue]) { P_SetMessage(player, TXT_NEEDBLUEKEY, false); S_StartSound(NULL, sfx_plroof); return; } break; case 27: // Yellow Lock case 34: if(!player) { return; } if(!player->keys[key_yellow]) { P_SetMessage(player, TXT_NEEDYELLOWKEY, false); S_StartSound(NULL, sfx_plroof); return; } break; case 28: // Green Lock case 33: if(!player) { return; } if(!player->keys[key_green]) { P_SetMessage(player, TXT_NEEDGREENKEY, false); S_StartSound(NULL, sfx_plroof); return; } break; } // if the sector has an active thinker, use it sec = sides[line->sidenum[side^1]].sector; secnum = sec-sectors; if(sec->specialdata) { door = sec->specialdata; switch(line->special) { case 1: // ONLY FOR "RAISE" DOORS, NOT "OPEN"s case 26: case 27: case 28: if(door->direction == -1) { door->direction = 1; // go back up } else { if(!thing->player) { // Monsters don't close doors return; } door->direction = -1; // start going down immediately } return; } } // for proper sound switch(line->special) { case 1: // NORMAL DOOR SOUND case 31: S_StartSound((mobj_t *)&sec->soundorg, sfx_doropn); //S_StartSound((mobj_t *)&sec->soundorg, sfx_dormov); break; default: // LOCKED DOOR SOUND S_StartSound((mobj_t *)&sec->soundorg, sfx_doropn); //S_StartSound((mobj_t *)&sec->soundorg, sfx_dormov); break; } // // new door thinker // door = Z_Malloc (sizeof(*door), PU_LEVSPEC, 0); P_AddThinker(&door->thinker); sec->specialdata = door; door->thinker.function = T_VerticalDoor; door->sector = sec; door->direction = 1; switch(line->special) { case 1: case 26: case 27: case 28: door->type = normal; break; case 31: case 32: case 33: case 34: door->type = open; line->special = 0; break; } door->speed = VDOORSPEED; door->topwait = VDOORWAIT; // // find the top and bottom of the movement range // door->topheight = P_FindLowestCeilingSurrounding(sec); door->topheight -= 4*FRACUNIT; } //================================================================== // // Spawn a door that closes after 30 seconds // //================================================================== void P_SpawnDoorCloseIn30(sector_t *sec) { vldoor_t *door; door = Z_Malloc(sizeof(*door), PU_LEVSPEC, 0); P_AddThinker(&door->thinker); sec->specialdata = door; sec->special = 0; door->thinker.function = T_VerticalDoor; door->sector = sec; door->direction = 0; door->type = normal; door->speed = VDOORSPEED; door->topcountdown = 30*35; } //================================================================== // // Spawn a door that opens after 5 minutes // //================================================================== void P_SpawnDoorRaiseIn5Mins(sector_t *sec, int secnum) { vldoor_t *door; door = Z_Malloc(sizeof(*door), PU_LEVSPEC, 0); P_AddThinker(&door->thinker); sec->specialdata = door; sec->special = 0; door->thinker.function = T_VerticalDoor; door->sector = sec; door->direction = 2; door->type = raiseIn5Mins; door->speed = VDOORSPEED; door->topheight = P_FindLowestCeilingSurrounding(sec); door->topheight -= 4*FRACUNIT; door->topwait = VDOORWAIT; door->topcountdown = 5*60*35; }

2009-05-12

手机编程的好书-手机编程

这个是一本手机相关编程的牛书,看完这个编手机病毒就没问题拉..哈哈

2009-05-08

手机编程宝典----系统编程

有关手机的系统编程和系统架构,是一本不可多的的好书

2009-05-08

智能手机操作系统编程

本书旨在把目前市场上最流行的也是持有最大市场分额的智能手机操作系统Symbian介绍给更广泛的人群。本忆较全面地覆盖了Symbian操作系统及编程等内容,主要包括开发环境、内存与资源管理、应用程序设计、控件、多媒体、网络与通信、消息等,并附有大量的编程实例。 本书的读者是高等院校相关专业的师生和软件开发人员。本书可以作为智能手机操作系统课程的主要教材或参考书。

2009-05-08

PHP编程起步--编程

学习php...新手和有定基础的好帮手,php的网络编程,与mysql结合编程

2009-05-07

asp.net经典范例50讲

<%@Register TagPrefix="snowy" NameSpace="snowy" Assembly="MyLabel" %> <html> <head> <title>My Label Test Page</title> <script language="C#" runat = "server" > public void OnClick(object sender, EventArgs e) { Label1.Text = "You clicked MyLabel control"; } </script> </head> <body> <form id="Form1" runat="server"> <snowy:MyLabel id="MyLabel1" runat="server" OnClick="OnClick" runat="server" Text="MyLabel" /> <br> <asp:Label id="Label1" runat="server" /> <asp:Button id="Button1" runat="server" Text="Submit" /> </form> </body> </html>

2009-05-07

动态链接库DLL编程资料

动态链接库(DLLs)是从C语言函数库和Pascal库单元的概念发展而来的。所有的C语言标准库函数都存放在某一函数库中,同时用户也可以用LIB程序创建自己的函数库。在链接应用程序的过程中,链接器从库文件中拷贝程序调用的函数代码,并把这些函数代码添加到可执行文件中。这 种方法同只把函数储存在已编译的.OBJ文件中相比更有利于代码的重用。   但随着Windows这样的多任务环境的出现,函数库的方法显得过于累赘。如果为了完成屏幕输出、消息处理、内存管理、对话框等操作,每个程序都不得不拥有自己的函数,那么Windows程序将变得非常庞大。Windows的发展要求允许同时运行的几个程序共享一组函数的单一拷贝。动态 链接库就是在这种情况下出现的。动态链接库不用重复编译或链接,一旦装入内存,Dlls函数可以被系统中的任何正在运行的应用程序软件所使用,而不必再将DLLs函数的另一拷贝装入内存。 10.1.1 动态链接库的工作原理   "动态链接"这几字指明了DLLs是如何工作的。对于常规的函数库,链接器从中拷贝它需要的所有库函数,并把确切的函数地址传送给调用这些函数的程序。而对于DLLs,函数储存在一个独立的动态链接库文件中。在创建Windows程序时,链接过程并不把DLLs文件链接到程序上。直到程 序运行并调用一个DLLs中的函数时,该程序才要求这个函数的地址。此时Windows才在DLLs中寻找被调用函数,并把它的地址传送给调用程序。采用这种方法,DLLs达到了复用代码的极限。   动态链接库的另一个方便之处是对动态链接库中函数的修改可以自动传播到所有调用它的程序中,而不必对程序作任何改动或处理。   DLLs不仅提供了函数重用的机制,而且提供了数据共享的机制。任何应用程序都可以共享由装入内存的DLLs管理的内存资源块。只包含共享数据的DLLs称为资源文件。如Windows的字体文件等。

2009-05-07

衣购网站项目(三层开发)源码

(1)运用技术 本购物系统运用asp.net2.0开发平台(具体网站配置说明在后面写明),access数据库,采用三层架构进行开发。客户端脚本语言使用JavaScript,服务器端语言使用C#。美工使用Photoshop图片处理软件,使用Dream wearer 进行网页设计。 (2)开发团队 广西财经学院 计算机与信息管理系 电子商务 0722班 闵俊瑜 班小路 黄萍 莫杏妮 姚霞。 三 网站前台功能模块说明 (1)商品模块: 商品模块为核心模块。商品分为新品上架,特价商品,推荐商品三个小模块,分别显示的是最新发布的商品,打折后价格优惠的特价商品和经过网站推荐并且价格合理的商品。在商品信息的网页中显示一件商品的名称,商品一级分类,商品二级分类,商品点击数,商品数量,商品销售量,商品的市场价,会员价和特价。 (2) 用户中心模块 用户中心模块为用户自己的信息管理中心。用户可以通过该模块对自己的资料进行修改,密码修改,查看订单,查看购物车,退出登录。 (3)留言板模块 留言板提供给用户一个和网站信息交流的平台,用户对网站有什么疑问和建议,都在留言板上留言,管理员看过,都可以进行详细的回答和反馈。 (4)商品查询模块 商品查询功能提供了一个快速查看商品的途径。商品查询分为基本查询和高级查询。基本查询:提供关键字和商品大类两种条件的查询,用户可以只填写关键字或者选择商品大类或者关键字和商品大类都填写来查询商品。高级查询:提供关键字,商品大类,商品小类,商品价格范围四种条件的查询,用户可以任意填写其中一种或几种的查询条件来查询想要了解的商品信息。商品查询功能大大的方便了用户,提高了网站的用户体验。 (5)帮助系统模块 帮助系统是一个人性化的功能,当用户对网站的存在疑问或者对购物流程不了解都可以查看帮助系统。 四 网站后台管理 (1)留言管理 管理员可以查看用户的留言,对用户的问题和建议进行回复解答。对留言也可以修改和删除。 (2)订单管理 管理员查看用户的所有订单,了解用户订单的详细情况并且审核订单,可以按用户名和订单状态来查询订单,并对某张订单进行操作。 (3)会员管理 管理员可以查看所有用户,了解用户的基本资料,可以修改用户的资料,密码并且可以删除用户,添加用户。 (4)商品类别管理 管理员可以对商品的一级类别,二级类别进行管理,可以添加,修改,删除商品的一级类别和商品二级类别。 (5)商品管理 管理员可以编辑商品,填写商品的详细资料后发布商品,也可以删除商品。 (6)退出登录 管理员退出管理页面。 App_Data下为Access数据库 管理员账号:51aspx ,密码:51aspx 测试用户账号:popomin,密码:popomin

2009-05-06

VCNET编程宝典资源源代码

VCNET编程宝典资源源代码 (相关的程序)

2009-05-05

java极限编程-java

java极限编程,一本关于java的好书

2009-05-05

ASP经典百例-各种功能编程

ASP经典百例里面的上百个实例,关于web的各种编程 <HTML> <BODY> <TITLE> 用户登录 </TITLE> <% if Request.Form.Count=0 then %> 请输入用户名和密码 <FORM ACTION="login.asp" METHOD="post"> <Table border=0> <tr><td>用户名:</td> <td><INPUT TYPE=text NAME=username VALUE=""></td> </tr> <tr><td>密码:</td> <td><INPUT TYPE=password NAME=password VALUE=""></td> </tr> </Table> <INPUT TYPE=Submit VALUE=确认提交> <INPUT TYPE=reset VALUE=重新输入> </FORM> <%else%> <% Dim user dim pwd user=Request.Form("username") pwd=Request.Form("password") if user="fenfang" then if pwd="1234" then Response.write "用户登录成功" else Response.write "用户密码无效" end if else Response.write "用户无效" end if end if %>

2009-05-05

整理内存的软件(极牛)

这块整理内存的软件,我用拉很长时间..整理效果不错,特别适合配置低,内存小的,常玩大型的游戏的哥们姐妹们. 给大家分享.....

2009-05-05

asp精华集-网页编程

asp精华集设计网页的各种设计及各种功能的实现例子,是初学者提高的好书

2009-04-29

CButtonST示例源代码

CButtonST示例源代码,实现在button控件上既显示文字又显示图片

2009-04-29

MFC深入浅出(李进久)(chm)

这个传错啦...修改不了,大家不要下拉....

2009-04-28

Q版缓冲区溢出教程-场景教程

目录 4 前言 6 作者简介 6 主要角色简介 6 阅读指南 6 第一章、Windows下堆栈溢出入门 8 1.1 梦,已经展开 8 1.2 啤酒和杯子――缓冲区溢出原理 8 1.3 神秘的Windows系统 10 1.4 ShellCode编写简介 17 1.5 窥豹一斑――本地缓冲区溢出简单利用 21 1.6 小结——摘自小强的日记 28 1.7 首次实战――FoxMail溢出漏洞编写 29 1.8 牛刀小试――Printer溢出漏洞编写 41 1.9 JMP /CALL EBX——另一种溢出利用方式 42 1.10 拾阶而上——IDA/IDQ溢出漏洞编写 55 课后解惑 58 第二章、Windows下ShellCode编写初步 60 2.1 ShellCode是什么? 60 2.2 简单的例子——编写控制台窗口的ShellCode 63 2.3 ShellCode通用性的初步分析 78 2.4 弹出Windows对话框ShellCode的编写 82 2.5 添加用户ShellCode的编写 88 课后解惑 98 第三章、后门的编写和ShellCode的提取 100 3.1 预备知识 101 3.2 后门总体思路 121 3.3 Telnet后门的高级语言实现 125 3.4 生成ShellCode 136 3.5 进一步的探讨 156 3.6 反连后门ShellCode的编写 160 课后解惑 166 第四章 Windows下堆溢出利用编程 168 4.1 堆溢出初探 168 4.2 RtlAllcoateHeap的失误 170 4.3 实例——Message堆溢出漏洞的利用 191 4.4 RtlFreeHeap的失误 197 4.5 堆溢出的其他利用方式 204 4.6 实例——JPEG处理堆溢出漏洞的利用 208 课后解惑 215 第五章 ShellCode变形编码大法 217 5.1 为什么要编码 217 5.2 简单的编码——异或大法 221 5.3 简便的变形——微调法 231 5.4 直接替换法 233 5.5 字符拆分法 239 5.6 内存搜索法 247 5.7 搜索实例——Serv_U漏洞的利用 249 5.8 “计算与你同行”—— Computing & Society 257 课后解惑 258 第六章 ShellCode编写高级技术 260 6.1 通用ShellCode的编写 260 6.2 ShellCode的高效提取技巧 285 6.3 ShellCode的高级功能 294 课后解惑 305 第七章、漏洞的发现、分析和利用 308 7.1 CCProxy 漏洞的分析 308 7.2 黑盒法探测漏洞和Python脚本 319 7.3 白盒法和IDA分析漏洞 333

2009-04-28

icwb2-data等分词语料

分词相关训练语料数据icwb2-data icwb2-data icwb2-data

2018-06-28

TE_Socket类|SocksPacket.h|HttpDownload.h

//////////////////////////////////////////////////////////////////////////////// // Copyright (C) 2000-2001 Softelf Inc. All rights reserved. //////////////////////////////////////////////////////////////////////////////// // // Author : Telan // Date : 2000-10-04 // Purpose : Encapsulate winsock2 functions to make it more easily used // History : // 1.0 : 2000-03-10 - First Edition of this source code ( called:FE_SOCKET ) // 2.0 : 2000-06-25 - Second Edition ( name changed to TE_SOCKET ) // - Add Error Control // 3.0 : 2000-09-21 - Third Edition ( name changed to TE_SOCKET ) // - Change the errors' process mechanism // - Add BufSocket Model // - Add TE_ConnectEx(...) // - Add TE_BSocketGetData(...) for specail usage // 3.1 : 2000-10-04 - Add TE_AcceptEx(...) // - Add TE_GetIP(...) to fix NT DNS resolve cache problem // - Modify TE_ConnectEx // - Fix several bugs in NetEvent process // // Mailto : [email protected] ( Bugs' Report or Comments ) // Notes : This source code may be used in any form in any way you desire. It is // provided "as is" without express or implied warranty. Use it at your own // risk! The author accepts no liability for any damage/loss of business // that this product may cause. // //////////////////////////////////////////////////////////////////////////////// #include "stdafx.h" #include "TE_Socket.h" //需要ws2_32.lib库 #pragma comment(lib,"ws2_32.lib") //错误代号 static __declspec(thread) int _iThreadedErrorNo = 0; // 辅助函数 //获取最近一次操作的错误代码 int TE_GetLastError() { return (_iThreadedErrorNo); } //设置错误代码 void TE_SetLastError(int iErrorCode) { _iThreadedErrorNo = iErrorCode; } ///////////////////////////////////////////////////////////////////////// // Winsock2 函数 ///////////////////////////////////////////////////////////////////////// //初始化Winsock2动态连接库 int TE_InitLibrary() { WSADATA WSD; WORD wVersionRequired = MAKEWORD( TE_SOCKET_MAJOR_VERSION,TE_SOCKET_MINOR_VERSION ); ZeroMemory(&WSD,sizeof(WSADATA)); int nErrorNo = WSAStartup(wVersionRequired, &WSD); if ( SOCKET_SUCCESS != nErrorNo ) { TE_SetLastError( nErrorNo ); return ( SOCKET_ERROR ); } if ( LOBYTE( WSD.wVersion ) != TE_SOCKET_MINOR_VERSION || HIBYTE( WSD.wVersion ) != TE_SOCKET_MAJOR_VERSION ) { WSACleanup( ); TE_SetLastError( WSAVERNOTSUPPORTED ); return (SOCKET_ERROR); } //成功初始化 return (SOCKET_SUCCESS); } //释放Winsock2动态连接库 void TE_CleanupLibrary(void) { WSACleanup(); } //设置套接字属性 int TE_SetSocketOption(SOCKET hSocket) { int iActivate = 1; //允许地址重用 if (setsockopt(hSocket, SOL_SOCKET, SO_REUSEADDR, (const char *) &iActivate,sizeof(iActivate)) == SOCKET_ERROR ) { TE_SetLastError( WSAGetLastError() ); return (SOCKET_ERROR); } // 如果支持,设置KEEPALIVE属性 (这样做会带来其他不良后果) //setsockopt(hSocket, SOL_SOCKET, SO_KEEPALIVE, (const char *) &iActivate,sizeof(iActivate)); return (SOCKET_SUCCESS); } //创建具有重叠IO能力的套接字 SOCKET TE_CreateSocket(int iAddressFamily /*= AF_INET*/, int iType/*= SOCK_STREAM*/,int iProtocol/*= 0*/) { SOCKET hSocket = WSASocket(iAddressFamily, iType, iProtocol, NULL,0,WSA_FLAG_OVERLAPPED); if ( hSocket == INVALID_SOCKET ) { TE_SetLastError( WSAGetLastError() ); return (INVALID_SOCKET); } //设置套接字选项 if ( SOCKET_ERROR == TE_SetSocketOption(hSocket) ) //设置属性失败 { TE_CloseSocket(hSocket, TRUE); return (INVALID_SOCKET); } return (hSocket); } //关闭套接字 void TE_CloseSocket(SOCKET hSocket, BOOL bHardClose) { // 不需要捕获错误 if (!bHardClose) // 优雅关闭 Graceful close { // 不再发送数据,对于TCP套接字,在所有的数据都发送完毕之后, // 将发送一个 FIN ,通知接收方所有数据已经发送完毕。 shutdown(hSocket, SD_SEND); // 接收缓冲区有可能还有未接收的数据,在关闭套接字之前应该先 // 读取残留的数据。 int iRecvResult; HANDLE hSocketEvent = CreateEvent(NULL, FALSE, FALSE, NULL); char szBuffer[256]; do { if (hSocketEvent != NULL) { //注册网络事件 WSAEventSelect(hSocket, (WSAEVENT) hSocketEvent, FD_READ | FD_CLOSE); WSAWaitForMultipleEvents(1, &hSocketEvent, TRUE,TE_SHUTDOWN_RECV_TIMEOUT, TRUE); //清除网络事件 WSAEventSelect(hSocket, (WSAEVENT) hSocketEvent, 0); } ZeroMemory(szBuffer,256); iRecvResult = TE_RecvLL(hSocket, szBuffer, sizeof(szBuffer)); } while (iRecvResult > 0); if (hSocketEvent != NULL) CloseHandle(hSocketEvent); //不再允许接收和发送 shutdown(hSocket, SD_BOTH); } // 关闭套接字 closesocket(hSocket); } // 一次性接收数据(重叠IO) int TE_RecvLL(SOCKET hSocket, char *pszBuffer, int iBufferSize) { DWORD dwRtxBytes = 0, dwRtxFlags = 0; WSABUF WSABuff; //清空缓冲 ZeroMemory(&WSABuff,sizeof(WSABUF)); WSABuff.len = iBufferSize; WSABuff.buf = pszBuffer; return ((WSARecv(hSocket, &WSABuff, 1, &dwRtxBytes, &dwRtxFlags,NULL, NULL) == SOCKET_SUCCESS) ? (int) dwRtxBytes : -WSAGetLastError()); } // 接收数据(阻塞直至收到数据为止) int TE_RecvData(SOCKET hSocket, char *pszBuffer, int iBufferSize, DWORD dwTimeout) { HANDLE hReadEvent = CreateEvent(NULL, FALSE, FALSE, NULL); if (hReadEvent == NULL) { TE_SetLastError( (int)GetLastError() ); return ( SOCKET_ERROR ); } int iRecvBytes = 0; DWORD dwWaitResult ; for (;;) { // 注册FD_READ | FD_CLOSE 事件 // (因为可能在等待FD_READ事件中,对方关闭套接字,所以要关注FD_CLOSE) if( WSAEventSelect(hSocket, (WSAEVENT) hReadEvent, FD_READ | FD_CLOSE) == SOCKET_ERROR) { CloseHandle(hReadEvent); TE_SetLastError( WSAGetLastError() ); return (SOCKET_ERROR); } // 等等FD_READ | FD_CLOSE事件的发生 dwWaitResult = WSAWaitForMultipleEvents(1, &hReadEvent, TRUE,dwTimeout, TRUE); if (dwWaitResult != WSA_WAIT_EVENT_0) { // 清除事件 WSAEventSelect(hSocket, (WSAEVENT) hReadEvent, 0); CloseHandle(hReadEvent); TE_SetLastError( WSAGetLastError() ); return (SOCKET_ERROR); } ////////////////////////////////////////////////////////////// /// 注意:即使 dwWaitResult == WSA_WAIT_EVENT0 ,也应该 /// 进一步检查网络是否发生错误 /////////////////////////////////////////////////////////////// WSANETWORKEVENTS NetEvent; if(WSAEnumNetworkEvents(hSocket,(WSAEVENT)hReadEvent,&NetEvent) == SOCKET_ERROR) { // 清除事件 WSAEventSelect(hSocket, (WSAEVENT) hReadEvent, 0); CloseHandle(hReadEvent); TE_SetLastError( WSAGetLastError() ); return (SOCKET_ERROR); } //判断发生了什么事件 FD_READ 或 FD_CLOSE if( ( NetEvent.lNetworkEvents == FD_CLOSE ) || ( NetEvent.lNetworkEvents == FD_READ && NetEvent.iErrorCode[FD_READ_BIT] !=0 ) ) // 发生错误 { // 清除事件 WSAEventSelect(hSocket, (WSAEVENT) hReadEvent, 0); CloseHandle(hReadEvent); TE_SetLastError(WSAGetLastError() ); return (SOCKET_ERROR); } //////////////////////////////////////////////////////////////// // 清除事件 WSAEventSelect(hSocket, (WSAEVENT) hReadEvent, 0); // 接收数据 if ((iRecvBytes = TE_RecvLL(hSocket, pszBuffer, iBufferSize)) >= 0) break; // 跳出循环 int iErrorCode = -iRecvBytes; if ( iErrorCode != WSAEWOULDBLOCK ) //太多的未完成重叠操作 { CloseHandle(hReadEvent); TE_SetLastError( iErrorCode ); return (SOCKET_ERROR); } //阻塞住了 //////////////////////////////////////////////////////////////////////// // 如果发生阻塞,就等待一定时间后重试,以免CPU轮询浪费时间 //////////////////////////////////////////////////////////////////////// Sleep(TE_BLOCKED_SNDRCV_SLEEP); } CloseHandle(hReadEvent); return (iRecvBytes); } // 接收数据直至达到规定的长度(缓冲区满)或超时或没有数据可读取时 int TE_Recv(SOCKET hSocket, char *pszBuffer, int iBufferSize, DWORD dwTimeout) { int iRtxBytes = 0; int iRtxCurrent = 0; while (iRtxBytes < iBufferSize) { iRtxCurrent = TE_RecvData(hSocket, (pszBuffer + iRtxBytes),(iBufferSize - iRtxBytes), dwTimeout); if (iRtxCurrent < 0) //没有数据可读取 return (iRtxBytes); iRtxBytes += iRtxCurrent; } return (iRtxBytes); } //一次性发送数据(重叠IO) int TE_SendLL(SOCKET hSocket, char const * pszBuffer, int iBufferSize) { DWORD dwRtxBytes = 0; WSABUF WSABuff; ZeroMemory(&WSABuff,sizeof(WSABUF)); WSABuff.len = iBufferSize; WSABuff.buf = (char *) pszBuffer; return ((WSASend(hSocket, &WSABuff, 1, &dwRtxBytes, 0,NULL, NULL) == SOCKET_SUCCESS) ? (int) dwRtxBytes : -WSAGetLastError()); } // 发送数据 int TE_SendData(SOCKET hSocket, char const * pszBuffer, int iBufferSize, DWORD dwTimeout) { HANDLE hWriteEvent = CreateEvent(NULL, FALSE, FALSE, NULL); if (hWriteEvent == NULL) { TE_SetLastError( (int)GetLastError() ); return (SOCKET_ERROR); } int iSendBytes = 0; for (;;) { //////////////////////////////////////////////////////////////// // 发送数据成功 if ((iSendBytes = TE_SendLL(hSocket, pszBuffer, iBufferSize)) >= 0) break; int iErrorCode = -iSendBytes; if (iErrorCode != WSAEWOULDBLOCK) { CloseHandle(hWriteEvent); TE_SetLastError( WSAGetLastError() ); return (SOCKET_ERROR); } /////////////////////////////////////////////////////////////////////////////// // 睡眠一段时间 /////////////////////////////////////////////////////////////////////////////// Sleep(TE_BLOCKED_SNDRCV_SLEEP); // 注册FD_WRITE | FD_CLOSE 事件 if( WSAEventSelect(hSocket, (WSAEVENT) hWriteEvent, FD_WRITE|FD_CLOSE) == SOCKET_ERROR) { CloseHandle(hWriteEvent); TE_SetLastError( WSAGetLastError() ); return (SOCKET_ERROR); } // 等待事件发生 DWORD dwWaitResult = WSAWaitForMultipleEvents(1, &hWriteEvent, TRUE,dwTimeout, TRUE); if (dwWaitResult != WSA_WAIT_EVENT_0) { // 清除网络事件 WSAEventSelect(hSocket, (WSAEVENT) hWriteEvent, 0); CloseHandle(hWriteEvent); TE_SetLastError( WSAGetLastError() ); return (SOCKET_ERROR); } ////////////////////////////////////////////////////////////// /// 注意:即使 dwWaitResult == WSA_WAIT_EVENT0 ,也应该 /// 进一步检查网络是否发生错误 /////////////////////////////////////////////////////////////// WSANETWORKEVENTS NetEvent; if(WSAEnumNetworkEvents(hSocket,(WSAEVENT)hWriteEvent,&NetEvent) == SOCKET_ERROR) { // 清除网络事件 WSAEventSelect(hSocket, (WSAEVENT) hWriteEvent, 0); CloseHandle(hWriteEvent); TE_SetLastError( WSAGetLastError() ); return (SOCKET_ERROR); } if( ( NetEvent.lNetworkEvents == FD_CLOSE ) || ( NetEvent.lNetworkEvents == FD_WRITE && NetEvent.iErrorCode[FD_WRITE_BIT] !=0 ) ) // 发生错误 { // 清除网络事件 WSAEventSelect(hSocket, (WSAEVENT) hWriteEvent, 0); CloseHandle(hWriteEvent); TE_SetLastError( WSAGetLastError() ); return (SOCKET_ERROR); } // 清除网络事件 WSAEventSelect(hSocket, (WSAEVENT) hWriteEvent, 0); } CloseHandle(hWriteEvent); return (iSendBytes); } //发送完所有数据或超时 int TE_Send(SOCKET hSocket, char const * pszBuffer, int iBufferSize, DWORD dwTimeout) { int iRtxBytes = 0; int iRtxCurrent = 0; while (iRtxBytes < iBufferSize) { iRtxCurrent = TE_SendData(hSocket, (pszBuffer + iRtxBytes),(iBufferSize - iRtxBytes), dwTimeout); if (iRtxCurrent < 0) return (iRtxBytes); iRtxBytes += iRtxCurrent; } return (iRtxBytes); } // 建立连接 int TE_Connect(SOCKET hSocket, const struct sockaddr * pSocketAddress, int iNameLen,DWORD dwTimeout) { HANDLE hConnectEvent = CreateEvent(NULL, FALSE, FALSE, NULL); if (hConnectEvent == NULL) { TE_SetLastError( (int)GetLastError() ); return (SOCKET_ERROR); } // 注册FD_CONNECT事件 if( WSAEventSelect(hSocket, (WSAEVENT) hConnectEvent, FD_CONNECT) == SOCKET_ERROR) { CloseHandle(hConnectEvent); TE_SetLastError( WSAGetLastError() ); return (SOCKET_ERROR); } int iConnectResult = WSAConnect(hSocket, pSocketAddress, iNameLen, NULL, NULL, NULL, NULL); int iConnectError = WSAGetLastError(); if ((iConnectResult == SOCKET_ERROR) && (iConnectError == WSAEWOULDBLOCK)) { DWORD dwWaitResult = WSAWaitForMultipleEvents(1, &hConnectEvent, TRUE,dwTimeout, TRUE); if (dwWaitResult != WSA_WAIT_EVENT_0) { TE_SetLastError( WSAGetLastError() ); iConnectResult = SOCKET_ERROR; } else { ////////////////////////////////////////////////////////////// /// 注意:即使 dwWaitResult == WSA_WAIT_EVENT0 ,也应该 /// 进一步检查网络是否发生错误 /////////////////////////////////////////////////////////////// WSANETWORKEVENTS NetEvent; if(WSAEnumNetworkEvents(hSocket,(WSAEVENT)hConnectEvent,&NetEvent) == SOCKET_ERROR) { TE_SetLastError( WSAGetLastError() ); iConnectResult = SOCKET_ERROR; } else if(NetEvent.iErrorCode[FD_CONNECT_BIT] !=0 ) // 发生错误 { TE_SetLastError( NetEvent.iErrorCode[FD_CONNECT_BIT] ); iConnectResult = SOCKET_ERROR; } else iConnectResult = SOCKET_SUCCESS; //////////////////////////////////////////////////////////////// } } // 注销网络事件 WSAEventSelect(hSocket, (WSAEVENT) hConnectEvent, 0); CloseHandle(hConnectEvent); return (iConnectResult); } /////////////////////////////////////////////////////////// // // 引入该函数的目的是为了避免NT下对域名解析的CACHE造成的问题 // /////////////////////////////////////////////////////////// DWORD WINAPI DNSThread( LPVOID pParam ) { DWORD dwIP = INADDR_NONE; PHOSTENT pHost = gethostbyname( (char *)pParam ); if(pHost == NULL) return INADDR_NONE; dwIP = inet_addr( inet_ntoa(*(IN_ADDR *)*pHost->h_addr_list) ); return dwIP; } DWORD TE_GetIP(const char* name,BOOL fFixNtDNS /* = FALSE*/) // Used to Fix NT DNS Problem { DWORD dwIP = inet_addr(name); if( dwIP != INADDR_NONE ) return dwIP; if( fFixNtDNS ) { OSVERSIONINFO osVersion; osVersion.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); if( GetVersionEx(&osVersion) ) { if(osVersion.dwPlatformId == VER_PLATFORM_WIN32_NT) { DWORD dwThreadId = 0; HANDLE hThread = CreateThread(NULL,0,DNSThread,(LPVOID)name,0,&dwThreadId); if( hThread != NULL) { WaitForSingleObject(hThread,INFINITE); if( GetExitCodeThread(hThread,&dwIP)) return dwIP; } } } } PHOSTENT pHost = gethostbyname(name); if(pHost == NULL) return INADDR_NONE; dwIP = inet_addr( inet_ntoa(*(IN_ADDR *)*pHost->h_addr_list) ); return dwIP; } // 建立连接(扩展函数) int TE_ConnectEx(SOCKET hSocket, char const * pszServer, int nPort,DWORD dwTimeout,BOOL fFixNtDNS /*= FALSE*/) { ///////////////////////////////////////////////////////////////////////////// SOCKADDR_IN sockAddr; ZeroMemory(&sockAddr,sizeof(sockAddr)); sockAddr.sin_family = AF_INET; sockAddr.sin_port = htons((u_short)nPort); sockAddr.sin_addr.s_addr = TE_GetIP(pszServer,fFixNtDNS); if (sockAddr.sin_addr.s_addr == INADDR_NONE) { TE_SetLastError( WSAGetLastError() ); return (SOCKET_ERROR); } ////////////////////////////////////////////////////////////////////// return TE_Connect(hSocket, (SOCKADDR *)&sockAddr,sizeof(sockAddr),dwTimeout); } // 绑定套接字 int TE_BindSocket(SOCKET hSocket, const struct sockaddr * SockName, int iNameLen) { if (bind(hSocket, SockName, iNameLen) == SOCKET_ERROR) { TE_SetLastError( WSAGetLastError() ); return (SOCKET_ERROR); } return (SOCKET_SUCCESS); } // 绑定套接字 int TE_BindSocketEx(SOCKET hSocket,int nPort) { SOCKADDR_IN sockAddr; ZeroMemory(&sockAddr,sizeof(sockAddr)); sockAddr.sin_family = AF_INET; sockAddr.sin_addr.s_addr = htonl(INADDR_ANY); sockAddr.sin_port = htons((u_short)nPort); return TE_BindSocket(hSocket,(SOCKADDR *)&sockAddr, sizeof(sockAddr)); } // 监听套接字 int TE_ListenSocket(SOCKET hSocket, int iConnections) { if(listen(hSocket, iConnections) == SOCKET_ERROR) { TE_SetLastError( WSAGetLastError() ); return (SOCKET_ERROR); } return (SOCKET_SUCCESS); } // 接受套接字连接 SOCKET TE_Accept(SOCKET hSocket, struct sockaddr * pSocketAddress, int *iNameLen,DWORD dwTimeout) { HANDLE hAcceptEvent = CreateEvent(NULL, FALSE, FALSE, NULL); if (hAcceptEvent == NULL) { TE_SetLastError( (int)GetLastError() ); return (INVALID_SOCKET); } // 注册FD_ACCEPT事件 if( WSAEventSelect(hSocket, (WSAEVENT) hAcceptEvent, FD_ACCEPT) == SOCKET_ERROR) { CloseHandle(hAcceptEvent); TE_SetLastError( WSAGetLastError() ); return (INVALID_SOCKET); } SOCKET hSocketAccept = WSAAccept(hSocket, pSocketAddress, iNameLen, NULL, 0); int iConnectError = WSAGetLastError(); if ((hSocketAccept == INVALID_SOCKET) && (iConnectError == WSAEWOULDBLOCK)) { // 阻塞 DWORD dwWaitResult = WSAWaitForMultipleEvents(1, &hAcceptEvent, TRUE,dwTimeout, TRUE); if (dwWaitResult == WSA_WAIT_EVENT_0) { ////////////////////////////////////////////////////////////// /// 注意:即使 dwWaitResult == WSA_WAIT_EVENT0 ,也应该 /// 进一步检查网络是否发生错误 /////////////////////////////////////////////////////////////// WSANETWORKEVENTS NetEvent; if(WSAEnumNetworkEvents(hSocket,hAcceptEvent,&NetEvent) == SOCKET_ERROR) TE_SetLastError( WSAGetLastError() ); else if(NetEvent.iErrorCode[FD_ACCEPT_BIT] !=0 ) // 发生错误 TE_SetLastError( NetEvent.iErrorCode[FD_ACCEPT_BIT] ); else hSocketAccept = WSAAccept(hSocket, pSocketAddress, iNameLen, NULL, 0); } else TE_SetLastError( WSAGetLastError() ); } // 注销网络事件 WSAEventSelect(hSocket, (WSAEVENT) hAcceptEvent, 0); CloseHandle(hAcceptEvent); if (hSocketAccept != INVALID_SOCKET) { // 设置套接字的属性为地址可重用并且为非阻塞的 if ( (TE_BlockSocket(hSocketAccept, 0) == SOCKET_ERROR ) || (TE_SetSocketOption(hSocketAccept) == SOCKET_ERROR ) ) { TE_CloseSocket(hSocketAccept,TRUE); return (INVALID_SOCKET); } } return (hSocketAccept); } // 接受套接字连接(允许中断) SOCKET TE_AcceptEx(SOCKET hSocket, struct sockaddr * pSockName, int *iNameLen,HANDLE hEndEvent,DWORD dwTimeout /*= TE_DEFAULT_TIMEOUT*/) { if( hEndEvent == NULL) return TE_Accept(hSocket,pSockName,iNameLen,dwTimeout); HANDLE hAcceptEvent = CreateEvent(NULL, FALSE, FALSE, NULL); if (hAcceptEvent == NULL) { TE_SetLastError( (int)GetLastError() ); return (INVALID_SOCKET); } WSAEVENT hEvent[2]; hEvent[0] = (WSAEVENT)hAcceptEvent; hEvent[1] = (WSAEVENT)hEndEvent; // 注册FD_ACCEPT事件 if( WSAEventSelect(hSocket, (WSAEVENT) hAcceptEvent, FD_ACCEPT) == SOCKET_ERROR) { CloseHandle(hAcceptEvent); TE_SetLastError( WSAGetLastError() ); return (INVALID_SOCKET); } SOCKET hSocketAccept = WSAAccept(hSocket, pSockName, iNameLen, NULL, 0); int iConnectError = WSAGetLastError(); if ((hSocketAccept == INVALID_SOCKET) && (iConnectError == WSAEWOULDBLOCK)) { // 阻塞 DWORD dwWaitResult = WSAWaitForMultipleEvents(2, hEvent, FALSE,dwTimeout, TRUE); if (dwWaitResult == WSA_WAIT_EVENT_0) { ////////////////////////////////////////////////////////////// /// 注意:即使 dwWaitResult == WSA_WAIT_EVENT0 ,也应该 /// 进一步检查网络是否发生错误 /////////////////////////////////////////////////////////////// WSANETWORKEVENTS NetEvent; if(WSAEnumNetworkEvents(hSocket,hAcceptEvent,&NetEvent) == SOCKET_ERROR) TE_SetLastError( WSAGetLastError() ); else if(NetEvent.iErrorCode[FD_ACCEPT_BIT] !=0 ) // 发生错误 TE_SetLastError( NetEvent.iErrorCode[FD_ACCEPT_BIT] ); else hSocketAccept = WSAAccept(hSocket, pSockName, iNameLen, NULL, 0); } else TE_SetLastError( WSAGetLastError() ); } // 注销网络事件 WSAEventSelect(hSocket, (WSAEVENT) hAcceptEvent, 0); CloseHandle(hAcceptEvent); if (hSocketAccept != INVALID_SOCKET) { // 设置套接字的属性为地址可重用并且为非阻塞的 if ( (TE_BlockSocket(hSocketAccept, 0) < 0) || (TE_SetSocketOption(hSocketAccept) < 0) ) { TE_CloseSocket(hSocketAccept,TRUE); return (INVALID_SOCKET); } } return (hSocketAccept); } // 设置套接字是否为阻塞的 int TE_BlockSocket(SOCKET hSocket, BOOL bBlock) { u_long IoctlLong = (bBlock) ? 0 : 1; if (ioctlsocket(hSocket, FIONBIO, &IoctlLong) == SOCKET_ERROR) { TE_SetLastError( WSAGetLastError() ); return (SOCKET_ERROR); } return (SOCKET_SUCCESS); } // 数据报接收函数 int TE_RecvDataFrom( SOCKET hSocket, struct sockaddr * pFrom, int iFromlen, char *pszBuffer, int iBufferSize, DWORD dwTimeout) { HANDLE hReadEvent = CreateEvent(NULL, FALSE, FALSE, NULL); if (hReadEvent == NULL) { TE_SetLastError((int)GetLastError() ); return (SOCKET_ERROR); } DWORD dwRtxBytes = 0, dwRtxFlags = 0; WSABUF WSABuff; ZeroMemory(&WSABuff,sizeof(WSABUF)); WSABuff.len = iBufferSize; WSABuff.buf = pszBuffer; for (;;) { // 注册FD_READ事件 if( WSAEventSelect(hSocket, (WSAEVENT) hReadEvent, FD_READ) == SOCKET_ERROR) { CloseHandle(hReadEvent); TE_SetLastError( WSAGetLastError() ); return (SOCKET_ERROR); } DWORD dwWaitResult = WSAWaitForMultipleEvents(1, &hReadEvent, TRUE, dwTimeout, TRUE); if( dwWaitResult != WSA_WAIT_EVENT_0 ) { // 注销事件 WSAEventSelect(hSocket, (WSAEVENT) hReadEvent, 0); CloseHandle(hReadEvent); TE_SetLastError( WSAGetLastError()); return (SOCKET_ERROR); } ////////////////////////////////////////////////////////////// /// 注意:即使 dwWaitResult == WSA_WAIT_EVENT0 ,也应该 /// 进一步检查网络是否发生错误 /////////////////////////////////////////////////////////////// WSANETWORKEVENTS NetEvent; if(WSAEnumNetworkEvents(hSocket,(WSAEVENT)hReadEvent,&NetEvent) == SOCKET_ERROR) { // 注销事件 WSAEventSelect(hSocket, (WSAEVENT) hReadEvent, 0); CloseHandle(hReadEvent); TE_SetLastError( WSAGetLastError() ); return (SOCKET_ERROR); } if(NetEvent.iErrorCode[FD_READ_BIT] !=0 ) // 发生错误 { // 注销事件 WSAEventSelect(hSocket, (WSAEVENT) hReadEvent, 0); CloseHandle(hReadEvent); TE_SetLastError(NetEvent.iErrorCode[FD_READ_BIT]); return (SOCKET_ERROR); } //////////////////////////////////////////////////////////////// // 注销事件 WSAEventSelect(hSocket, (WSAEVENT) hReadEvent, 0); int FromLen = iFromlen; if ( WSARecvFrom(hSocket, &WSABuff, 1, &dwRtxBytes, &dwRtxFlags,pFrom, &FromLen, NULL, NULL) == SOCKET_SUCCESS ) break; if ( WSAGetLastError() != WSAEWOULDBLOCK) { CloseHandle(hReadEvent); TE_SetLastError( WSAGetLastError() ); return (SOCKET_ERROR); } /////////////////////////////////////////////////////////////////////////// // 睡眠一段时间 ////////////////////////////////////////////////////////////////////////// Sleep(TE_BLOCKED_SNDRCV_SLEEP); } CloseHandle(hReadEvent); return ((int) dwRtxBytes); } // 数据报发送数据报 int TE_SendDataTo(SOCKET hSocket, const struct sockaddr * pTo,int iToLen, char const * pszBuffer, int iBufferSize, DWORD dwTimeout) { HANDLE hWriteEvent = CreateEvent(NULL, FALSE, FALSE, NULL); if (hWriteEvent == NULL) { TE_SetLastError( (int)GetLastError() ); return (SOCKET_ERROR); } DWORD dwRtxBytes = 0, dwRtxFlags = 0; WSABUF WSABuff; ZeroMemory(&WSABuff,sizeof(WSABUF)); WSABuff.len = iBufferSize; WSABuff.buf = (char *) pszBuffer; for (;;) { if (WSASendTo( hSocket, &WSABuff, 1, &dwRtxBytes, dwRtxFlags,pTo, iToLen, NULL, NULL) == SOCKET_SUCCESS) break; if (WSAGetLastError() != WSAEWOULDBLOCK) { CloseHandle(hWriteEvent); TE_SetLastError( WSAGetLastError() ); return (SOCKET_ERROR); } ////////////////////////////////////////////////////////////////////////// // 睡眠一段时间 ///////////////////////////////////////////////////////////////////////// Sleep(TE_BLOCKED_SNDRCV_SLEEP); // 注册FD_WRITE事件 if( WSAEventSelect(hSocket, (WSAEVENT) hWriteEvent, FD_WRITE) == SOCKET_ERROR) { CloseHandle(hWriteEvent); TE_SetLastError( WSAGetLastError() ); return (SOCKET_ERROR); } DWORD dwWaitResult = WSAWaitForMultipleEvents(1, &hWriteEvent, TRUE,dwTimeout, TRUE); if( dwWaitResult != WSA_WAIT_EVENT_0 ) { // 注销事件 WSAEventSelect(hSocket, (WSAEVENT) hWriteEvent, 0); CloseHandle(hWriteEvent); TE_SetLastError( WSAGetLastError() ); return (SOCKET_ERROR); } ////////////////////////////////////////////////////////////// /// 注意:即使 dwWaitResult == WSA_WAIT_EVENT0 ,也应该 /// 进一步检查网络是否发生错误 /////////////////////////////////////////////////////////////// WSANETWORKEVENTS NetEvent; if(WSAEnumNetworkEvents(hSocket,(WSAEVENT)hWriteEvent,&NetEvent) == SOCKET_ERROR) { // 注销事件 WSAEventSelect(hSocket, (WSAEVENT) hWriteEvent, 0); CloseHandle(hWriteEvent); TE_SetLastError( WSAGetLastError() ); return (SOCKET_ERROR); } if(NetEvent.iErrorCode[FD_WRITE_BIT] !=0 ) // 发生错误 { // 注销事件 WSAEventSelect(hSocket, (WSAEVENT) hWriteEvent, 0); CloseHandle(hWriteEvent); TE_SetLastError(NetEvent.iErrorCode[FD_WRITE_BIT]); return (SOCKET_ERROR); } //////////////////////////////////////////////////////////////// // 注销事件 WSAEventSelect(hSocket, (WSAEVENT) hWriteEvent, 0); } CloseHandle(hWriteEvent); return ((int) dwRtxBytes); } //////////////////////////////////////////////////////////////////////////////// // // BSocket函数 // //////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// // // 功能: 绑定套接字 // 参数: // hSocket -- SOCKET(待绑定套接字) // iBufferSize -- 缓冲区长度(缺省为TE_SOCKET_BUFFER_SIZE) // 返回: // 结构指针(失败时为NULL) // //////////////////////////////////////////////////////////////////////////////// PBSD TE_BSocketAttach(SOCKET hSocket, int iBufferSize /* = TE_SOCKET_BUFFER_SIZE */ ) { if( hSocket == INVALID_SOCKET) return NULL; // 分配内存 PBSD pBSD = (PBSD) malloc(sizeof(BSD)); if (pBSD == NULL) return NULL; char *pszBuffer = (char *) malloc(iBufferSize); if (pszBuffer == NULL) { free(pBSD); return NULL; } // 设置结构成员 ZeroMemory(pBSD,sizeof(BSD)); ZeroMemory(pszBuffer,iBufferSize); pBSD->hSocket = hSocket; pBSD->iBufferSize = iBufferSize; pBSD->pszBuffer = pszBuffer; pBSD->iBytesInBuffer = 0; pBSD->iReadIndex = 0; pBSD->iBufferIndex = 0; return pBSD; } //////////////////////////////////////////////////////////////////////////// // // 功能: 解开套接字 // 参数: // pBSD -- BufSocketData结构指针 // bCloseSocket -- 是否在解开套接字同时关闭套接字(缺省为FALSE) // 返回: // 若bCloseSocket为FALSE,返回解开的套接字 // 若bCloseSocket为TRUE ,返回INVALID_SOCKET // /////////////////////////////////////////////////////////////////////////// SOCKET TE_BSocketDetach(PBSD pBSD, BOOL bCloseSocket /* = FALSE */ ) { SOCKET hSocket = pBSD->hSocket; // 释放内存 free(pBSD->pszBuffer); free(pBSD); // 是否关闭套接字 if (bCloseSocket) { TE_CloseSocket(hSocket); return (INVALID_SOCKET); } return (hSocket); } //////////////////////////////////////////////////////////////////// // // 功能: 从缓冲区读取数据 // 参数: // pBSD -- BufSocketData结构指针 // dwTimeOut -- 接收超时(缺省为TE_RECV_TIMEOUT) // 返回: // 0 --- 成功 (SOCKET_SUCCESS) // -1 --- 失败 (SOCKET_ERROR) // //////////////////////////////////////////////////////////////////// int TE_BSocketReadData(PBSD pBSD, DWORD dwTimeout /* = TE_RECV_TIMEOUT */ ) { // 计算缓冲区空闲区域 int iMaxRead = pBSD->iBufferSize - pBSD->iBytesInBuffer; char *pszBuffer = (char *) malloc(iMaxRead + 1); if (pszBuffer == NULL) return (SOCKET_ERROR); // 清空 ZeroMemory(pszBuffer,iMaxRead+1); // 接收数据 int iReadedBytes = TE_RecvData(pBSD->hSocket, pszBuffer, iMaxRead, dwTimeout); if (iReadedBytes > 0) { int iHeadSize = Min(pBSD->iBufferSize - pBSD->iBufferIndex, iReadedBytes); if (iHeadSize > 0) memcpy(pBSD->pszBuffer + pBSD->iBufferIndex, pszBuffer, iHeadSize); pBSD->iBufferIndex += iHeadSize; if (pBSD->iBufferIndex == pBSD->iBufferSize) pBSD->iBufferIndex = 0; int iBackSize = iReadedBytes - iHeadSize; if (iBackSize > 0) memcpy(pBSD->pszBuffer + pBSD->iBufferIndex, pszBuffer + iHeadSize, iBackSize); pBSD->iBufferIndex += iBackSize; pBSD->iBytesInBuffer += iReadedBytes; } free(pszBuffer); return (iReadedBytes); } //////////////////////////////////////////////////////////////////// // // 功能: 从缓冲区读取一个字符 // 参数: // pBSD -- BufSocketData结构指针 // dwTimeOut -- 接收超时(缺省为TE_RECV_TIMEOUT) // 返回: // 一个字符(错误时返回TE_EOF) // //////////////////////////////////////////////////////////////////// int TE_BSocketGetChar(PBSD pBSD, DWORD dwTimeout /* = TE_RECV_TIMEOUT */ ) { if ((pBSD->iBytesInBuffer == 0) && (TE_BSocketReadData(pBSD, dwTimeout) <= 0)) return (TE_EOF); int iChar =( (int) pBSD->pszBuffer[pBSD->iReadIndex]) & 0x000000ff; pBSD->iReadIndex = INext(pBSD->iReadIndex, pBSD->iBufferSize); --pBSD->iBytesInBuffer; return (iChar); } //////////////////////////////////////////////////////////////////////////// // // 功能: 从缓冲区读取一行(注意,结尾的回车换行0x0D,0x0A并不包括在其中) // 参数: // pBSD -- BufSocketData结构指针 // pszBuffer -- 接收缓冲区 // iBufferSize -- 缓冲大小 // iStatus -- 状态 (0:正常,1:缓冲不够,-1:错误) // dwTimeOut -- 接收超时(缺省为TE_RECV_TIMEOUT) // 返回: // 0 --- 成功 (SOCKET_SUCCESS) // -1 --- 失败 (SOCKET_ERROR) // //////////////////////////////////////////////////////////////////////////// int TE_BSocketGetString(PBSD pBSD, char *pszBuffer, int iBufferSize, int* iStatus, DWORD dwTimeout /* = TE_RECV_TIMEOUT */ ) { *iStatus = 1; //缓冲长度不足 int ii,iChar; for (ii = 0; ii < (iBufferSize - 1);) { iChar = TE_BSocketGetChar(pBSD, dwTimeout); if (iChar == TE_EOF) { *iStatus = (-1) ; return SOCKET_ERROR; } if (iChar == 0x0D) // 回车符号 { iChar = TE_BSocketGetChar(pBSD, dwTimeout); if (iChar == TE_EOF) { *iStatus = (-1); return (SOCKET_ERROR); } if (iChar == 0x0A) // 换行 { *iStatus = 0; //正常情况 break; } else pszBuffer[ii++] = 0x0D; } else pszBuffer[ii++] = (char) iChar; } pszBuffer[ii] = '\0'; return (SOCKET_SUCCESS); } ///////////////////////////////////////////////////////////////////////////////////////// // // 功能: 从缓冲区读取一行(包括单换行0x0A)(注意,结尾的回车换行不包括在其中) // 参数: // pBSD -- BufSocketData结构指针 // pszBuffer -- 接收缓冲区 // iBufferSize -- 缓冲大小 // iStatus -- 状态 (0:正常,1:缓冲不够,-1:错误) // dwTimeOut -- 接收超时(缺省为TE_RECV_TIMEOUT) // 返回: // 0 --- 成功 (SOCKET_SUCCESS) // -1 --- 失败 (SOCKET_ERROR) // ////////////////////////////////////////////////////////////////////////////////////////// int TE_BSocketGetStringEx(PBSD pBSD, char *pszBuffer, int iBufferSize, int* iStatus, DWORD dwTimeout /* = TE_RECV_TIMEOUT */ ) { *iStatus = 1; //缓冲长度不足 int ii,iChar; int LastChar = TE_EOF; for (ii = 0; ii < (iBufferSize - 1);) { iChar = TE_BSocketGetChar(pBSD, dwTimeout); if (iChar == TE_EOF) { *iStatus = (-1) ; return SOCKET_ERROR; } if (iChar == 0x0A) // 换行符号 { *iStatus = 0; //正常情况 if (LastChar == 0x0D) ii-- ; break; } else pszBuffer[ii++] = (char) iChar; LastChar = iChar; } pszBuffer[ii] = '\0'; return (SOCKET_SUCCESS); } //////////////////////////////////////////////////////////////////// // // 功能: 发送一行 : 自动在最后加上“回车换行符(0x0D,0x0A)” // 参数: // pBSD -- BufSocketData结构指针 // pszBuffer -- 待发送字符串 // dwTimeOut -- 发送超时(缺省为TE_SEND_TIMEOUT) // 返回: // 0 --- 成功 (SOCKET_SUCCESS) // -1 --- 失败 (SOCKET_ERROR) // //////////////////////////////////////////////////////////////////// int TE_BSocketSendString(PBSD pBSD, const char *pszBuffer, DWORD dwTimeout /* = TE_SEND_TIMEOUT */ ) { char *pszSendBuffer = (char *) malloc(strlen(pszBuffer) + 3); if (pszSendBuffer == NULL) return (SOCKET_ERROR); ZeroMemory( pszSendBuffer,strlen(pszBuffer) + 3); sprintf(pszSendBuffer, "%s\r\n", pszBuffer); int iSendLength = strlen(pszSendBuffer); if (TE_Send(pBSD->hSocket, pszSendBuffer, iSendLength, dwTimeout) != iSendLength) { free(pszSendBuffer); return (SOCKET_ERROR); } free(pszSendBuffer); return (iSendLength); } //////////////////////////////////////////////////////////////////// // // 功能: 获取套接字 // 参数: // pBSD -- BufSocketData结构指针 // 返回: // 与此结构绑定在一起的SOCKET // //////////////////////////////////////////////////////////////////// SOCKET TE_BSocketGetAttachedSocket(PBSD pBSD) { return (pBSD->hSocket); } //////////////////////////////////////////////////////////////////// // // 功能: 从缓冲区读取一定数量的数据 // 参数: // pBSD -- BufSocketData结构指针 // pszBuffer -- 接收缓冲区 // iBufferSize -- 缓冲大小 // dwTimeOut -- 接收超时(缺省为TE_RECV_TIMEOUT) // 返回: // 读的数据的字节数 //////////////////////////////////////////////////////////////////// int TE_BSocketGetData(PBSD pBSD, char *pszBuffer, int iBufferSize,DWORD dwTimeout /*= TE_RECV_TIMEOUT*/) { int iReadBytes = 0; int iHeadSize,iBackSize; if ((pBSD->iBytesInBuffer == 0) && (TE_BSocketReadData(pBSD, dwTimeout) <= 0)) return 0; if( pBSD->iBytesInBuffer < iBufferSize ) // 数据不够多 { iHeadSize = Min( pBSD->iBufferSize - pBSD->iReadIndex ,pBSD->iBytesInBuffer ); memcpy(pszBuffer+iReadBytes,pBSD->pszBuffer+pBSD->iReadIndex,iHeadSize); pBSD->iReadIndex += iHeadSize; if( pBSD->iReadIndex == pBSD->iBufferSize ) pBSD->iReadIndex = 0; iReadBytes += iHeadSize; iBackSize = pBSD->iBytesInBuffer - iHeadSize; if( iBackSize > 0) memcpy(pszBuffer+iReadBytes,pBSD->pszBuffer+pBSD->iReadIndex,iBackSize); iReadBytes += iBackSize; pBSD->iReadIndex += iBackSize; pBSD->iBytesInBuffer = 0; // 数据全部读完 } else // 这次的数据足够多了 { iHeadSize = Min( pBSD->iBufferSize - pBSD->iReadIndex,iBufferSize - iReadBytes ); memcpy(pszBuffer+iReadBytes,pBSD->pszBuffer+pBSD->iReadIndex,iHeadSize); pBSD->iReadIndex += iHeadSize; if( pBSD->iReadIndex == pBSD->iBufferSize ) pBSD->iReadIndex = 0; iReadBytes += iHeadSize; iBackSize = iBufferSize - iReadBytes; if( iBackSize > 0) memcpy(pszBuffer+iReadBytes,pBSD->pszBuffer+pBSD->iReadIndex,iBackSize); iReadBytes += iBackSize; pBSD->iReadIndex += iBackSize; pBSD->iBytesInBuffer -= (iHeadSize+iBackSize); } return iReadBytes; }

2009-12-17

发两个BMP转JPG和bmp转gif的控件及适用方法

//bmp to gif void CConvertGIfDlg::OnBrown() { CFileDialog dlg(TRUE,"bmp",NULL,NULL,"位图文件(BMP)|*.bmp",this); if (dlg.DoModal()==IDOK) { m_FileName = dlg.GetPathName(); UpdateData(FALSE); } if (!m_FileName.IsEmpty()) { HANDLE handle = ::LoadImage(AfxGetInstanceHandle(),m_FileName,IMAGE_BITMAP,0,0,LR_LOADFROMFILE); m_Image.SetBitmap((HBITMAP)handle); } } void CConvertGIfDlg::OnConvert() { if (!m_FileName.IsEmpty()) { m_Gif.SetBmpFile(m_FileName); CFileDialog dlg(FALSE,"gif",NULL,NULL,"GIF文件(GIF)|*.gif",this); if (dlg.DoModal()==IDOK) { m_Gif.SaveToFile(dlg.GetPathName()); } } }

2009-11-11

模拟滚动条(带皮肤)

m_Startpt = point; //确定滚动区域 CRect rcScroll = m_ClientRect; rcScroll.left += m_ThumbWidth; rcScroll.right-= m_ThumbWidth; DWORD wparam; SetCapture(); if (m_ThumbRect.PtInRect(point)) { m_ButtonDown = TRUE; } else if (rcScroll.PtInRect(point)) //单击滚动区域 { CPoint centerPt = m_ThumbRect.CenterPoint(); int offset = point.x-centerPt.x; if ((int)point.x<m_ThumbRect.left) //左滚动区域 m_IsLeftRange = TRUE; if ((int)point.x>m_ThumbRect.right) m_IsRightRange= TRUE; m_ThumbRect.OffsetRect(offset,0); int left = m_ThumbRect.left; int right = m_ThumbRect.right; if (left<(int)m_ThumbWidth) //判断当前滚动量是否超出了滚动范围 { int width = m_ThumbRect.Width(); m_ThumbRect.left = m_ThumbWidth; m_ThumbRect.right = m_ThumbRect.left+width; m_CurPos = /*m_MinRange*/(point.x-m_ThumbWidth)*m_Rate; wparam = MAKELONG(SB_PAGELEFT,m_CurPos) ; ::SendMessage(GetParent()->m_hWnd,WM_HSCROLL,wparam,(LPARAM)m_hWnd); DrawControl(); return; } else if (right>(int)(m_ClientRect.Width()-m_ThumbWidth)) { int width = m_ThumbRect.Width(); m_ThumbRect.right = m_ClientRect.Width()-m_ThumbWidth; m_ThumbRect.left = m_ThumbRect.right -width; m_CurPos = m_MaxRange; wparam = MAKELONG(SB_PAGERIGHT,m_CurPos); ::SendMessage(GetParent()->m_hWnd,WM_HSCROLL,wparam,(LPARAM)m_hWnd); DrawControl(); return; }

2009-11-09

滚动条显示图片scrollbar

switch (nSBCode) { case SB_THUMBTRACK: //拖动滚动块 ScrollWindow(-(nPos-pos),0); SetScrollPos(SB_HORZ,nPos); break; case SB_LINELEFT : //单击左箭头 if (pos != 0) { ScrollWindow(1,0); SetScrollPos(SB_HORZ,pos-1); } break; case SB_LINERIGHT: //单击右箭头 if (pos+thumbwidth <= max) { SetScrollPos(SB_HORZ,pos+1); ScrollWindow(-1,0); } break; case SB_PAGELEFT: //在滚动块的左方空白滚动区域单击 if (pos >= thumbwidth) { ScrollWindow(thumbwidth,0); SetScrollPos(SB_HORZ,pos-thumbwidth); } else { ScrollWindow(pos,0); SetScrollPos(SB_HORZ,0); } break; case SB_PAGERIGHT: //在滚动块的右方空白滚动区域单击 if (pos+thumbwidth <= max-thumbwidth) { ScrollWindow(-thumbwidth,0); SetScrollPos(SB_HORZ,pos+thumbwidth); } else { ScrollWindow(-(max-(pos+thumbwidth)),0); SetScrollPos(SB_HORZ,max-thumbwidth); } break; } CDialog::OnHScroll(nSBCode, nPos, pScrollBar);

2009-11-09

CRichEditCtrl利用ole显示word文档

doc.AttachDispatch( app.GetDocuments()); doc1.AttachDispatch(doc.Add(&a,&b,&c,&d)); Range range; //求出文档的所选区域 range = doc1.GetContent();//取出文件内容 CString str; str = range.GetText(); m_richedit.SetWindowText(str); .............

2009-11-09

ADOX创建数据表程序(ACCESS)

//包括创建数据库MDB //获取数据表名 //获取数据列名 //查询数据. //修改更新还没做,发给大家看看, 本人也是新手,就是帮助新手们了解一点数据库呵呵 //获得表内的列名 _RecordsetPtr m_pRecordset; m_pRecordset.CreateInstance("ADODB.Recordset"); long ColCount =0; HRESULT hr; FieldsPtr fields; CString strTemp; strTemp = "SELECT * FROM "; strTemp += strTable; m_pRecordset->Open((_variant_t)strTemp, m_pConnection.GetInterfacePtr(), adOpenDynamic, adLockOptimistic, adCmdText); hr = m_pRecordset->get_Fields (&fields); //得到记录集的字段集和 if(SUCCEEDED(hr)) fields->get_Count(&ColCount); headcount = ColCount; //得到记录集的字段集合中的字段的总个数 CString strColName; CString strTemp1; BSTR bstrColName; LV_COLUMN lvColmon; _variant_t l_vaIndex; l_vaIndex.vt = VT_I2; for(int i=0;iGetItem(l_vaIndex)->get_Name(&bstrColName); //得到记录集//中的字段名 strColName = _com_util::ConvertBSTRToString(bstrColName); strTemp1 = strColName; csArrayCol.Add(strTemp1); lvColmon.iSubItem = i+2; lvColmon.pszText = (LPTSTR)(LPCTSTR)strTemp1; lvColmon.cx = 100; lvColmon.fmt = LVCFMT_LEFT; lc.InsertColumn(i+2, &lvColmon); } if(SUCCEEDED(hr)) fields->Release();//释放指针 m_pRecordset->Close();

2009-09-18

软件测试经验与教训-技术文档

老美高级工程师写的这本软件测试的总结.. 涉及技术和经验 对测试和编程人员都是很有帮助的

2009-07-02

软件开发文档-开发流程..

{ 项目名称 } 立项建议书 文件状态: [√] 草稿 [ ] 正式发布 [ ] 正在修改 文件标识: Company-Project-PIM-PROPOSAL 当前版本: X.Y 作 者: 完成日期: Year-Month-Day 版 本 历 史 版本/状态 作者 参与者 起止日期 备注 目 录 0. 文档介绍 4 0.1 文档目的 4 0.2 文档范围 4 0.3 读者对象 4 0.4 参考文献 4 0.5 术语与缩写解释 4 1. 产品介绍 5 1.1 产品定义 5 1.2 产品开发背景 5 1.3 产品主要功能和特色 5 1.4 产品范围 5 2. 市场概述 6 2.1 客户需求 6 2.2 市场规模与发展趋势 6 3. 产品发展目标 6 4. 产品技术方案 6 4.1 产品体系结构 6 4.2 关键技术 7 5. 产品优缺点分析 7 6. MAKE-OR-BUY决策 7 7. 项目计划 7 7.1 项目团队 7 7.2 软件硬件资源估计 8 7.3 成本估计 8 7.4 进度表 8 8. 市场营销计划 9 8.1产品盈利模式和销售目标 9 8.2 促销和渗透方式 9 8.3 销售方式和渠道 9 9. 成本效益分析 10 10. 总结 10 0. 文档介绍 0.1 文档目的 0.2 文档范围 0.3 读者对象 0.4 参考文献 提示:列出本文档的所有参考文献(可以是非正式出版物),格式如下: [标识符] 作者,文献名称,出版单位(或归属单位),日期 例如: [AAA] 作者,《立项调查报告》,机构名称,日期 [BBB] 作者,《立项可行性分析报告》,机构名称,日期 [SPP-PROC-PIM] SEPG,立项管理规范,机构名称,日期 0.5 术语与缩写解释 缩写、术语 解 释 SPP 精简并行过程,Simplified Parallel Process PIM 立项管理,Project Initialization Management … 1. 产品介绍 1.1 产品定义 提示:用简练的语言说明本产品“是什么”,“什么用途”。根据经验,概念罗嗦含糊的产品很难被用户接受。所以产品定义一定要简练且清晰。 1.2 产品开发背景 提示:从内因、外因两方面阐述产品开发背景,重点说明“为什么”要开发本产品。 (1)因方面着重考虑:开发方的短期、长期发展战略;开发方的当前实力。 (2)外因方面着重考虑:市场需求及发展趋势;技术状况及发展趋势。 (3)如果是合同项目,请说明项目的来源。 1.3 产品主要功能和特色 提示: (1)给出产品的主要功能列表(Feature Lists)。 (2)说明本产品的特色。 1.4 产品范围 提示: (1)说明本产品“适用的领域”和“不适用的领域”。 (2)说明本产品“应当包含的内容”和“不包含的内容”。 2. 市场概述 2.1 客户需求 提示: (1)阐述本产品面向的消费群体(客户)的特征 (2)说明客户对产品的功能性需求和非功能性需求 (3)说明本产品如何满足客户的需求,以及给客户带来什么好处。 2.2 市场规模与发展趋势 提示: (1)分析市场发展历史与发展趋势,说明本产品处于市场的什么发展阶段。 (2)本产品和同类产品的价格分析 (3)统计当前市场的总额、竞争对手所占的份额,分析本产品能占多少份额。 注意:引用数据应当写明数据来源,最好有直观的图表。 3. 产品发展目标 提示:说明本产品的短期目标和长期目标,绘制产品的Roadmap。目标必须清晰并且可以度量。 4. 产品技术方案 4.1 产品体系结构 提示: (1)绘制产品的体系结构 (2)阐述设计原理 (3)如果有多种体系结构,需比较优缺点。 4.2 关键技术 提示:阐述本产品的关键技术,评价技术实现的难易程度 5. 产品优缺点分析 提示:综合考虑本产品的功能、质量、价格、品牌等因素,分析优缺点。 6. Make-or-Buy决策 提示: 确定哪些产品部件应当采购、外包开发或者自主研发,说明理由。 (2)分析相应的风险。 7. 项目计划 7.1 项目团队 提示:说明项目团队的角色、知识技能要求、建议人选、人数、工作时间,如下表所示。 角色 知识技能要求 建议人选、人数 工作时间 项目经理 需求开发人员 系统设计人员 编程人员 测试人员 质量保证人员 配置管理人员 服务与维护人员 …… 7.2 软件硬件资源估计 提示: (1)估计项目所需的软件和硬件资源,说明主要配置。 (2)说明以何种方式获得,如“已经存在”、“可以借用”或“需要购买”等

2009-07-02

强悍的文件夹加密软件

这款加密软件,目前网络任没有破解调的,当你加密以后,记住密码,要不没法找到密码,相对的安全,而且不用机密压缩什么的,只要将软件放置到文件夹里面,运行设置就能加密. 安全技术高,我们公司机密都用这个进行加密.

2009-06-16

VisualC++编程资源大全控件源码

VisualC++编程资源大全源码控件,不错的资料,可以学习下 1,WINAPI_OCX.zip 封装了部分Windows API的控件(92KB)<END> 2,HeaderCtrl.zip 多行标题的CListCtrl(19KB)<END> 3,RoundBut.zip 你需要圆形的按钮吗?这个类已经替你做好了,它可是有正常、平面、下推几种风格的,快使用它吧(25KB)<END> 4,TransBut.zip 实现背景透明的按钮类(306KB)<END> 5,AviButton.zip 这个类库可以在按钮上显示AVI动画,很酷的(68KB)<END> 6,cirbutton.zip 一个圆形的可下推按钮,还不错,可以试试看(50KB)<END> 7,anibutton.zip 这是一个可以使用DIB显示动画的按钮类库,值得一试(186KB)<END> 8,bitbutton.zip 这个类库允许你在按钮上使用位图和文字(9KB)<END> 9,CButtonST.zip 只要你的程序中使用按钮,这个类库就使你可以轻松做出图文并茂的按钮来(133KB)<END> 10,hoverbut.zip 这个类库是对鼠标敏感的按纽,你用它可以做出象Office助手提示选项那样的东东来(24KB)<END> 11,menubut.zip 当用户单击一个按钮时弹出一个菜单(5KB)<END> 12,TrackBut.zip 也是一个位图按钮。不过可比MFC提供的那个好多了!(222KB)<END> 13,Stranbut.zip 你需要不规则形状的按钮吗?这个类已经替你做好了,使用它吧(67KB)<END> 14,tributton.zip 你需要三角形的按钮吗?这个类已经替你做好了,使用它吧(31KB)<END> 15,butpicker.zip 你想有一个选择颜色的下拉列表吗?胜至你想有一个选择图形的下拉列表吗?这个类是你所需的,下载一个回去试试,分析分析一定会有收获(85KB)<END>

2009-06-01

多张小图任意位置合成大图

CCTestSelDrawPicDoc* pDoc = GetDocument(); ASSERT_VALID(pDoc); CRect rect; GetClientRect(&rect); //得到客户区矩形 HBITMAP hbitmap; CBitmap bmptemp; CPoint point(200, 50); MedeyTwoPic(pDC, &m_dcFore, &m_dcBk, &m_bmpFore, &m_bmpBk, point, rect); hbitmap =(HBITMAP)GetCurrentObject(m_dcBk.GetSafeHdc(), OBJ_BITMAP); m_bmpBk.Detach(); m_bmpBk.Attach(hbitmap); CPoint pointtemp1(0,500); MedeyTwoPic(pDC, &m_dcFore, &m_dcBk, &m_bmpFore, &m_bmpBk, pointtemp1, rect); hbitmap =(HBITMAP)GetCurrentObject(m_dcBk.GetSafeHdc(), OBJ_BITMAP); //CBitmap bmptemp1; m_bmpBk.Detach(); m_bmpBk.Attach(hbitmap); CPoint pointtemp2(0,120); MedeyTwoPic(pDC, &m_dcFore, &m_dcBk, &m_bmpFore, &m_bmpBk, pointtemp2, rect); m_bmpBk.Detach(); Tofile(hbitmap, "c:\\temp.bmp");

2009-05-27

类似画图板的小程序-windows

最近做了一个类似Windows画图板的小程序,拿来和大家分享一下。功能和界面全部模仿于Windows自带的画图板,界面如截图。功能主要有: 手绘线、简单图形、文字输入、图块拖放、重复撤销、画面缩放、打开保存图片文件,另外为了直接从数据库或者XML中存取图片,另外还提供了从Base64编码存取图片的接口,其他还实现了和画图板同样效果的工具箱及颜料盒。 1、 绘图: 绘制功能主要在OnLButtonDown、OnMouseMove、OnLButtonUp中实现,根据当前选择的工具和工具的样式进行绘制。程序中每种工具的绘制都是通过一个图元对象实现,比如钢笔、画刷因为本质上都是手绘线所以都通过CDrawPen来实现、直线和矩形等都通过CDrawShape来实现,所有的图元对象都放在文件DrawObject.h中,具体的实现请参见代码。 另外为了避免屏幕的闪烁,程序中做了两个处理:一、把视图自己的重绘背景代码屏蔽掉,即响应视图的WM_ERASEBKGND消息,直接返回TRUE,并在Ondraw中程序自己绘制背景就可以了;二,在Ondraw中绘制的时候,先绘制到内存DC中,然后再贴回视图的DC。这样就基本上就可以避免屏幕的闪烁了。 2、 撤销重做: 由于整个程序较为简单,就没有采用把动作记录下来的方式,只是采取了一个较简单的方法,在每当一个图元绘制动作结束时就把画布的内容存到bmp中以备撤销,这些历史画面存放在一个bmp数组中,并定义了一个Stack类来管理该数组(此实现方式参考了在线杂志21期《类似画笔的绘图控件-卫琳》,在此表示感谢!),然后在屏幕上绘制的时候就是把当前位图贴到屏幕上,并把还没存取位图的图元绘上就行了。 3、 缩放: 一般视图缩放的实现是通过DC的两个函数来实现:SetViewportExt和SetWindowExt,但是这两个函数只在MM_ISOTROPIC和MM_ANISOTROPIC这两种映射模式下有效果,而常用的带滚动条的视图类CScrollView却不支持这两种模式(参见CScrollView::SetScrollSizes)的实现。所以只好把MFC的CScrollView的代码拿过来改了一下以支持MM_ISOTROPIC映射模式,如下所示,具体参见程序文件“ADMMScrollView.h”: ::SetMapMode(hdc,MM_ISOTROPIC); int XLogMm = ::GetDeviceCaps(hdc, HORZSIZE); int YLogMm = ::GetDeviceCaps(hdc, VERTSIZE); int XLogPix = ::GetDeviceCaps(hdc, HORZRES); int YLogPix = ::GetDeviceCaps(hdc, VERTRES); ::SetWindowExtEx(hdc,XLogMm*100,YLogMm*100,NULL); ::SetViewportExtEx(hdc,(int)(XLogPix*fZoomScale), (int)(YLogPix*fZoomScale),NULL); 4、 工具箱: 首先为了实现工具箱的按钮分两列显示的效果,需要设置一下按钮的TBBS_WRAPPED,参见程序中的CToolPaletteBar类;然后,选择不同工具时展现出工具的样式,比如选择“直线”时列出可用的直线宽度样式,该功能通过在ToolBar上放一个CListCtrl实现,当前的工具样式通过图标的方式展现,效果和画图板的类似。 5、 颜料盒: 从CDialogBar类继承了一个类,然后在WM_PAINT响应函数里面绘制一个个小颜色矩形,并重写其OnLButtonDown、OnRButtonDown、OnLButtonDblClk来和用户交互,实现出来的效果还不错,看上去和画图板的颜料盒一样。 6、 鼠标光标样式: 首先在资源文件中增加需要的光标资源,然后在视图的OnSetCursor消息函数中调用SetCursor函数来设置光标样式就可以了,注意要判断HitTest参数是否为HTCLIENT,不然的话鼠标移到了滚动条上的时候光标还是画笔的样式就让人觉得怪怪的了。

2009-05-27

文字与图片合成图片代码

// AddTextDlg.cpp : implementation file // #include "stdafx.h" #include "Test.h" #include "AddTextDlg.h" #include ".\addtextdlg.h" #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif ///////////////////////////////////////////////////////////////////////////// // CAddTextDlg dialog CAddTextDlg::CAddTextDlg(CWnd* pParent /*=NULL*/) : CDialog(CAddTextDlg::IDD, pParent) { //{{AFX_DATA_INIT(CAddTextDlg) m_strText = _T(""); //}}AFX_DATA_INIT m_strBmpFilePath = ""; ZeroMemory(&m_bmpIfHi, sizeof(BITMAPINFOHEADER)); m_dwSize = 0; m_lpDIBits = NULL; } void CAddTextDlg::DoDataExchange(CDataExchange* pDX) { CDialog::DoDataExchange(pDX); //{{AFX_DATA_MAP(CAddTextDlg) DDX_Control(pDX, IDC_EDIT_TEXT, m_edtText); DDX_Control(pDX, IDC_STATIC_SHOW, m_BmpShow); DDX_Text(pDX, IDC_EDIT_TEXT, m_strText); //}}AFX_DATA_MAP } BEGIN_MESSAGE_MAP(CAddTextDlg, CDialog) //{{AFX_MSG_MAP(CAddTextDlg) ON_EN_CHANGE(IDC_EDIT_TEXT, OnChangeEditText) //}}AFX_MSG_MAP ON_BN_CLICKED(IDOK, OnBnClickedOk) END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // CAddTextDlg message handlers BOOL CAddTextDlg::OnInitDialog() { CDialog::OnInitDialog(); // TODO: Add extra initialization here m_edtText.EnableWindow(FALSE); int nCharLimit = 0; if (m_strBmpFilePath.GetLength() > 0) {//传文件路径 if (m_BmpShow.SetReadBmpPath(m_strBmpFilePath, &nCharLimit)) { m_edtText.EnableWindow(); m_edtText.SetLimitText(nCharLimit); } else { PostMessage(WM_CLOSE, 0, 0); } } else {//传位图信息和数据 if (NULL == m_lpDIBits) { PostMessage(WM_CLOSE, 0, 0); } if (m_BmpShow.SetBmpInfo(&m_bmpIfHi, m_lpDIBits, &nCharLimit)) { m_edtText.EnableWindow(); m_edtText.SetLimitText(nCharLimit); } else { PostMessage(WM_CLOSE, 0, 0); } } return TRUE; // return TRUE unless you set the focus to a control } void CAddTextDlg::OnChangeEditText() { // TODO: If this is a RICHEDIT control, the control will not // send this notification unless you override the CDialog::OnInitDialog() // function and call CRichEditCtrl().SetEventMask() // with the ENM_CHANGE flag ORed into the mask. UpdateData(); m_BmpShow.SetBmpText(m_strText); // TODO: Add your control notification handler code here } BOOL CAddTextDlg::SetBmpFilePath(LPCTSTR pszPath) { if (0 == _mbstrlen(pszPath)) { return FALSE; } m_strBmpFilePath = pszPath; return TRUE; } void CAddTextDlg::OnOK() { // TODO: Add extra validation here if (m_strBmpFilePath.GetLength() > 0) { m_BmpShow.SetSaveBmpPath(m_strBmpFilePath); } if (m_lpDIBits != NULL) { delete[] m_lpDIBits; m_lpDIBits = NULL; } m_lpDIBits = new BYTE[m_dwSize]; m_BmpShow.SaveModify(&m_bmpIfHi, m_lpDIBits); CDialog::OnOK(); } void CAddTextDlg::OnCancel() { // TODO: Add extra cleanup here CDialog::OnCancel(); } BOOL CAddTextDlg::SetBmpInfo(const LPBITMAPINFOHEADER lpbmih, const LPVOID lpvBits) { ASSERT((lpbmih != NULL) && (lpvBits != NULL)); m_strBmpFilePath = ""; if (m_lpDIBits != NULL) { delete[] m_lpDIBits; m_lpDIBits = NULL; } if ((lpbmih->biBitCount < 16) || (lpbmih->biBitCount > 32)) { return FALSE; } memcpy(&m_bmpIfHi, lpbmih, sizeof(BITMAPINFOHEADER)); m_BmpShow.ComputeImageSize(&m_bmpIfHi, &m_dwSize); /* if (m_dwSize != lpbmih->biSizeImage) { return FALSE; }*/ m_lpDIBits = new BYTE[m_dwSize]; memcpy(m_lpDIBits, lpvBits, lpbmih->biSizeImage); // memcpy(m_lpDIBits, lpvBits, m_dwSize); return TRUE; } CAddTextDlg::~CAddTextDlg() { if (m_lpDIBits != NULL) { delete[] m_lpDIBits; m_lpDIBits = NULL; } } BOOL CAddTextDlg::GetBmpInfo(LPBITMAPINFOHEADER lpbmih, LPVOID lpvBits, LPDWORD pdwSize) { memcpy(lpbmih, &m_bmpIfHi, sizeof(BITMAPINFOHEADER)); *pdwSize = m_dwSize; memcpy(lpvBits, m_lpDIBits, m_dwSize); return TRUE; } void CAddTextDlg::OnBnClickedOk() { // TODO: 在此添加控件通知处理程序代码 OnOK(); }

2009-05-27

注册表知识大全破解版(CHM)

根据本人经验,修改注册表有三种方法,归纳如下:   在这里提醒大家一句,如果你没有把握,切记在修改之前,一定要备份注册表。 一.用windows的注册表修改器--regedit.exe 方法是在windows的左下角开始菜单里,点击运行,然后键入regedit,回车即可。你可以在打开的修改器里查找所需要修改的注册表修改项。比如要禁止“开始”菜单里的查找功能,我们知道修改的内容为:HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Policies\Explorer,在右边的窗口中新建一个DWORD值"NoFind",并设值为1.(查阅本手册即可找到)。那么我们打开注册表修改器,可以看到有HKEY_CURRENT_USER这个根键,左边还有一个"+"号,点击"+"号展开下面的目录树,找到Software,再展开找Microsoft,这样一层一层地展开,直到找到Explorer项,看右边的窗口,你会发现有不少的键值,恭喜你,你快成功了。然后在右边的窗口中单击鼠标右键,选择新建DWORD值,输入NoFind,注意大小写,你会发现右边窗口中多了一个名为NoFind的键名,OK,我们给它赋值,在NoFind上双击,然后在弹出的窗口中将原来默认的0改成1,最后,重新启动计算机后,你会发现开始菜单里的“查找”消失了,如果你想把它改回来,那么按上面的方法,把1改成0,然后重新启动就可以了。是不是很简单?其他的修改也差不多了,关键是要找到修改的内容,这就是本手册所提供的强大功能了。呵呵,相信能给你带来很大的帮助。   二.用专门的修改软件 如果你很懒,不想知道究竟要修改什么内容。那么就用专门的注册表修改软件了,比较有名气的是“超级兔子魔法”,还有“windows优化大师”,在这里评价一下,windows优化大师名字响,可是不好用。我本人比较喜欢的是另外一个叫“注册终结者”的修改器,主要是界面友好,功能多而不容易出错。现在随着winXP的推出,各种修改器也随之更新,可是功能还有待改进。现在新出的“神奇注册表”修改器,可以修改winXP等,大家可以试试看。这些修改器都很容易上手,修改起来很方便。不过你如果想深入学习注册表,最好还是手动修改了,不然你学不到多少东西的了。 三.手工写.reg注册表文件 这是修改注册表的高级技巧了.有没有试过自己写注册表文件?不用任何修改器?直接把写好的注册表文件——.reg倒入注册表?呵呵,这项技巧并不需要每个人都知道了,你只要知道上面的两个就可以了。当然,如果你是电脑迷,我们赞成深入学习。 现在我们来看看.reg文件的结构如何。 .reg文件的标准格式如下:

2009-05-14

Win CE驱动开发

设备驱动程序是操作系统与硬件交互的方式,是连接硬件与操设备驱动程序是操作系统与硬件交互的方式,是连接硬件与操 作系统之间的桥梁.通常,设备驱动程序在操作系统与硬件之间作系统之间的桥梁.通常,设备驱动程序在操作系统与硬件之间...

2009-05-14

易语言图解(详细版)

本章学习内容: 1.1 如何下载“易语言” 1.6 如何较好地输入程序代码 1.2 如何安装“易语言” 1.7 “易语言”的帮助系统 1.3 了解“易语言”的界面 1.8 初学者的常见问题 1.4 开始写第一个易程序 1.9 课后练习 1.5 分析第一个易程序

2009-05-14

XML电子书(国外的pdf)

XML电子书(国外的pdf) XML电子书(国外的pdf) XML电子书(国外的pdf) XML电子书(国外的pdf) XML电子书(国外的pdf)

2009-05-13

空空如也

TA创建的收藏夹 TA关注的收藏夹

TA关注的人

提示
确定要删除当前文章?
取消 删除