zoukankan      html  css  js  c++  java
  • RFID会议签到系统总结(十)――客户端通讯组件

     

    上一篇Socket封装只是一个技术的封装,是为了隐藏一些技术细节,这一篇主要是通讯组件的逻辑封装。

    这里基本没有什么可谈的,只是到处调用上一篇里的方法而已。比如读取配置连接远程主机啦,关闭Socket连接啦,组合字符串发送命令啦等。

    这个地方最费事的是SocketPackOnReceive事件的处理,这个事件在Socket接收到远程主机的命令时会触发。

           private void winsock_OnReceive(object sender, ComReceiveEventArgs e) {

               try

               {

                  string msg = e.ComData;

     

                  logNetForInfo.Info("From [" + Host + "] Data:" + msg);

     

                  int commandEndIndex = 0;

                  int dataEndIndex = 0;

                  int oldDataIndex = 0;

                  string command = "";

                  string data = "";

     

                  while(true)

                  {  

                      #region 解析指令与数据部分

                      commandEndIndex = msg.IndexOf(CommandConst.COMMANDTOKEN,dataEndIndex);

                      if (commandEndIndex < 0) break;

                      oldDataIndex = dataEndIndex;

                      dataEndIndex = msg.IndexOf(CommandConst.DATATOKEN,commandEndIndex);

                      if (dataEndIndex < 0) break;

     

                      if (oldDataIndex == 0)

                         command = msg.Substring(0,commandEndIndex);

                      else

                         command = msg.Substring(oldDataIndex + CommandConst.DATATOKENLENGTH,commandEndIndex - oldDataIndex - CommandConst.DATATOKENLENGTH);

     

                      data = msg.Substring(commandEndIndex + CommandConst.COMMANDTOKENLENGTH,dataEndIndex - commandEndIndex - CommandConst.COMMANDTOKENLENGTH);

                      #endregion

     

                      ProcessData(command,data);

                  }

     

     

               }

               catch(Exception ex)

               {

                  logNet.Error(" [" + Host + "]读取数据时发生错误:" + ex.Message);

               }

           }

    上面没什么可以特别一书的东西,就是字符串运算,很笨的方法。然后下面处理解析得的数据

           private void ProcessData(string command,string data)

           {

               #region 根据不同指令触发不同事件

               switch(command)

               {

                  case CommandConst.BEGINSIGNIN://开始签到

                      if (BeginSignInEvent != null)

                         ThreadingEvent.Invoke(BeginSignInEvent,new object[]{this,new BeginSignInEventArgs(true)});

                      break;

                  //......

                  //............

                  //......

                  case CommandConst.DOWNLOADDB://下载数据库

                      if (DownLoadDBEvent != null)

                          DownLoadDBEvent.BeginInvoke(this,System.EventArgs.Empty,new AsyncCallback(DownLoadDBResult),null);

                      break;

                  default:

                      if (DataReceive != null)//其他命令

                         ThreadingEvent.Invoke(DataReceive,new object[]{this,new ComReceiveEventArgs(data)});

                      break;

               }

               #endregion

           }

     

    我们注意到上头事件的触发有时没有用通常的写法,而是用ThreadingEvent.Invoke。因为在.net里在辅助线程上是无法执行方法来修改窗体UI的,要修改UI只能在窗体自身的线程上执行。由于系统中运用的一些组件多是在各个不同的线程中运行,甚至组件本身运行在很多的线程上,这其中有很多事件都涉及到UI的改变。而按我们通常的写法,那些事件代码都将会在触发这个事件的线程里执行,那样的话无法改变UI。所以写了个事件触发的通用写法,只要有可能涉及到修改UI的事件都通用它来触发。

          public sealed class ThreadingEvent

          {

                 public static void Invoke(Delegate eventDelegate,object[] param)

                 {

                        Control ctr = eventDelegate.Target as Control;

                        if (ctr != null)

                        {

                               if (ctr.IsHandleCreated)

                                      ctr.Invoke(eventDelegate,param);

                        }

                        else

                               eventDelegate.DynamicInvoke(param);

                 }

          }

    有点不完善的地方,没有再写一个用于异步调用的方法,因为在else这个条件时,Delegate的异步调用不知该怎么写。不过还好现在看来那些同步触发的事件也没造成系统的什么大问题,所以就这样将就用了。

     

    最后不要忘了,还有一个Socket连接可用性的监测,如果有变化,还记得要向外部触发事件,这个比较简单,就不去讲述了。

  • 相关阅读:
    Apache 虚拟主机 VirtualHost 配置
    EAX、ECX、EDX、EBX寄存器的作用
    Python中文文档 目录(转载)
    八度
    POJ 3268 Silver Cow Party (最短路)
    POJ 2253 Frogger (求每条路径中最大值的最小值,Dijkstra变形)
    2013金山西山居创意游戏程序挑战赛——复赛(1) HDU 4557 非诚勿扰 HDU 4558 剑侠情缘 HDU 4559 涂色游戏 HDU 4560 我是歌手
    HDU 4549 M斐波那契数列(矩阵快速幂+欧拉定理)
    UVA 11624 Fire! (简单图论基础)
    HDU 3534 Tree (树形DP)
  • 原文地址:https://www.cnblogs.com/lichdr/p/797932.html
Copyright © 2011-2022 走看看