一、前言

AgileEAS.NET SOA 中间件平台是一款基于基于敏捷并行开发思想和Microsoft .Net构件(组件)开发技术而构建的一个快速开发应用平台。用于帮助中小型软件企业建立一条适合市场快速变化的开发团队,以达到节省开发成本、缩短开发时间,快速适应市场变化的目的。

AgileEAS.NET SOA中间件平台提供了敏捷快速开发软件工程的最佳实践,通过提供大量的基础支撑功能如IOC、ORM、SOA、分布式体系及敏捷并发开发方法所支撑的插件开发体系,以及提供了大量的实体、数据模型设计生成工具、代码生成工具,用于帮助中小软件开发商快速成长。

AgileEAS.NET平台充分把握目前软件行业快速发展的新趋势,基于敏捷并行开发、快速适应市场这样淳朴的软件工程实践,采用业界广泛使用的Microsoft .Net构件(组件)开发技术实践了这种开发思想,帮助软件企业实现“敏捷变化、快速适合”的目标,从而帮助软件企业在激烈的市场竞争中赢得先机并获得更高的回报。

二、关于Socket/Tcp框架的需求

在AgileEAS.NET SOA 中间件平台在大量客户的使用过程之中,有的客户提出了一些基于“消息推”、和应用系统事件通知的需求,比如在“医院信息系统”、“电子病历系统‘、”区域公共卫生平台“、等系统之中就提供了这样的需求,比如当大夫为病人开立了医嘱之后、需要在相关护理人员即时提示,之前大家都使用数据库刷新,数据库的压力都比较大,所以迫切的提出了这样的需求。

另外一个原因是AgileEAS.NET SOA 中间件平台之前一直使用WCF、WS、Romotinig通信做为SOA分布式架构的通信基础,我们在考虑WS、WCF的某些协议并不能提供给我们非常高效的通信,所以我们也需要有一套直接基于Socket/TCP的通信体系用于支撑我们的SOA分布式服务业务体系。

三、AgileEAS.NET SOA 中间件Socket/Tcp框架结构

AgileEAS.NET SOA中间件需要的Socket/Tcp框架严格意思是需要的基于Socket的通信消息中件间,其所提供的功能本质是对消息的处理,所以其所提供的API有三大类、Socket框架本身、消息框架及消息处理框架,以下是AgileEAS.NET SOA中间件的Socket/Tcp的应用框架结构:

各上图我们可以看到AgileEAS.NET SOA中间件需要的Socket/Tcp框架实现了这么一件有意思的事,把原生的Socekt基于数据流的流式通信模式转换为基于消息的消息通信模式,让开发人员多复杂的系统Socket通信和数据流处理之中解放出来,转而关心高层通信消息的设计和消息处理的业务设计与实现。

三、AgileEAS.NET SOA 中间件Socket/Tcp框架重要的接口和类

AgileEAS.NET SOA中间件需要的Socket/Tcp框架严格意思是需要的基于Socket的通信消息中件间,其所提供的功能本质是对消息的处理,所以其所提供的API有三大类、Socket框架本身、消息框架及消息处理框架,以下是AgileEAS.NET SOA中间件的Socket/Tcp的应用框架结构:

其中ISocketCient接口为客户段功能封装,其定义大体如下:

   1: /// <summary>

   2: /// Tcp客户端接口。

   3: /// </summary>

   4: public interface ISocketClient : ISocketEngine

   5: {

   6:     /// <summary>

   7:     /// 客户端状态。

   8:     /// </summary>

   9:     ClientState ClientState

  10:     {

  11:         get;

  12:     }        

  13:  

  14:     /// <summary>

  15:     /// 连接Tcp服务器。

  16:     /// </summary>

  17:     bool Connect();

  18:  

  19:     /// <summary>

  20:     /// 关闭与服务器的连接。

  21:     /// </summary>

  22:     void Close();

  23:  

  24:     /// <summary>

  25:     /// 发送消息。

  26:     /// </summary>

  27:     /// <param name="message">消息。</param>

  28:     void Send(IMessage message);

  29:  

  30:     /// <summary>

  31:     /// 调用消息,用于服务器/客户端应用中的请示==》响应消息的应用。

  32:     /// </summary>

  33:     /// <param name="request">请示消息。</param>

  34:     /// <returns>服务器返回的响应消息。</returns>

  35:     IMessage Invoke(IMessage request);

  36:  

  37:     /// <summary>

  38:     /// 异步调用消息,用于服务器/客户端应用中的请示==》响应消息的应用。

  39:     /// </summary>

  40:     /// <param name="request">请示消息。</param>

  41:     /// <returns>包含响应消息的异步任务。</returns>

  42:     NetInvokeTask BeginInvoke(IMessage request);

  43:  

  44:     /// <summary>

  45:     /// 服务器发生错误时触发。

  46:     /// </summary>

  47:     event ErrorEventHandler Error;

  48:  

  49:     /// <summary>

  50:     /// 连接服务器后触发。

  51:     /// </summary>

  52:     event EventHandler Connected;

  53:  

  54:     /// <summary>

  55:     /// 断开服务器连接后触发。

  56:     /// </summary>

  57:     event EventHandler Closed;

  58: }

