好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

如何从 Winform 移植到 Webform [自己搞定HTTP协议]

如何从 Winform 移植到 Webform [自己搞定HTTP协议]

Winform 如何移植到 WebForm。

这个问题其实也就是要找一个好的方案,最大程度的复用现有的资源。

同时,WebForm的话,不一定要走ASPNET这条路,可以自己搞定HTTP协议的。

    下图是Winform版 

      

    下图是Web版本

      

1。如何自己搞定HTTP协议

     WebForm,可以重头老老实实的用ASPNET来做,不过,现在Oracle,MongoDB这样的数据库都支持本地的浏览器方式管理了,这样的应用,不用安装ASP,PHP这样的服务器,完全自己实现一个简单的HTTP服务器。

      OK,我们也实现一个吧,侦听13000(这里随便什么都可以的,不过推荐使用10000以上的端口号)端口,开启多线程,做HTTP服务吧。

         public   void  Start()
        {
            TcpListener server =  null ;
             try
            {
                 //  Set the TcpListener on port 13000.
                Int32 port =  13000 ;
                IPAddress localAddr = IPAddress.Parse( " 127.0.0.1 " );

                 //  TcpListener server = new TcpListener(port);
                server =  new  TcpListener(localAddr, port);

                 //  Start listening for client requests.
                server.Start();

                 //  Enter the listening loop.
                 while  ( true )
                {
                     /// 对于每个请求创建一个线程,线程的参数是TcpClient对象
                    TcpClient client = server.AcceptTcpClient();
                    OutputLog( " [Init] "  + DateTime.Now +  " Connected! " ,  0 );
                    ParameterizedThreadStart ParStart =  new  ParameterizedThreadStart(ProcessFun);
                    Thread t =  new  Thread(ParStart);
                    t.Start(client);
                }
            }
             catch  (SocketException e)
            {
                OutputLog( " SocketException:  "  + e,  0 );
            }
             finally
            {
                 //  Stop listening for new clients.
                server.Stop();
                server =  null ;
            }

        }

复制代码

这里就是不停的启动ProcessFun来响应客户端(写客户端),同时用一个无限循环来侦听请求。

  private   void  ProcessFun( object  clientObj)
        {
            TcpClient client = clientObj  as  TcpClient;
             //  Buffer for reading data
            Byte[] bytes =  new  Byte[ 512 ];

            OutputLog( " [Init]Waiting for a connection...  " ,  0 );

             //  Get a stream object for reading and writing
            NetworkStream stream = client.GetStream();
             int  i;
             //  Loop to receive all the data sent by the client.
             while  ((client.Available !=  0 ) && (i = stream.Read(bytes,  0 , bytes.Length)) !=  0 )
            {
                 //  Translate data bytes to a ASCII string.
                String data = System.Text.Encoding.ASCII.GetString(bytes,  0 , i);
                 // OutputLog("Received:" + data);

                 string [] OrgRequest = data.Split(Environment.NewLine.ToCharArray());
                 if  (OrgRequest[ 0 ].StartsWith( " GET " ))
                {
                    String[] Request = OrgRequest[ 0 ].Split( "   " .ToCharArray());
                    String RequestItem = HttpUtility.UrlDecode(Request[ 1 ], System.Text.Encoding.UTF8);
                    OutputLog( " [RequestItem]Received :  "  + RequestItem,  0 );
                    String[] RequestPath = RequestItem.Split( " ? " .ToCharArray());
                     switch  (RequestPath[ 0 ])
                    {
                         case   " / " :
                             // 根节点 
                            GETPage(stream, GetPage.ConnectionList());
                             break ;
                         case   " /Connection " :
                            GETPage(stream, GetPage.Connection(RequestPath[ 1 ]));
                             break ;
                         default :
                            GETFile(stream, RequestItem.Replace( " / " ,  " \\ " ));
                             break ;
                    }
                }
                 else
                {
                     if  (OrgRequest[ 0 ].StartsWith( " POST " ))
                    {

                    }
                }
            }

             //  Shutdown and end connection
            client.Close();
        }

