• c#winform TCP/IP异步 包括心跳检测。


    client类

      1 using System;
      2 using System.Collections.Generic;
      3 using System.Linq;
      4 using System.Text;
      5 using System.Threading.Tasks;
      6 using System.Net.Sockets;
      7 using System.Threading;
      8 using System.Net;
      9 using System.Windows.Forms; 11 namespace SocketClientTest
     12 {
     13     public class SocketClient
     14     {
     15         public event Action<string> EventReceive;
     16         public event Func< string,bool > EventSend;  
     17         public event Action<string> EventconnectState; //1:链接  0:断开
     18         public Socket NewScocket = null;
     19         byte[] byteBuffer = new byte[512];
     20         string beginMsg = string.Empty;
     21         public int isconnect = 0; //0未连接 1成功 2连接失败 3plc断开
     22         //string endMsg = "
    ";
     23         Log log = new Log();
     24         public SocketClient()
     25         {
     26             EventSend += Send;
     27 
     28             System.Windows.Forms.Timer nTime = new System.Windows.Forms.Timer();
     29             nTime.Interval = 500;
     30             nTime.Tick += NTime_Tick;
     31             nTime.Enabled = true;
     32         }
     33 
     34         private void NTime_Tick(object sender, EventArgs e)
     35         {
     36             if (NewScocket!=null&& NewScocket.Connected)
     37             {
     38                 if (EventconnectState != null)
     39                 {
     40                     EventconnectState("1");
     41                 }
     42             }
     43             else
     44             {
     45                 if (EventconnectState != null)
     46                 {
     47                     EventconnectState("0");
     48                 }
     49             }
     50         }
     51 
     52         public bool Connect(string ip,int port)
     53         {
     54             try
     55             {
     56                 if (NewScocket != null && NewScocket.Connected) //只有一个client
     57                 {
     58                     Close(NewScocket);
     59                 }
     60                 NewScocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
     61                 NewScocket.Blocking = false;
     62                 IPEndPoint ipe = new IPEndPoint(IPAddress.Parse(ip), port);
     63                 //绑定  异步链接
     64                 NewScocket.BeginConnect(ipe, new AsyncCallback(OnConnectRequest), NewScocket);
     65                 return true;           
     66             }
     67             catch (Exception)
     68             {
     69                 log.WriteLog("链接异常");
     70                 MessageBox.Show("链接异常", "链接提示");
     71                 return false;
     72             }
     73         }
     74 
     75         private void OnConnectRequest(IAsyncResult ar)
     76         {
     77             //获取链接状态
     78            Socket _Socket = (Socket)ar.AsyncState;//
     79             try
     80             {
     81                 //判断链接是否成功
     82                 if (_Socket.Connected)
     83                 {                    
     84                     SetReceiveCallback(_Socket);
     85                    // MessageBox.Show("链接成功");
     86                     //log.WriteLog("链接成功");
     87                     isconnect = 1;
     88                     //if (EventconnectState!=null)
     89                     //{
     90                     //    EventconnectState("1");
     91                     //}
     92                 }
     93                 else
     94                 {
     95                     log.WriteLog("链接失败,请检查网线");
     96                     MessageBox.Show("链接失败,请检查网线", "链接提示");
     97                     isconnect = 2;
     98 
     99                 }
    100             }
    101             catch (Exception)
    102             {
    103                 log.WriteLog("链接异常");
    104                 MessageBox.Show("链接异常", "链接提示");
    105                 isconnect = 2;
    106 
    107             }
    108         }
    109 
    110         /// <summary>
    111         /// 回调法法
    112         /// </summary>
    113         private void SetReceiveCallback(Socket _Sock)
    114         {
    115             AsyncCallback receive = new AsyncCallback(OnReceiveData);
    116             _Sock.BeginReceive(byteBuffer, 0, byteBuffer.Length, SocketFlags.None, OnReceiveData, _Sock);
    117         }
    118 
    119         /// <summary>
    120         /// 接受数据
    121         /// </summary>
    122         /// <param name="ar"></param>
    123         private void OnReceiveData(IAsyncResult ar)
    124          {
    125             Socket _Sock = (Socket)ar.AsyncState;
    126             try
    127             {
    128                 int receiveLengthData = _Sock.EndReceive(ar);
    129                 //大于0接受到报文数据
    130                 if (receiveLengthData > 0)
    131                 {
    132                     // if (m_ByteBuffer[0]==0)
    133                     //接受到的数据
    134                     string receiveMsg = Encoding.UTF8.GetString(byteBuffer, 0, receiveLengthData);
    135                     //传值
    136                     if (EventReceive!=null)
    137                     {
    138                         EventReceive(receiveMsg);
    139                     }
    140                     //重复调用
    141                     SetReceiveCallback(_Sock);
    142                 }
    143                 else
    144                 {
    145                     //光闭Socket
    146                     MessageBox.Show("plc已关闭");
    147                     isconnect = 3;
    148                     Close(_Sock);
    149                 }
    150             }
    151             catch (Exception )
    152             {
    153             }
    154         }
    155 
    156         /// <summary>
    157         /// 发送数据
    158         /// </summary>
    159         public  bool  Send(string str)//字符串转字节发送
    160         {
    161             //把字符转换字节
    162             byte[] _ByteSend = Encoding.UTF8.GetBytes(str);
    163             //发送数据
    164             try
    165             {
    166                 NewScocket.Send(_ByteSend, _ByteSend.Length, 0);
    167                 //if (EventReceive != null)
    168                 //{
    169                 //    EventReceive.Invoke("客户端:"+str);
    170                 //}
    171                 return true;
    172             }
    173             catch (Exception)
    174             {
    175                 return false;
    176             }
    177             
    178         }
    179 
    180 
    181         public bool strToHexByte(string hexString)//字符串转成16进制发送
    182         {
    183           
    184           hexString = hexString.Replace(" ", "");
    185           if ((hexString.Length % 2) != 0)
    186                hexString += " ";
    187           byte[] returnBytes = new byte[hexString.Length / 2];
    188           for (int i = 0; i < returnBytes.Length; i++)
    189                 //转字节发送
    190           returnBytes[i] = Convert.ToByte(hexString.Substring(i * 2, 2).Replace(" ", ""), 10);//十进制
    191 
    192             //转字发送
    193             byte[] bytes = new byte[12];
    194             // UInt16 a = 54543;
    195             for (int j = 0; j < returnBytes.Length; j++)
    196             {
    197                 byte[] tempbyte = new byte[2];
    198                 tempbyte = BitConverter.GetBytes(returnBytes[j]);
    199                 bytes[j * 2] = tempbyte[1];
    200                 bytes[j * 2 + 1] = tempbyte[0];
    201             }
    202             try
    203             {
    204                 NewScocket.Send(bytes, bytes.Length, 0);
    205                 //if (EventReceive != null)//客户端发送后单纯的只是为了显示再客户端的界面上而已
    206                 //{
    207                 //    EventReceive.Invoke("客户端:" + hexString);//客户端发送的数据
    208                 //    //EventReceive.Invoke(hexString);
    209                 //}
    210                 return true;
    211             }
    212             catch (Exception)
    213             {
    214                 return false;
    215             }                       
    216         }
    217 
    218         public bool SendDM(string str)//字符串转字节发送 
    219         {
    220             //把字符转换字节
    221             byte[] _ByteSend = Encoding.ASCII.GetBytes(str);
    222             //发送数据
    223             try
    224             {
    225                 NewScocket.Send(_ByteSend, _ByteSend.Length, 0);
    226                 //if (EventReceive != null)
    227                 //{
    228                 //    EventReceive.Invoke("客户端:"+str);
    229                 //}
    230                 return true;
    231             }
    232             catch (Exception)
    233             {
    234                 return false;
    235             }
    236 
    237         }
    238 
    239         /// <summary>
    240         /// 关闭Sockte
    241         /// </summary>
    242         /// <param name="sockte"></param>
    243         public void Close(Socket socket)
    244         {
    245             if(socket != null&& socket.Connected)
    246             {
    247                 socket.Shutdown(SocketShutdown.Both);
    248                 Thread.Sleep(10);
    249                 socket.Close();
    250             }           
    251         }
    252     }
    253 }

    Form1.C

     
      1  //全局变量
            SocketClient ks = new SocketClient(); //一个通讯 2 SocketClient keep_heart = new SocketClient(); //一个发送心跳包 3 string ip = "127.0.0.1"; 4 int port = 9000; 5 int heart_port = 8501; 6 private void Form1_Load(object sender, EventArgs e) 7 {
              ks.EventReceive += ReceiveText;
    8 Thread thread1 = new Thread(() => //发送心跳 9 { 10 int i = 0; 11 while (true) 12 { 13 if (keep_heart.NewScocket!=null&&keep_heart.NewScocket.Connected) 14 { 15 string RD = null; 16 if (i % 2 == 0) 17 { 18 RD = "WR MR" + "9100" + ".L " + "0" + " ";//注意".L "中是有空格的 19 } 20 else 21 { 22 RD = "WR MR" + "9100" + ".L " + "1" + " ";//注意".L "中是有空格的 23 } 24 keep_heart.SendDM(RD); 25 } 26 i++; 27 Thread.Sleep(500); 28 } 29 }); 30 thread1.Start(); 31 Thread judge_state = new Thread(() => //判断是否关闭 32 { 33 while (true) 34 { 35 if (ks.isconnect == 3) 36 { 37 this.BeginInvoke(new MethodInvoker(() => 38 { 39 textBox3.Text = "断开"; 40 textBox3.BackColor = Color.Yellow; 41 btn_start.Enabled = true; 42 })); 43 ks.Close(ks.NewScocket); 44 keep_heart.Close(keep_heart.NewScocket); 45 display_log("plc已断开"); 46 } 47 Thread.Sleep(500); 48 } 49 50 }); 51 judge_state.Start(); 52 judge_state.IsBackground = true; 53 } 54 private void btn_start_Click(object sender, EventArgs e) 55 { 56 if (stastuLine)//在线模式 57 { //连接PLC 69 ks.Connect(ip, port); 70 while(ks.isconnect==0||ks.isconnect==3) 71 { 72 Thread.Sleep(50); 73 } 74 if (ks.isconnect == 1) 75 { 76 lab_plcStatu.Text = "在线"; 77 lab_plcStatu.ForeColor = Color.Green; 78 textBox3.Text = "连接"; 79 textBox3.BackColor = Color.Green; 80 81 MessageBox.Show("连接PLC成功", "温馨提示"); 82 display_log("plc连接成功"); 83 btn_start.Enabled = false; 84 ks.isconnect = 0; 85 86 //plc链接成功后,再判断心跳 87 keep_heart.Connect(ip, heart_port); 88 while(keep_heart.isconnect==0||keep_heart.isconnect==3) 89 { 90 Thread.Sleep(50); 91 } 92 if (keep_heart.isconnect == 1) 93 { 94 display_log("plc心跳连接成功"); 95 keep_heart.isconnect = 0; 96 97 } 98 else if (keep_heart.isconnect == 2) 99 { 100 display_log("plc心跳连接失败"); 101 MessageBox.Show("plc心跳连接失败", "温馨提示"); 102 } 103 104 } 105 else if(ks.isconnect == 2) 106 { 107 lab_plcStatu.Text = "离线"; 108 lab_plcStatu.ForeColor = Color.Black; 109 textBox3.Text = "断开"; 110 textBox3.BackColor = Color.Yellow; 111 log.WriteLog("连接PLC失败"); 112 display_log("连接plc失败"); 113 MessageBox.Show("连接PLC失败", "温馨提示"); 114 ks.isconnect = 0; 115 } 116 #endregion 117 } 118 } 119 138 139 public void ReceiveText(string s)//接收函数 140 { 141 142 if (s == "1111")//如果收到1111信号,进行处理 143 { 144 145 } 146 if (ks.Send(“”))//发送数据 147 { 148 } 149 else 150 { 151 } 152 153 }
  • 相关阅读:
    HTML技巧篇:如何让单行文本以及多行文本溢出时显示省略号(…)
    SpringMVC中响应json数据(异步传送)
    如何用Spring框架的<form:form>标签实现REST风格的增删改查操作
    如何使用REST请求风格
    Spring插件的安装与卸载---笔记
    元素 "context:component-scan" 的前缀 "context" 未绑定的解决方案
    简单的文件上传的下载(动态web项目)
    用简单的反射优化代码(动态web项目)
    json数据与Gson工具类的使用
    JSON简介
  • 原文地址:https://www.cnblogs.com/sclu/p/13066247.html
Copyright © 2020-2023  润新知