其是最重要方法为void Send(IMessage message)方法,即发送一个消息到服务器,这个方法也是对使用者开放的最重要方法,在这里发送的不是字节流,而是一个实现了IMessage接口的消息对象,当服户段接收到IMessage对象之后会调用与其对应的消息处理器(IMessageHandler)对象进行消息处理,反之客户段收到IMessage也会调用与其相关的消息处理器(IMessageHandler)对象进行处理。

ISocketServer、ISocketServerBase接口:

   1: /// <summary>

   2: /// Socket服务器基类接口。

   3: /// </summary>

   4: public interface ISocketServerBase : ISocketEngine

   5: {

   6:     /// <summary>

   7:     /// 客户端会话集合。

   8:     /// </summary>

   9:     IList<NetSession> Sessions

  10:     {

  11:         get;

  12:     }

  13:  

  14:     /// <summary>

  15:     /// 注册了一个新会话后发生。

  16:     /// </summary>

  17:     event NetSessionEventHandler SessionStarted;

  18:  

  19:     /// <summary>

  20:     /// 某一个会话结束后发生。

  21:     /// </summary>

  22:     event NetSessionEventHandler SessionAbandoned;

  23:  

  24:     /// <summary>

  25:     /// 发送消息。

  26:     /// </summary>

  27:     /// <param name="target">消息接收方ID(会话ID)。</param>

  28:     /// <param name="message">消息。</param>

  29:     void Send(Guid target, IMessage message);

  30:  

  31:     /// <summary>

  32:     /// 发送网络消息。

  33:     /// </summary>

  34:     /// <param name="target">消息接收方ID(会话ID)。</param>

  35:     /// <param name="netMessage">网络消息。</param>

  36:     void Send(Guid target, NetMessage netMessage);

  37:  

  38:     /// <summary>

  39:     /// 发送网络报文(仅网关模式有效)。

  40:     /// </summary>

  41:     /// <param name="target">消息接收方ID(会话ID)。</param>

  42:     /// <param name="netPacket">网络报文。</param>

  43:     void Send(Guid target, NetPacket netPacket);

  44:  

  45:     /// <summary>

  46:     /// 发送网络数据(仅网关模式有效)。

  47:     /// </summary>

  48:     /// <param name="target">消息接收方ID(会话ID)。</param>

  49:     /// <param name="buffer">网络数据。</param>

  50:     void Send(Guid target, byte[] buffer);

  51: }

   1: /// <summary>

   2: /// Socket服务器接口。

   3: /// </summary>

   4: public interface ISocketServer :  ISocketServerBase

   5: {

   6:     /// <summary>

   7:     /// 客户端连接数。

   8:     /// </summary>

   9:     int ClientCount

  10:     {

  11:         get;

  12:     }

  13:  

  14:     /// <summary>

  15:     /// 服务器状态。

  16:     /// </summary>

  17:     ServerState ServerState

  18:     {

  19:         get;

  20:     }        

  21:  

  22:     /// <summary>

  23:     /// 开始Tcp服务器。

  24:     /// </summary>

  25:     void StartServer();

  26:  

  27:     /// <summary>

  28:     /// 停止Tcp服务器。

  29:     /// </summary>

  30:     void StopServer();

  31:  

  32:     /// <summary>

  33:     /// 关闭指定客户的连接。

  34:     /// </summary>

  35:     /// <param name="client">客户Guid。</param>

  36:     void AbandonSession(System.Guid client);

  37:  

  38:     /// <summary>

  39:     /// 服务器发生错误时触发。

  40:     /// </summary>

  41:     event ServerErrorEventHandler ServerError;

  42:  

  43:     /// <summary>

  44:     /// 服务器启动后触发。

  45:     /// </summary>

  46:     event System.EventHandler ServerStarted;        

  47:  

  48:     /// <summary>

  49:     /// 服务器停止后触发。

  50:     /// </summary>

  51:     event System.EventHandler ServerStopped;

  52: }

