• 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连接可用性的监测,如果有变化,还记得要向外部触发事件,这个比较简单,就不去讲述了。

  • 相关阅读:
    vim删除某一列
    linux下在当前文件夹查找一个字符串信息
    .tar和.tar.gz的区别
    visual studio中调用masm汇编
    iconv转码失败的原因
    终端查看
    kubectl 常用命令总结
    Charles实战之Charles抓取https请求
    Fiddler实战之拟2G、3G、4G网络进行弱网测试
    Fiddler实战之使用Fiddler模拟弱网环境
  • 原文地址:https://www.cnblogs.com/lichdr/p/797932.html
Copyright © 2020-2023  润新知