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 = "\r\n";
 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" + "\r";//注意".L "中是有空格的 19 } 20 else 21 { 22 RD = "WR MR" + "9100" + ".L " + "1" + "\r";//注意".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 }