这两个接口定义了SocketServer的一些行为和属性,其中最重要的方法还是void Send(Guid target, IMessage message),实现向某个特定客户段连接发送应用消息,别外定义了一个IList<NetSession> Sessions属性,表示目前连接到此SocketServer的所有客户端会话信息。

NetSession表示服务器的一个客户段连接会话,包括连接上下文信息和连接的Socket通信对象,当某个SocketClient发送给SocketServer的信息都会被与其应对的NetSession进行处理,NetSession定义两个重要的方法public void Reply(uint requestID, IMessage message)和public void Abandon(),其中Reply表示向客户端回复一个消息,Abandon表示服务器强制中止此会话。

在整个Socket/tcp框架之中进行通信的最基本单元都是IMessage,那么SocketClient、SocketServer接收到IMessage如何处理呢,答案是由与之配对的IMessageHandler进行处理,所以SocketClient、SocketServer都实现了一个基础接口ISocketEngine:

   1: /// <summary>

   2: /// Socket引擎,Socket网络通信基础类。

   3: /// </summary>

   4: public interface ISocketEngine : IDisposable

   5: {

   6:     /// <summary>

   7:     /// 通信引擎的全局唯一标识符号。

   8:     /// </summary>

   9:     System.Guid Guid

  10:     {

  11:         get;

  12:     }

  13:  

  14:     /// <summary>

  15:     /// IP地址和端口号。

  16:     /// </summary>

  17:     IPEndPoint IPEndPoint

  18:     {

  19:         get;

  20:         set;

  21:     }

  22:  

  23:     /// <summary>

  24:     /// IP地址。

  25:     /// </summary>

  26:     string IPAddress

  27:     {

  28:         get;

  29:         set;

  30:     }

  31:  

  32:     /// <summary>

  33:     /// 端口号。

  34:     /// </summary>

  35:     int Port

  36:     {

  37:         get;

  38:         set;

  39:     }

  40:  

  41:     /// <summary>

  42:     /// 报文最大长度。

  43:     /// </summary>

  44:     int MessageMaxSize

  45:     {

  46:         get;

  47:     }        

  48:  

  49:     /// <summary>

  50:     /// 注册消息处理器。

  51:     /// </summary>

  52:     /// <typeparam name="T">消息类型。</typeparam>

  53:     /// <param name="hander">消息处理器。</param>

  54:     void AddHander<T>(IMessageHandler<T> hander) where T : IMessage;

  55:  

  56:     /// <summary>

  57:     /// 通过Socket发送数据之后触发。

  58:     /// </summary>

  59:     event SocketDataHandler SocketDataSend;

  60:  

  61:     /// <summary>

  62:     ///  通过Socket接收数据之后触发。

  63:     /// </summary>

  64:     event SocketDataHandler SocketDataReceived;

  65:  

  66:     /// <summary>

  67:     /// 发送报文完成之后触发。

  68:     /// </summary>

  69:     event PacketHandler PacketSend;

  70:  

  71:     /// <summary>

  72:     /// 报文接收完成之后触发。

  73:     /// </summary>

  74:     event PacketHandler PacketReceived;

  75:  

  76:     /// <summary>

  77:     /// 载送完一个NetMessage之后触发。

  78:     /// </summary>

  79:     event NetMessageHandler NetMessageSend;

  80:  

  81:     /// <summary>

  82:     /// 接收完一个NetMessage之后触发。

  83:     /// </summary>

  84:     event NetMessageHandler NetMessageReceived;

  85:  

  86:     /// <summary>

  87:     /// 消息发送完成之后触发。

  88:     /// </summary>

  89:     event MessageHandler MessageSend;

  90:  

  91:     /// <summary>

  92:     /// 接收消息完成之后触发。

  93:     /// </summary>

  94:     event MessageHandler MessageReceived;

  95: }

其中方法void AddHander<T>(IMessageHandler<T> hander) where T : IMessage实现对消息处理器的注册,以便收到IMessage之后选择合适的处理器进行处理。

四、消息和消息处理器

从以上的介绍我们可以明确的知道AgileEAS.NET SOA中间件Socket/Tcp框架是的一个基于消息对象的消息通信框架,那么其最核心的业务就是定义消息及消息的处理思路,我们称之为消息及消息处理器结构:

