<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      XuGang

      記錄一個(gè)程序員的成長(zhǎng)

       

      使用C# 實(shí)現(xiàn)串口撥號(hào)器的SIM卡通信[修正版]

       

      在第一版 使用C# 實(shí)現(xiàn)串口撥號(hào)器的SIM卡通信 的代碼中,存在一些實(shí)際的問(wèn)題,經(jīng)過(guò)反復(fù)測(cè)試和實(shí)際使用,對(duì)原代碼進(jìn)行了一些改進(jìn)。

       

      首先,博客園的ㄟ荖樹炪厊ㄖ同學(xué)提出將撥號(hào)指令A(yù)TD發(fā)出后,不必使用 Thread.Sleep(20 * 1000) 方法等待20秒后進(jìn)行掛機(jī),而改用AutoResetEvent來(lái)處理,不必讓線程死等,也能提高你程序的性能。但修改后效果并不理想,還是使用Thread.Sleep(20 * 1000) 方法快捷實(shí)用。

       

      其次,由于撥號(hào)器以及服務(wù)器等硬件設(shè)備的差異,導(dǎo)致反饋信息的速度不一致,以前采用Thread.Sleep() 方法綁定固定秒數(shù)然后查看返回信息的方式存在一定的問(wèn)題,改用如下代碼就行:

      int i = 0;
      while (read.Trim() == "" && i <15)
      {
          Thread.Sleep(100);
          i++;
      }
      
      if (read.Contains("ATH") && read.Contains("OK"))
      {  ......  }

      其余的不詳細(xì)介紹,看代碼即可。

       

      MySerialPort 類

      對(duì)每一個(gè)連接到COM 串行端口的撥號(hào)器實(shí)例化 MySerialPort 對(duì)象,代碼如下:

      using System;
      using System.Collections.Generic;
      using System.Linq;
      using System.Text;
      using System.IO.Ports;
      using System.Threading;
      
      namespace Con_SerialPortExample
      {
      
          public class MySerialPort
          {
              private SerialPort com;
      
              public MySerialPort(string _portName)
              {
                  this.com = new SerialPort();
                  //this.autoResetEvent_HasModem = new AutoResetEvent(true);
                  //this.autoResetEvent_Dialing = new AutoResetEvent(false);
      
                  //接收數(shù)據(jù)事件
                  this.com.DataReceived += new SerialDataReceivedEventHandler(com_DataReceived);
                  //串口名
                  com.PortName = _portName;
                  this.PortName = _portName;
      
                  // BaudRate 串行波特率
                  com.BaudRate = 9600; //默認(rèn)值
      
                  // 是否啟用請(qǐng)求發(fā)送 (RTS) 信號(hào)。
                  com.RtsEnable = true; //由計(jì)算機(jī)發(fā)送   Request   To   Send   信號(hào)到聯(lián)接的調(diào)制解調(diào)器,以請(qǐng)示允許發(fā)送數(shù)據(jù)。
      
                  // 是否使Data Terminal Ready (DTR)線有效。  xugang 2012.8.20 添加
                  //com.DtrEnable = true; //Data   Terminal   Ready   是計(jì)算機(jī)發(fā)送到調(diào)制解調(diào)器的信號(hào),指示計(jì)算機(jī)在等待接受傳輸。 
      
                  try
                  {
                      com.Open();
                  }
                  catch //(Exception)
                  {
                      Close();
                  }
      
              }
      
              public MySerialPort(string _portName, int _baudRate)
                  : this(_portName)
              {
                  if (_baudRate != 0)
                  {
                      // BaudRate 串行波特率
                      com.BaudRate = _baudRate;
                  }
              }
      
      
              private string portName;
              //串口名稱
              public string PortName
              {
                  get { return portName; }
                  set { portName = value; }
              }
      
              // BaudRate 串行波特率
              public int BaudRate
              {
                  get { return com.BaudRate; }
                  set { com.BaudRate = value; }
              }
      
              private bool isWorking;
              //設(shè)置是否正在使用
              public bool IsWorking
              {
                  get { return isWorking; }
                  set { isWorking = value; }
              }
      
              //private enum AutoResetEvent_Type
              //{
              //   None, HasModem, Dialing
              //}
              //private AutoResetEvent autoResetEvent_HasModem;
              //private AutoResetEvent autoResetEvent_Dialing;
              //private AutoResetEvent_Type autoResetEvent_Type = AutoResetEvent_Type.None;
              //private bool enableUse;
              private DateTime lastUseTime = DateTime.MinValue;
              //當(dāng)前撥號(hào)器能否使用 (解決連續(xù)使用撥號(hào)問(wèn)題)
              public bool EnableUse
              {
                  get 
                  {
                      TimeSpan span = DateTime.Now - lastUseTime;
                      return span.TotalSeconds >= 60; 
                  }
                  //set { enableUse = value; }
              }
      
              // 檢測(cè)當(dāng)前端口是否安裝有撥號(hào)器
              public bool HasModem()
              {
                  //this.autoResetEvent_Type = AutoResetEvent_Type.HasModem;
      
                  //read = ""; //清空返回緩沖區(qū)
                  WriteSerial("AT\r\n");
                  //Thread.Sleep(500);
                  //this.autoResetEvent_HasModem.WaitOne(5 * 1000);
                  //this.autoResetEvent_Type = AutoResetEvent_Type.None;
      
                  int i = 0;
                  while (read.Trim() == "" && i < 40)
                  {
                      Thread.Sleep(100);
                      i++;
                  }
      
                  Console.WriteLine(read.TrimEnd('\r', '\n'));
                  //Console.Write(read);
      
                  //if (read.Contains("AT") && read.Contains("OK"))
                  if (read.Contains("OK"))
                  {
                      Console.WriteLine(this.com.PortName + "端口能使用!");
                      return true;
                  }
                  else
                  {
                      Console.WriteLine(this.com.PortName + "端口無(wú)法使用!");
                      return false;
                  }
      
              }
      
              //進(jìn)行撥號(hào),喚醒上位機(jī)
              public void Dialing(string _SIM)
              {
                  IsWorking = true; //正在撥號(hào)
                  try
                  {
                      //this.autoResetEvent_Type = AutoResetEvent_Type.Dialing;
      
                      read = ""; //清空返回緩沖區(qū)
      
                      StringBuilder sb = new StringBuilder(36);
                      sb.Append(this.com.PortName);
                      sb.Append("端口開始對(duì)SIM卡:");
                      sb.Append(_SIM);
                      sb.Append(" 進(jìn)行撥號(hào)...");
                      Console.WriteLine(sb.ToString());
      
                      WriteSerial(string.Format("ATD{0};\r\n", _SIM));
      
                      System.Threading.Thread.Sleep(20 * 1000);
                      //this.autoResetEvent_Dialing.WaitOne(20 * 1000);
                      //this.autoResetEvent_Type = AutoResetEvent_Type.None;
      
                      read = ""; //清空返回緩沖區(qū)
      
                      WriteSerial("ATH\r\n");
      
                      //this.autoResetEvent.WaitOne(1000);
      
                      int i = 0;
                      while (read.Trim() == "" && i <15)
                      {
                          Thread.Sleep(100);
                          i++;
                      }
                      Console.WriteLine(read);
      
                      if (read.Contains("ATH") && read.Contains("OK"))
                      {
                          Console.WriteLine(this.com.PortName + "端口撥號(hào)已完成!");
                      }
                      else
                      {
                          read = ""; //清空返回緩沖區(qū)
      
                          //System.Threading.Thread.Sleep(1000);
                          WriteSerial("ATH\r\n");
                          
                          //this.autoResetEvent.WaitOne(1000);
      
                          i = 0;
                          while (read.Trim() == "" && i < 20)
                          {
                              Thread.Sleep(100);
                              i++;
                          }
      
                          Console.WriteLine(read);
      
                          if (read.Contains("ATH") && read.Contains("OK"))
                          {
                              Console.WriteLine(this.com.PortName + "端口撥號(hào)已完成!");
                          }
                          else
                          {
                              //IsWorking = false; //撥號(hào)完成
      
                              string strExc = this.com.PortName + "撥號(hào)異常!";
                              Console.WriteLine(strExc);
      
                              throw new Exception(strExc);
                          }
                      }
                  }
                  catch (Exception ex)
                  {
                      throw ex;
                  }
                  finally
                  {
                      IsWorking = false; //撥號(hào)完成
                  }
              }
      
      
              /// <summary>
              /// 向串口端發(fā)送命令!
              /// </summary>
              /// <param name="s">命令字符串</param>
              private void WriteSerial(string s)
              {
                  //this.autoResetEvent_HasModem.WaitOne(20*1000);
      
                  //mLogger.Info(s);
      
                  byte[] buff = Encoding.ASCII.GetBytes(s);
                  try
                  {
                      this.com.Write(buff, 0, buff.Length);
                  }
                  catch (Exception ex)
                  {
                      //WriteExecLog.Writing(ex);
                      Console.WriteLine(ex.Message);
                  }
              }
      
              //int n = 0;
              string read = "";
              //接收數(shù)據(jù)事件方法
              void com_DataReceived(object sender, SerialDataReceivedEventArgs e)
              {
                  if (sender is SerialPort)
                  {
                      try
                      {
                          Thread.Sleep(500);
                          read = ""; //清空返回緩沖區(qū)
                          SerialPort mySerial = sender as SerialPort;
                          if (mySerial.IsOpen == false)
                          {
                              mySerial.Open();
                          }
      
                          //方法一
                          //read += mySerial.ReadLine().Trim();
                          //Console.WriteLine(mySerial.PortName + " 第" + n.ToString() + "接收數(shù)據(jù):" + read);
      
                          //方法二
                          byte[] readBuffer = new byte[1024];
                          int count = mySerial.Read(readBuffer, 0, 1023);
                          if (count > 0)
                          {
                              read = System.Text.Encoding.ASCII.GetString(readBuffer, 0, count);
                              //Console.WriteLine(read);
                          }
      
                          //AT 返回
                          //if (autoResetEvent_Type == AutoResetEvent_Type.HasModem
                          //    && read.Contains("OK"))
                          //{
                          //    this.autoResetEvent_HasModem.Set();
                          //}
      
                          //ATD 返回
                          //if (autoResetEvent_Type == AutoResetEvent_Type.Dialing
                          //    && (read.Contains("ERROR") || read.Contains("BUSY") || read.Contains("OK") || read.Contains("NO CARRIER"))
                          //    )
                          //{
                          //    this.autoResetEvent_Dialing.Set();
                          //}
      
                      }
                      catch (TimeoutException)
                      {
                          return;    //xg備忘:可以將異常寫入日志!
                      }
                      catch (Exception)
                      {
                          return;    //xg備忘:可以將異常寫入日志!
                      }
                      //finally
                      //{
                      //    this.autoResetEvent_HasModem.Set();
                      //}
                  }
              }
      
              //private string ReadSerial()
              //{
              //    while (_keepReading)
              //    {
              //        if (com.IsOpen)
              //        {
              //            //byte[] readBuffer = new byte[com.ReadBufferSize + 1];
              //            byte[] readBuffer = new byte[10];
              //            try
              //            {
              //                //int count = com.Read(readBuffer, 0, com.ReadBufferSize);
              //                int count = com.Read(readBuffer, 0, 9);
              //                String SerialIn = System.Text.Encoding.ASCII.GetString(readBuffer, 0, count);
              //                if (count != 0)
              //                {
              //                    return SerialIn;
              //                }
              //            }
              //            catch (TimeoutException) 
              //            {
              //                return "";
              //            }
              //        }
              //        else
              //        {
              //            TimeSpan waitTime = new TimeSpan(0, 0, 0, 0, 50);
              //            Thread.Sleep(waitTime);
              //        }
              //    }
      
              //    return "";
              //}
      
      
              //關(guān)閉
              public void Close()
              {
                  if (com != null)
                  {
                      com.Close();
                      com.Dispose();
                  }
              }
      
          }
      
      }

       

      SerialPortList 類

      定義一個(gè) SerialPortList 類,實(shí)現(xiàn)對(duì)所有連接上的撥號(hào)器 MySerialPort 對(duì)象進(jìn)行管理和調(diào)度使用。代碼如下:

      using System;
      using System.Collections.Generic;
      using System.Linq;
      using System.Text;
      using System.IO.Ports;
      using System.Threading;
      
      namespace Con_SerialPortExample
      {
      
          public class SerialPortList
          {
              //已經(jīng)安裝了撥號(hào)器的串口對(duì)象
              private List<MySerialPort> al = null;
              //可使用的撥號(hào)器個(gè)數(shù)
              public int WorkableCount
              {
                  get
                  {
                      if (al == null) return 0;
                      else return al.Count;
                  }
              }
      
              private Dictionary<string, int> portBaudRate = null;
              //波特率配置列表
              public Dictionary<string, int> PortBaudRate
              {
                  get { return portBaudRate; }
                  set { portBaudRate = value; }
              }
      
              private bool hasPort = false;
              //當(dāng)前有無(wú)可使用的串口撥號(hào)器
              public bool HasPort
              {
                  get { return hasPort; }
                  //set { hasPort = value; }
              }
      
              private int reCheckMinutes = 30; //默認(rèn)30分鐘
              //串口撥號(hào)器的重新檢測(cè)間隔分鐘
              public int ReCheckMinutes
              {
                  get { return reCheckMinutes; }
                  set { reCheckMinutes = value; }
              }
      
              #region  構(gòu)造方法重載
              public SerialPortList() { }
      
              public SerialPortList(Dictionary<string, int> _portBaudRate)
              {
                  this.portBaudRate = _portBaudRate;
              }
              public SerialPortList(int _reCheckMinutes)
              {
                  this.reCheckMinutes = _reCheckMinutes;
              }
              public SerialPortList(Dictionary<string, int> _portBaudRate, int _reCheckMinutes)
              {
                  this.portBaudRate = _portBaudRate;
                  this.reCheckMinutes = _reCheckMinutes;
              }
              #endregion  構(gòu)造方法重載
      
              /// <summary>
              ///  獲得串口上已經(jīng)安裝了撥號(hào)器的對(duì)象
              /// </summary>
              public void GetSerialPortList()
              {
                  al = new List<MySerialPort>();
      
                  //步驟一: 獲得所有的串口名稱(列表)
                  string[] ports = SerialPort.GetPortNames();
      
                  foreach (string port in ports)
                  {
                      MySerialPort mySerialPort = null;
      
                      Console.WriteLine("正在檢測(cè):" + port); //測(cè)試使用
      
                      //是否設(shè)置波特率?
                      if (portBaudRate != null
                          && portBaudRate.ContainsKey(port)
                          && portBaudRate[port] != 0)
                      {
                          mySerialPort = new MySerialPort(port, portBaudRate[port]);
                      }
                      else mySerialPort = new MySerialPort(port);
      
                      bool ok = mySerialPort.HasModem();
                      if (ok)
                      {
                          al.Add(mySerialPort);
                      }
                      else
                      {
                          mySerialPort.Close();
                          mySerialPort = null;
                      }
                  }
      
                  // 判斷當(dāng)前計(jì)算機(jī)有無(wú)可使用串口端
                  hasPort = al.Count <= 0 ? false : true;
              }
      
      
              /// <summary>
              /// 重新獲得串口上已經(jīng)安裝了撥號(hào)器的對(duì)象
              /// </summary>
              public void ReGetSerialPortList()
              {
                  if (al == null) GetSerialPortList();
                  else
                  {
                      //步驟一: 重新獲得所有的串口名稱(列表)
                      string[] portsName_2 = SerialPort.GetPortNames();
      
                      //如果當(dāng)前串口數(shù)目 > 正在使用的COM
                      if (portsName_2.Length > al.Count)
                      {
                          Console.WriteLine("正在重新檢測(cè)可以使用的撥號(hào)器!"); //測(cè)試使用
                          foreach (string pName_2 in portsName_2)
                          {
                              //當(dāng)前串口名是否存在撥號(hào)列表中
                              bool hasAt = al.Exists(delegate(MySerialPort port_1)
                              {
                                  return pName_2 == port_1.PortName;
                              });
      
                              //如果當(dāng)前串口名不存在撥號(hào)列表中,則重新檢測(cè)!
                              if (!hasAt)
                              {
                                  Console.WriteLine("正在重新檢測(cè):" + pName_2); //測(cè)試使用
      
                                  MySerialPort mySerialPort = null;
      
                                  //是否設(shè)置波特率?
                                  if (portBaudRate != null
                                      && portBaudRate.ContainsKey(pName_2)
                                      && portBaudRate[pName_2] != 0)
                                  {
                                      mySerialPort = new MySerialPort(pName_2, portBaudRate[pName_2]);
                                  }
                                  else mySerialPort = new MySerialPort(pName_2);
      
                                  bool ok = mySerialPort.HasModem();
                                  if (ok)
                                  {
                                      al.Add(mySerialPort);
                                  }
                                  else
                                  {
                                      mySerialPort.Close();
                                      mySerialPort = null;
                                  }
                              }
                          }
                      }
                  }
      
                  // 判斷當(dāng)前計(jì)算機(jī)有無(wú)可使用串口端
                  hasPort = al.Count <= 0 ? false : true;
              }
      
              /// <summary>
              /// 重新獲得串口上已經(jīng)安裝了撥號(hào)器的對(duì)象 (波特率使用默認(rèn)值)
              /// </summary>
              public void ReGetSerialPortList(int _reCheckMinutes)
              {
                  //串口撥號(hào)器的重新檢測(cè)間隔分鐘
                  reCheckMinutes = _reCheckMinutes;
      
                  ReGetSerialPortList();//波特率全部使用默認(rèn)值
              }
      
              /// <summary>
              /// 釋放所有串口資源組件
              /// </summary>
              public void ClearAllSerialPort()
              {
                  if (al != null)
                  {
                      for (int i = 0; i < al.Count; i++)
                      {
                          al[i].Close();
                          al[i] = null;
                      }
                      al = null;
                  }
      
                  if (portBaudRate != null)
                  {
                      portBaudRate = null;
                  }
              }
      
              private int index_Number = -1;
              //串口的調(diào)度號(hào)
              private int IndexNumber()
              {
      
                  lock (this)
                  {
                      if (index_Number + 1 >= al.Count)
                      {
                          if (al.Count == 0) index_Number = -1;
                          else index_Number = 0;
                      }
                      else
                      {
                          index_Number++;
                      }
      
                      return index_Number;
                  }
      
              }
      
              /// <summary>
              /// 對(duì)已經(jīng)安裝了撥號(hào)器的串口調(diào)度使用
              /// </summary>
              private void UseingSerialPort(string _SIM)
              {
                  if (al == null) return;
      
                  // 等待線程進(jìn)入 
                  Monitor.Enter(al);
      
                  MySerialPort getPort = null;
                  try
                  {
                      //獲得當(dāng)前調(diào)用的串口對(duì)象的索引號(hào)
                      int num = IndexNumber();
      
                      if (num >= 0) //判斷是否存在撥號(hào)器
                      {
                          getPort = al[num];
                          if (getPort != null && !getPort.IsWorking)
                          {
                              getPort.Dialing(_SIM); //對(duì) SIM 進(jìn)行撥號(hào),喚醒上位機(jī)
                          }
                      }
                      else
                      {
                          //沒有可使用的撥號(hào)器,則重新檢測(cè)。
                          this.ReGetSerialPortList();
                      }
                  }
                  catch
                  {
                      //再一次檢查該 COM 能否使用! (范工提議)
                      if (getPort != null)
                      {
                          string re_PortName = getPort.PortName;
                          al.Remove(getPort); //從可用列表去除
                          getPort.Close();
      
                          MySerialPort mySerialPort = new MySerialPort(re_PortName);
                          bool ok = mySerialPort.HasModem();
                          if (ok)
                          {
                              al.Add(mySerialPort); //重新添加到列表
                          }
                          else
                          {
                              mySerialPort.Close();
                              mySerialPort = null;
                          }
                      }
                  }
                  finally
                  {
                      // 通知其它對(duì)象
                      Monitor.Pulse(al);
                      // 釋放對(duì)象鎖 
                      Monitor.Exit(al);
                  }
              }
      
              //重新檢測(cè)端口時(shí)間
              private DateTime dtCheck = DateTime.Now;
      
              /// <summary>
              /// 調(diào)用撥號(hào)器
              /// </summary>
              /// <param name="_SIM"></param>
              public void InvokingSerialPort(string _SIM)
              {
                  if (hasPort == false)
                  {
                      // 獲得串口上已經(jīng)安裝了撥號(hào)器的對(duì)象
                      this.GetSerialPortList();
                  }
                  if (hasPort == true)
                  {
                      this.UseingSerialPort(_SIM);
                      //Thread.Sleep(5000);
                  }
      
                  //定期檢測(cè)串口列表
                  //if (dtCheck.AddMinutes(reCheckMinutes) <= DateTime.Now)
                  if (dtCheck.AddMinutes(5) <= DateTime.Now)
                  {
                      // 重新獲得串口上已經(jīng)安裝了撥號(hào)器的對(duì)象
                      this.ReGetSerialPortList();
                      dtCheck = DateTime.Now;
                  }
              }
      
          }
      
      }

       

      測(cè)試代碼如下:

      using System;
      using System.Collections.Generic;
      using System.Linq;
      using System.Text;
      //
      //using System.IO.Ports;
      using System.Threading;
      //using System.Collections;
      
      namespace Con_SerialPortExample
      {
          class Program
          {
              static void Main(string[] args)
              {
                  // 獲得串口上已經(jīng)安裝了撥號(hào)器的對(duì)象 (自定義波特率)
                  Dictionary<string, int> _portBaudRate = new Dictionary<string, int>();
                  _portBaudRate["COM1"] = 9600;
                  _portBaudRate["COM2"] = 9600;
                  _portBaudRate["COM7"] = 9600;
      
                  SerialPortList list = new SerialPortList(_portBaudRate,5);
      
                  try
                  {
                      // 獲得串口上已經(jīng)安裝了撥號(hào)器的對(duì)象
                      list.GetSerialPortList();
      
                      if (list.HasPort == false)
                      {
                          Console.WriteLine("當(dāng)前計(jì)算機(jī)無(wú)可使用的串口撥號(hào)器!");
                      }
      
                      while (list.HasPort)
                      {
                          // 調(diào)用撥號(hào)器
                          list.InvokingSerialPort("13500000000"); 
                          Thread.Sleep(5000);
                      }
      
                      Console.WriteLine("程序運(yùn)行結(jié)束!");
                  }
                  finally
                  {
                      // 釋放所有串口資源組件
                      list.ClearAllSerialPort();
                  }
      
                  Console.ReadLine();
              }
          }
      }

       

      posted on 2012-09-19 16:06  鋼鋼  閱讀(1785)  評(píng)論(7)    收藏  舉報(bào)

      導(dǎo)航

      主站蜘蛛池模板: 少妇高潮喷水正在播放| 日韩大片一区二区三区| 洱源县| 国产 一区二区三区视频| 日韩人妻少妇一区二区三区| 人妻少妇不满足中文字幕| 亚洲欧美人成人综合在线播放 | 国产在线亚州精品内射| 色多多性虎精品无码av| 干老熟女干老穴干老女人| 久视频久免费视频久免费| 亚洲熟妇自偷自拍另欧美| 55大东北熟女啪啪嗷嗷叫| 国产欧美日韩精品第二区| 中文亚洲成A人片在线观看| 亚洲成人av免费一区| 久久久无码精品亚洲日韩蜜臀浪潮| 国产精品自在欧美一区| 狠狠色综合久久丁香婷婷| 亚日韩精品一区二区三区| 蜜桃视频一区二区在线观看| 牛牛视频一区二区三区| 中文字幕99国产精品| 日韩有码国产精品一区| 国产成人精品午夜2022| 视频一区视频二区在线视频| 日韩乱码视频一区二区三区| 免费午夜无码片在线观看影院 | 国产精品高清一区二区三区| 人妻在线中文字幕| 免费国产精品黄色一区二区| 亚洲欧美综合中文| 黄色免费在线网址| 国产一区二区精品偷系列| L日韩欧美看国产日韩欧美| 国产免费又黄又爽又色毛| 91一区二区三区蜜桃臀| 无码成人一区二区三区| 免费午夜无码片在线观看影院| 国产午夜福利视频第三区| 蜜桃av多人一区二区三区|