复制代码

 这里响应请求,我只写完了GET,POST还没有开始动手呢。这里我们通过Stream.Read来获取请求,然后根据请求内容来寻找资源,将资源返还给客户端。

         ///   <summary>
         ///  
         ///   </summary>
         ///   <param name="stream"></param>
         ///   <param name="FileName"></param>
         private   void  GETFile(NetworkStream stream, String FileName)
        {
             byte [] msg =  null ;
             byte [] bFile =  new   byte [ 0 ];
            String data = String.Empty;
            Boolean IsFound =  false ;
             if  (File.Exists(ServerPath + FileName))
            {
                IsFound =  true ;
                bFile = ReadFile(ServerPath + FileName);
            }
             else
            {
                 // 资源文件里面获得
                 if  (FileName.StartsWith( " \\MainTreeImage " ))
                {
                     // MainTreeImage00.png -- 从MainTreeImage 里面获得
                     int  MainTreeImageIndex = Convert.ToInt32(FileName.Substring( " \\MainTreeImage " .Length,  2 ));
                    Image img = GetSystemIcon.MainTreeImage.Images[MainTreeImageIndex];
                    bFile = GetSystemIcon.imageToByteArray(img,ImageFormat.Png);
                    IsFound =  true ;
                }
            }

             if  (IsFound)
            {
                 //  Process the data sent by the client.
                data =  " HTTP/1.1 200 OK "  + Environment.NewLine;
                 // if content-type is wrong,FF can;t render it,but IE can
                 string  filetype = String.Empty;
                 switch  ( new  FileInfo(FileName).Extension)
                {
                     case   " .css " :
                        filetype =  " text/css " ;
                         break ;
                     case   " .js " :
                        filetype =  " text/javascript " ;
                         break ;
                     case   " .png " :
                        filetype =  " image " ;
                         break ;
                     default :
                         break ;
                }
                data +=  " Content-Type: @filetype; charset=utf-8 " .Replace( " @filetype " , filetype) + Environment.NewLine;
                data +=  " Content-Length:  " ;
                data += (bFile.Length).ToString();
                data += Environment.NewLine + Environment.NewLine;
                msg = System.Text.Encoding.ASCII.GetBytes(data);
                 //  Send back a response.
                stream.Write(msg,  0 , msg.Length);
                stream.Write(bFile,  0 , bFile.Length);
                OutputLog( " [System]Sent HTML OK " ,  0 );

            }
             else
            {
                data =  " HTTP/1.1 404 Not Found "  + Environment.NewLine;
                msg = System.Text.Encoding.ASCII.GetBytes(data);
                 //  Send back a response.
                stream.Write(msg,  0 , msg.Length);
                OutputLog( " [System]FileName Not Found: "  + FileName,  0 );
            }
            stream.Flush();

        }
    }

复制代码

 将资源(文件)给客户端,就是将资源转换为Bytes字节流,然后写入NetStream里面去。

 当然,为了“欺骗”浏览器,我们还要在成功找到资源的时候,给个200 OK的标记,如果没有资源的话,给个404的标记。

 以后,还要考虑 缓存的问题,已经请求过的资源,就给个3XX的,不用再重复取得资源了。

 对于有些资源内容,这里干脆不从实体文件里面取了,直接从资源里面取了。客户才不知道这个文件到底怎么来的。   

2。最大程度的复用代码

    为了展示这个树形结构,原来的Windows代码非常的冗长(不是冗余)。

    如何将这个树形Winform转为WebForm?如果最大程度的复用代码,这是必须要考虑的。树形展示,我使用了zTree这个Jquery插件。只要能够给他一个JSON的节点信息,就可以帮你自动完成树形了。

    原来的代码的目标是生成一个Treeview,现在的目标是做个JSON。当然,可以将原来的代码里面的TreeNode的构成逻辑化为BsonDocument(MongoDB的概念,类似JSON)。不过,最最正确的做法是,直接将Treeview的结果转换为JSON。不用修改任何原来的代码,最大限度的使用原来的代码。