其中IMessage接口为Socket/Tcp框架中最重要的接口,所有高层的应用消息都需要实现本接口:

   1: /// <summary>

   2: /// 消息接口定义。

   3: /// </summary>

   4: /// <remarks>

   5: /// 这里所说的消息是指业务处理的最小单元,而不是传输于网络之间的网络消息。

   6: /// </remarks>

   7: public interface IMessage

   8: {

   9:     /// <summary>

  10:     /// 从指定的 MessageReader加载消息对象。

  11:     /// </summary>

  12:     /// <param name="reader">消息读取器。</param>

  13:     void Load(BufferReader reader);

  14:  

  15:     /// <summary>

  16:     /// 将消息对象保存到指定的MessageWriter。

  17:     /// </summary>

  18:     /// <param name="writer">消息编写器。</param>

  19:     void WriteTo(BufferWriter writer);

  20: }

其中Load和WriteTo实现IMessage消息对象实例与字节流之间进行相互转换,Load消息用于从字节流之中读取并实例化消息、WriteTo把消息转换为流写入消息流之中,在应用开发过程之中必须实现这两个方法并且在消息类上打上MessageAttribute标记:

   1: /// <summary>

   2: /// 消息ID属性。

   3: /// </summary>

   4: /// <remarks>

   5: /// 标记网络消息,确定其唯一的ID。

   6: /// </remarks>

   7: [AttributeUsage(AttributeTargets.Class)]

   8: public class MessageAttribute : Attribute

   9: {

  10:     /// <summary>

  11:     /// 初始化MessageAttribute对象实例。

  12:     /// </summary>

  13:     /// <param name="messageID">消息ID。</param>

  14:     public MessageAttribute(string messageID)

  15:         :this(messageID,string.Empty)

  16:     {

  17:  

  18:     }

  19:  

  20:     /// <summary>

  21:     /// 初始化MessageAttribute对象实例。

  22:     /// </summary>

  23:     /// <param name="messageID">消息ID。</param>

  24:     /// <param name="description">消息说明。</param>

  25:     public MessageAttribute(string messageID, string description)

  26:     {

  27:         this.MessageID = new Guid(messageID);

  28:         this.Description = description;

  29:     }

  30:  

  31:     /// <summary>

  32:     /// 消息ID。

  33:     /// </summary>

  34:     public Guid MessageID

  35:     {

  36:         get;

  37:         set;

  38:     }

  39:  

  40:     /// <summary>

  41:     /// 消息说明。

  42:     /// </summary>

  43:     public string Description

  44:     {

  45:         get;

  46:         set;

  47:     }

  48: }

MessageAttribute标记用于向已实现IMessage接口的具体消息的消息ID与消息说明,即向Socket通信框架声音本消息的唯一性之用,其中MessageID为一个GUID对象,GUID对象理论上是唯一的,我们可以表示消息的唯一性,以下是一个具体的消息例子:

   1: /// <summary>

   2: /// 用户登录消息。

   3: /// </summary>

   4: [Message("F42433DF-2D4D-4514-9523-2FE911E63CAA", "登录消息")]

   5: [Serializable]

   6: public class LoginMessage : IMessage

   7: {

   8:     /// <summary>

   9:     /// 用户名。

  10:     /// </summary>

  11:     public string LoginID

  12:     {

  13:         get;

  14:         set;

  15:     }

  16:  

  17:     /// <summary>

  18:     /// 密码。

  19:     /// </summary>

  20:     public string PassWord

  21:     {

  22:         get;

  23:         set;

  24:     }

  25:  

  26:     #region IMessage 成员

  27:  

  28:     /// <summary>

  29:     /// 

  30:     /// </summary>

  31:     /// <param name="reader"></param>

  32:     public void Load(EAS.IO.BufferReader reader)

  33:     {

  34:         LoginID = reader.ReadString();

  35:         PassWord = reader.ReadString();

  36:     }

  37:  

  38:     /// <summary>

  39:     /// 

  40:     /// </summary>

  41:     /// <param name="writer"></param>

  42:     public void WriteTo(EAS.IO.BufferWriter writer)

  43:     {

  44:         writer.Write(LoginID);

  45:         writer.Write(PassWord);

  46:     }

  47:  

  48:     #endregion

  49: }

以上是一个具体消息的例子,其表明消息ID为“F42433DF-2D4D-4514-9523-2FE911E63CAA”,其作用是登录消息,用于实现类似登录业务。

五、可靠的消息中间件

AgileEAS.NET SOA中间件Socket/Tcp框架是一个可靠的消息中间件,在设计过程之初就选择了完成端口模型进行开发,以保证服务的高并发和吞吐量,在底层消息通信上,我们选择了不超过8K的可变大小通信报文,比如当一个高层的IMeesage只有512字节内容的时候,会取转成一个一个远小于8K的报文进行发送,如果一个高层IMeesage为66K时,会被分解成为9条消息报文进行通信,前8条消息报文长度为8K,最后一条不满足8K,接收文收到这9条报文后组合并转换为IMeesage对象之后交由消息处理器IMeeesgaHandler进行处理。

在进行消息报文收发过程之中,经过长期测试、验证、设计和选择了高性能的防粘包设计,避免应用开发者头疼的消息粘包问题。

六、AgileEAS.NET SOA中间件需要的Socket/Tcp框架下载

AgileEAS.NET SOA中间件Socket/Tcp框架包含在AgileEAS.NET SOA中间件平台之中,具体定义在EAS.MicroKernel.dll程序集之中,要使用AgileEAS.NET SOA中间件Socket/Tcp框架进行基于Socket的通信开发,请通过AgilleEAS.NET SOA 中站件平台官方网站最新下载页面下载。

七、联系我们

为了完善、改进和推广AgileEAS.NET而成立了敏捷软件工程实验室,是一家研究、推广和发展新技术,并致力于提供具有自主知识产权的业务基础平台软件,以及基于业务基础平台了开发的管理软件的专业软件提供商。主要业务是为客户提供软件企业研发管理解决方案、企业管理软件开发,以及相关的技术支持,管理及技术咨询与培训业务。

AgileEAS.NET平台自2004年秋呱呱落地一来,我就一直在逐步完善和改进,也被应用于保险、医疗、电子商务、房地产、铁路、教育等多个应用,但一直都是以我个人在推广,2010年因为我辞职休息,我就想到把AgileEAS.NET推向市场,让更多的人使用。

我的技术团队成员都是合作多年的老朋友,因为这个平台是免费的,所以也没有什么收入,都是由程序员的那种理想与信念坚持,在此我感谢一起奋斗的朋友。

团队网站:http://www.agilelab.cn

AgileEAS.NET网站:http://www.agileeas.net

官方博客:http://eastjade.cnblogs.com

github:https://github.com/agilelab/eas

QQ:47920381

AgileEAS.NET QQ群:

113723486(AgileEAS SOA 平台)/上限1000人

199463175(AgileEAS SOA 交流)/上限1000人

120661978(AgileEAS.NET 平台交流)/上限1000人

212867943(AgileEAS.NET研究)/上限500人

147168308(AgileEAS.NET应用)/上限500人

172060626(深度AgileEAS.NET平台)/上限500人

116773358(AgileEAS.NET 平台)/上限500人

125643764(AgileEAS.NET探讨)/上限500人

193486983(AgileEAS.NET 平台)/上限500人

邮件:james@agilelab.cn,mail.james@qq.com,

电话:18629261335。