#region "展示数据库结构 WebForm"
         ///   <summary>
         ///  
         ///   </summary>
         ///   <param name="ConnectionName"></param>
         ///   <returns></returns>
         public   static  String FillConnectionToJSON(String ConnectionName)
        {
            String strJSON = String.Empty;
            TreeView tree =  new  TreeView();
            FillConnectionToTreeView(tree);
             // Transform Treeview To JSON
             // 必须这样做,防止二重管理的问题。如果这里的逻辑有两套的话,维护起来比较麻烦。
             // 一套逻辑,来控制树的内容。然后将TreeView的内容转换为JSON。
             // 递归GetSubTreeNode
            strJSON = GetSubTreeNode(tree.Nodes[ 0 ]).ToJson(SystemManager.JsonWriterSettings);
             return  strJSON;
        }
         ///   <summary>
         ///  
         ///   </summary>
         ///   <param name="SubNode"></param>
         ///   <returns></returns>
         private   static  BsonDocument GetSubTreeNode(TreeNode SubNode)
        {
             if  (SubNode.Nodes.Count ==  0 )
            {
                BsonDocument SingleNode =  new  BsonDocument();
                SingleNode.Add( " name " , SubNode.Text);
                SingleNode.Add( " icon " ,  " MainTreeImage "  + String.Format( " {0:00} " ,SubNode.ImageIndex) +  " .png " );
                 return  SingleNode;
            }
             else
            {
                BsonDocument MultiNode =  new  BsonDocument();
                MultiNode.Add( " name " , SubNode.Text);
                BsonArray ChildrenList =  new  BsonArray();
                 foreach  (TreeNode item  in  SubNode.Nodes)
                {
                    ChildrenList.Add(GetSubTreeNode(item));
                }
                MultiNode.Add( " children " , ChildrenList);
                MultiNode.Add( " icon " ,  " MainTreeImage "  + String.Format( " {0:00} " , SubNode.ImageIndex) +  " .png " );
                 return  MultiNode;
            }
        }
         #endregion

复制代码

     原来的FillConnectionToTreeView(tree);是一个很庞大的方法,用来构建一个Treeview,里面存放着数据库的完整结构。

     这里我们将这个Treeview ,通过GetSubTreeNode 这个方法转换为了BsonDocument,然后直接使用内置方法转为JSON,一切搞定了。10来行代码,非常优雅。

    通过这个例子,我想说,作为程序员,一定要时刻注意,不要出现同样的代码,不要双重管理代码,不要改了一个地方,另一个地方也必须改动。

    明天去 埃森哲 入职,上海埃森哲的朋友,多多关照阿。。。。 

GitHub地址:  https://github.com/magicdict/MagicMongoDBTool

联系方式 mynightelfplayer@hotmail.com 

03 2012 档案

开源MongoDB管理工具MongoCola1.20 发布 离开IBM GDC的最后一个版本

摘要: 开源的MongoDB管理工具 MongoCola-1.20 正式发布了。虽然不敢说完全没有Bug,但是在我能力范围之内的,能改正的Bug都改正了。没有正规的测试团队,靠着零星的网友的帮忙,品质保证很难啊。下周开始去新公司上班了,由于种种原因,我要连续上9天的班,o(╯□╰)o。。。。这次新增的功能包括:(和1.13相比)1.Replset副本的初始化功能 通过工具,将任何一个普通的服务器提升为一个副本的Primary。2.副本服务器的管理: 通过工具,增加,移除副本服务器。3.Sharding的配置管理 增加Sharding,移除Sharding,配置Sharding数据库和数据集。4.... 阅读全文

posted @  2012-03-31 16:19  magicDict 阅读(1314) |  评论 (4)   编辑

MongoCola使用教程 2 - MongoDB的Replset 初始化和配置

摘要: 前言 首先再次感谢博客园的各位朋友。正是你们的关注才让我有信心将这个工具开发下去。这周同样也有热心网友对于MongoCola存在的问题给予了反馈。这次工具更新到了版本1.20,强化的地方是增加了Replset和Sharding的管理能力。MongoVUE和Mongocola以前在显示一个Replset或者Sharding的时候只是将Connection里面的内容,也就是Server的内容显示出来,而没有将Sharding的构造给显示出来,例如,Sharding可能是一个Replset,Replset里面可能有2台服务器。这个版本能够表示这些服务器的Instance的结构了。 当然这个版本还是无 阅读全文

posted @  2012-03-29 12:50  magicDict 阅读(614) |  评论 (0)   编辑

MongoCola使用教程 1 - MongoDB的基本操作和聚合功能

摘要: 前言 在开始正文之前,感谢博客园的Nosql爱好者对于MongoCola工具的试用(使用)。特别感谢 呆呆 这位朋友的Bug报告,让我纠正了一个很严重的Bug。同时也感谢以前的多个网友在博客留言中给我的意见,建议,以及BUG的修正方案。这个工具的进步离不开你们的贡献。最新版的MongoCola为1.13.主要改进了一些视觉效果上的东西,毕竟这个工具不是个人的工具了,在保证品质的前提下,也要考虑到美观和易用性了。如何得到MongoDB MongoDB是一个开源的项目,你可以从GitHub上获取MongoDB的源代码,当然对于大部分用户来说,我们并不需要源代码,直接下载可执行的文件即可。最新... 阅读全文

posted @  2012-03-22 11:00  magicDict 阅读(755) |  评论 (7)   编辑

MongoDB 可视化管理工具 MongoCola-1.1.0 测试版发布

摘要: 首先,感谢大家对于本工具的支持。 经过一周的努力,最新版的工具测试版出炉了,这个版本是一个很重要的版本。为什么说这个版本重要?以前的工具,只支持一个视图窗口,也就是说了,一次只能看一个数据集的数据。而从这个版本开始,支持多数据集了。你可以同时打开多个数据集,然后通过切换Tab来查看多个数据集的内容。当然,这个版本只是一个测试版,肯定有一些未知的BUG,同时在语言的汉化上还有一定的问题。好了,先来展示一些图片吧:原先的数据集没有经过分类,统一放在了数据库的节点下面,现在的数据集被分成了5个类别。1.USER 用户组 对应 system.users 这个数据集2.GFS 文件系统 对应 fs.f. 阅读全文

posted @  2012-03-16 13:20  magicDict 阅读(1134) |  评论 (13)   编辑

MongoDB 可视化管理工具 MongoCola-1.0.4发布

摘要: 随着NoSql的流行,MongoDB这款阶层型数据库慢慢被大家熟悉。园子里面的一线码农同志也在连载 8天学通MongoDB。 大家可能已经熟悉了图形界面的数据库管理工具,对于命令行可能不是很顺手。当然,有很多图形界面的MongoDB工具,不过大都不是用NET来写的,唯一的一款NET开发的MongoVUE不是开源软件。在30天试用期过后,很多功能就无法使用了。前段时间在学习MongoDB,所以用C#开发了一个MongoDB的可视化工具,已经在GitHub上开源了。GitHub地址:https://github.com/magicdict/MagicMongoDBTool现在版本已经升级到了1.0 阅读全文

posted @  2012-03-07 20:09  magicDict 阅读(919) |  评论 (5)   编辑

作者: Leo_wl

    

出处: http://www.cnblogs.com/Leo_wl/

    

本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

版权信息

查看更多关于如何从 Winform 移植到 Webform [自己搞定HTTP协议]的详细内容...

  阅读:56次