AgileEAS.NET SOA 中间件平台.Net Socket通信框架-介绍的更多相关文章

  1. AgileEAS.NET SOA 中间件平台.Net Socket通信框架-简单例子-实现简单的服务端客户端消息应答

    一.AgileEAS.NET SOA中间件Socket/Tcp框架介绍 在文章AgileEAS.NET SOA 中间件平台Socket/Tcp通信框架介绍一文之中我们对AgileEAS.NET SOA ...

  2. AgileEAS.NET SOA 中间件平台.Net Socket通信框架-完整应用例子-在线聊天室系统-下载配置

    一.AgileEAS.NET SOA中间件Socket/Tcp框架介绍 在文章AgileEAS.NET SOA 中间件平台Socket/Tcp通信框架介绍一文之中我们对AgileEAS.NET SOA ...

  3. AgileEAS.NET SOA中间件平台/敏捷软件开发平台

    AgileEAS.NET SOA中间件平台/敏捷软件开发平台 最新下载 一.前言 AgileEAS.NET SOA中间件平台,简称EAS.NET,是基于敏捷并行开发思想和Microsoft .Net构 ...

  4. AgileEAS.NET SOA 中间件平台 5.2 发布说明-包含Silverlight及报表系统的开源代码下载

    一.AgileEAS.NET SOA 中间件简介      AgileEAS.NET SOA 中间件平台是一款基于基于敏捷并行开发思想和Microsoft .Net构件(组件)开发技术而构建的一个快速 ...

  5. AgileEAS.NET SOA中间件平台更新日志 2015-04-28

    一.前言 AgileEAS.NET SOA 中间件平台是一款基于基于敏捷并行开发思想和Microsoft .Net构件(组件)开发技术而构建的一个快速开发应用平台.用于帮助中小型软件企业建立一条适合市 ...

  6. AgileEAS.NET SOA 中间件平台5.2版本下载、配置学习(二):配置WinClient分布式运行环境

    一.前言 AgileEAS.NET SOA 中间件平台是一款基于基于敏捷并行开发思想和Microsoft .Net构件(组件)开发技术而构建的一个快速开发应用平台.用于帮助中小型软件企业建立一条适合市 ...

  7. AgileEAS.NET SOA 中间件平台5.2版本下载、配置学习(四):开源的Silverlight运行容器的编译、配置

    一.前言 AgileEAS.NET SOA 中间件平台是一款基于基于敏捷并行开发思想和Microsoft .Net构件(组件)开发技术而构建的一个快速开发应用平台.用于帮助中小型软件企业建立一条适合市 ...

  8. AgileEAS.NET SOA 中间件平台5.2版本下载、配置学习(三):配置ActiveXForm运行环境

    一.前言 AgileEAS.NET SOA 中间件平台是一款基于基于敏捷并行开发思想和Microsoft .Net构件(组件)开发技术而构建的一个快速开发应用平台.用于帮助中小型软件企业建立一条适合市 ...

  9. 重写AgileEAS.NET SOA 中间件平台账号密码的加密算法

    一.平台简介 AgileEAS.NET SOA 中间件平台是一款基于基于敏捷并行开发思想和Microsoft .Net构件(组件)开发技术而构建的一个快速开发应用平台.用于帮助中小型软件企业建立一条适 ...

随机推荐

  1. 【转】windows环境下安装win8.1+Mac OS X 10.10双系统教程

    先要感谢远景论坛里的各位大神们的帖子  没有他们的分享我也不能顺利的装上Mac OS X 10.10! 写这篇随笔主要是为了防止自己遗忘,同时给大家分享下我的经验. 本教程适用于BIOS+MBR分区的 ...

  2. Struts2--属性设置方式

    Struts2自动获取/设置数据的方式一共分为两种 属性驱动(FieldDriven) 模型驱动(ModelDriven) 属性驱动 属性又分为两种: |- 基本数据类型 |- JavaBean属性类 ...

  3. ubuntu 14.04 修改网络配置

    修改IP地址: vi /etc/network/interfaces

  4. ORACLE常用数值函数、转换函数、字符串函数

    本文更多将会介绍三思在日常中经常会用到的,或者虽然很少用到,但是感觉挺有意思的一些函数.分二类介绍,分别是: 著名函数篇 -经常用到的函数 非著名函数篇-即虽然很少用到,但某些情况下却很实用 注:N表 ...

  5. hdu2005第几天?

    Problem Description 给定一个日期,输出这个日期是该年的第几天.   Input 输入数据有多组,每组占一行,数据格式为YYYY/MM/DD组成,具体参见sample input , ...

  6. Android源代码查看途径

    作为一个android coder,多阅读android源码对提高android开发水平是很有帮助的,那么我们可以通过哪些途径查看android源码呢 1.如果你能够FQ的话可以去android官网查 ...

  7. eafier 簡單易用 HTML、CSS 網頁編輯器(可自動插入 Tag 標籤)

    很久很久以前,一般人要做網頁的話大概都會用 FrontPage 之類的工具,更進階一點的會用 Dreamweaver 等軟體.雖然上述軟體提供很方便的「所見即所得」的編輯預覽模式,但寫出來的網頁程式碼 ...

  8. hashMap 深入理解

    1.java 的hashMap 是通过 链地址 法来解决 hash冲突的 2.初始时是一个empty table, 第一次添加数据时检查到时空数组就会 生成指定容量的数组,也就是 在第一次使用时才初始 ...

  9. 使用SVG绘制湖南地图

    项目中有需求使用SVG绘制湖南地图,现把自己制作过程写一下供大家参考. 1.首先准备一张湖南地图(仅有各市边界线即可).(图片最好是PNG的,除了地图其它什么也没有) 2.准备SVG编辑工具SVGDe ...

  10. 安装sitecore数据库和客户端到本机

    (提前先装好数据库和IIS) 安装教程下载:http://download.csdn.net/detail/qq1162195421/6436799 安装过程省略... 1.安装好之后,会自动在安装路 ...