TCPIP通信
最近在开发TCPIP通信,封装了3个类,望各位大神指点指点。
1 using System; 2 using System.Collections.Generic; 3 using System.Text; 4 using System.Net.Sockets; 5 using System.Threading; 6 using System.Net; 7 using System.Linq; 8 using System.Net.NetworkInformation; 9 10 namespace HY_RFID 11 { 12 public class MyTCPServer 13 { 14 public bool isExit = false; 15 private TcpListener listener; 16 public TcpClient readClient; 17 List<ReadWriteObject> rws = new List<ReadWriteObject>(); 18 public List<TCPIP> ips = new List<TCPIP>(); 19 20 #region 创建事件 21 //声明事件参数 22 public class TcpClientArgs : EventArgs 23 { 24 public readonly TcpClient client; 25 public TcpClientArgs(TcpClient client) 26 { 27 this.client = client; 28 } 29 } 30 public class BackMsgArgs : EventArgs 31 { 32 public readonly string backMsg; 33 public BackMsgArgs(string backMsg) 34 { 35 this.backMsg = backMsg; 36 } 37 } 38 public class BackByteArgs : EventArgs 39 { 40 public readonly byte[] backByte; 41 public BackByteArgs(byte[] backByte) 42 { 43 this.backByte = backByte; 44 } 45 } 46 public delegate void WaitConnectEventHandler(object sender,EventArgs e); 47 public event WaitConnectEventHandler OnWaitConnect; 48 protected virtual void WaitConnect() 49 { 50 if (OnWaitConnect != null)// 如果有对象注册 51 { 52 OnWaitConnect(this, null);// 调用所有注册对象的方法 53 } 54 } 55 //声明委托 56 public delegate void SuccessConnectEventHandler(object sender, TcpClientArgs e); 57 //声明事件 58 public event SuccessConnectEventHandler OnSuccessConnect; 59 //触发方法 60 protected virtual void SuccessConnect(TcpClientArgs e) 61 { 62 if (OnSuccessConnect != null)// 如果有对象注册 63 { 64 OnSuccessConnect(this, e);// 调用所有注册对象的方法 65 } 66 } 67 public delegate void ReadCallBackMsgEventHandler(object sender, BackByteArgs e); 68 public event ReadCallBackMsgEventHandler OnReadCallBack; 69 protected virtual void ReadCallBackMsg(BackByteArgs e) 70 { 71 if (OnReadCallBack != null)// 如果有对象注册 72 { 73 OnReadCallBack(this, e);// 调用所有注册对象的方法 74 } 75 } 76 public delegate void ReadErrorCallBackMsgEventHandler(object sender, BackMsgArgs e); 77 public event ReadErrorCallBackMsgEventHandler OnReadErrorCallBack; 78 protected virtual void ReadErrorCallBackMsg(BackMsgArgs e) 79 { 80 if (OnReadErrorCallBack != null)// 如果有对象注册 81 { 82 OnReadErrorCallBack(this, e);// 调用所有注册对象的方法 83 } 84 } 85 #endregion 86 87 //用于线程同步,初始状态设为非终止状态,使用手动重置方式 88 private EventWaitHandle allDone = new EventWaitHandle(false, EventResetMode.ManualReset); 89 //服务端监听方法 90 public void ServerListen(int port) 91 { 92 //由于服务器要为多个客户服务,所以需要创建一个线程监听客户端连接请求 93 isExit = false; 94 if (!PortInUse(port)) 95 { 96 Thread myThread = new Thread(new ParameterizedThreadStart(AcceptConnect)); 97 myThread.Start(port); 98 } 99 else 100 { 101 throw new Exception("当前端口已被占用!"); 102 } 103 } 104 /// <summary> 105 /// 检测但钱端口是否被占用 106 /// </summary> 107 /// <param name="port"></param> 108 /// <returns></returns> 109 private bool PortInUse(int port) 110 { 111 bool inUse = false; 112 //获取所有的监听连接 113 IPGlobalProperties ipProperties = IPGlobalProperties.GetIPGlobalProperties(); 114 IPEndPoint[] ipEndPoints = ipProperties.GetActiveTcpListeners(); 115 foreach (IPEndPoint endPoint in ipEndPoints) 116 { 117 if (endPoint.Port == port) 118 { 119 inUse = true; 120 break; 121 } 122 } 123 return inUse; 124 } 125 //与客户机取得连接 126 private void AcceptConnect(object o) 127 { 128 try 129 { 130 if (o == null) return; 131 IPAddress ip4 = GetLocalIpv4() as IPAddress; 132 listener = new TcpListener(ip4, Convert.ToInt32(o)); 133 listener.Start(); 134 //引用在异步操作完成时调用的回调方法 135 AsyncCallback callback = new AsyncCallback(AcceptTcpClientCallback); 136 while (!isExit) 137 { 138 139 //将事件的状态设为非终止 140 allDone.Reset(); 141 //触发等待事件 142 WaitConnect(); 143 //开始一个异步操作接受传入的连接尝试 144 listener.BeginAcceptTcpClient(callback, listener); 145 //阻塞当前线程,直到收到客户连接信号 146 allDone.WaitOne(); 147 Thread.Sleep(100); 148 } 149 } 150 catch (Exception ex) 151 { 152 throw ex; 153 } 154 } 155 //获取本机IP 156 public object GetLocalIpv4() 157 { 158 //获取本机所有IP地址 159 try 160 { 161 IPAddress[] localips = Dns.GetHostAddresses(Dns.GetHostName()); 162 foreach (IPAddress ip in localips) 163 { 164 //找到本地所有IP地址符合IPV4协议的IP地址 165 if (ip.AddressFamily == AddressFamily.InterNetwork) 166 { 167 return ip; 168 } 169 } 170 } 171 catch (Exception ex) 172 { 173 throw ex; 174 } 175 return null; 176 } 177 // 连接客户端的回调函数 178 //ar是IAsyncResult类型的接口,表示异步操作的状态是由listener.BeginAcceptTcpClient(callback, listener)传递过来的 179 private void AcceptTcpClientCallback(IAsyncResult ar) 180 { 181 lock (this) 182 { 183 try 184 { 185 if (isExit) return; 186 //将事件状态设为终止状态,允许一个或多个等待线程继续 187 allDone.Set(); 188 TcpListener myListener = (TcpListener)ar.AsyncState; 189 //异步接收传入的连接,并创建新的TcpClient对象处理远程主机通信 190 TcpClient client = myListener.EndAcceptTcpClient(ar); 191 //已接受客户连接 192 TcpClientArgs e = new TcpClientArgs(client); 193 ReadWriteObject readWriteObject = new ReadWriteObject(client); 194 rws.Add(readWriteObject); 195 string[] strs=client.Client.RemoteEndPoint.ToString().Split(':'); 196 ips.RemoveAll(c => c.TargetIP == strs[0]); 197 ips.Add(new TCPIP(strs[0], strs[1], DateTime.Now)); 198 //触发客户端连接成功事件 199 SuccessConnect(e); 200 readWriteObject.netStream.BeginRead(readWriteObject.readBytes, 0, readWriteObject.readBytes.Length, ReadCallback, readWriteObject); 201 } 202 catch (Exception ex) 203 { 204 throw ex; 205 } 206 } 207 } 208 private void ReadCallback(IAsyncResult ar) 209 { 210 try 211 { 212 ReadWriteObject readWriteObject = (ReadWriteObject)ar.AsyncState; 213 readClient=readWriteObject.client; 214 if (readClient.Client.Poll(10, SelectMode.SelectRead) && (readClient.Client.Available == 0) | readClient.Client.Connected) 215 { 216 throw new Exception(readWriteObject.client.Client.RemoteEndPoint + "【断开】"); 217 } 218 int length = readWriteObject.netStream.EndRead(ar); 219 if (length == 0) return; 220 List<byte> _byteData = new List<byte>(); 221 for (int i = 0; i < length; i++) 222 { 223 _byteData.Add(readWriteObject.readBytes[i]); 224 } 225 ReadCallBackMsg(new BackByteArgs(_byteData.ToArray())); 226 if (isExit == false) 227 { 228 readWriteObject.InitReadArray(); 229 readWriteObject.netStream.BeginRead(readWriteObject.readBytes, 0, readWriteObject.readBytes.Length, ReadCallback, readWriteObject); 230 } 231 } 232 catch (Exception ex) 233 { 234 ReadErrorCallBackMsg(new BackMsgArgs(ex.Message)); 235 } 236 } 237 public void SendString(string remoteEndPoint, string str) 238 { 239 try 240 { 241 ReadWriteObject readWriteObject = rws.Where(c => c.client.Client.RemoteEndPoint.ToString() == remoteEndPoint).FirstOrDefault(); 242 if (readWriteObject.client.Client.Poll(10, SelectMode.SelectRead) && (readWriteObject.client.Client.Available == 0) || !readWriteObject.client.Client.Connected) 243 { 244 throw new Exception(remoteEndPoint + "【断开】"); 245 } 246 if (readWriteObject != null) 247 { 248 readWriteObject.write = MyHelper.HexToByte(str); 249 readWriteObject.netStream.BeginWrite(readWriteObject.write, 0, readWriteObject.write.Length, new AsyncCallback(SendCallBack), readWriteObject); 250 readWriteObject.netStream.Flush(); 251 252 } 253 } 254 catch (Exception ex) 255 { 256 throw ex; 257 } 258 } 259 private void SendCallBack(IAsyncResult ar) 260 { 261 ReadWriteObject readWriteObject = (ReadWriteObject)ar.AsyncState; 262 try 263 { 264 readWriteObject.netStream.EndWrite(ar); 265 } 266 catch (Exception ex) 267 { 268 throw ex; 269 } 270 } 271 /// <summary> 272 /// 停止服务 273 /// </summary> 274 public void StopServer() 275 { 276 isExit = true; 277 allDone.Set(); 278 if (listener != null) 279 listener.Stop(); 280 } 281 } 282 }
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Net.Sockets; using System.Net; using System.Threading; namespace HY_RFID { public class MyTcpClient { #region 创建事件 public class RecMsgArgs : EventArgs { public readonly string recMsg; public RecMsgArgs(string recMsg) { this.recMsg = recMsg; } } public class RecErrArgs : EventArgs { public readonly string recErr; public RecErrArgs(string recErr) { this.recErr = recErr; } } public delegate void ReceivedMsgEventHandler(object sender, RecMsgArgs e); public event ReceivedMsgEventHandler OnReceived; protected virtual void ReceivedMsg(RecMsgArgs e) { if (OnReceived != null)// 如果有对象注册 { OnReceived(this, e);// 调用所有注册对象的方法 } } public delegate void ReceivedErrorEventHandler(object sender, RecErrArgs e); public event ReceivedErrorEventHandler OnReceivedErr; protected virtual void ReceivedError(RecErrArgs e) { if (OnReceivedErr != null)// 如果有对象注册 { OnReceivedErr(this, e);// 调用所有注册对象的方法 } } #endregion private bool isExit; private Socket socketClient = null; //连接服务端方法 public void ClientConnect(string IP, string Port) { isExit = false; //定义一个套字节监听 包含3个参数(IP4寻址协议,流式连接,TCP协议) socketClient = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); //需要获取文本框中的IP地址 IPAddress ipaddress = IPAddress.Parse(IP); //将获取的ip地址和端口号绑定到网络节点endpoint上 IPEndPoint endpoint = new IPEndPoint(ipaddress, int.Parse(Port)); //这里客户端套接字连接到网络节点(服务端)用的方法是Connect 而不是Bind socketClient.Connect(endpoint); //创建一个线程 用于监听服务端发来的消息 Thread threadClient = new Thread(RecMsg); //将窗体线程设置为与后台同步 threadClient.IsBackground = true; //启动线程 threadClient.Start(); } // 发送节目全屏byte串信息到服务端的方法 public void ClientSendMsg(string msg) { try { if (socketClient.Poll(10, SelectMode.SelectRead) && (socketClient.Available == 0) || !socketClient.Connected) { throw new Exception(socketClient.RemoteEndPoint + "已断开!"); } Byte[] data = System.Text.Encoding.Default.GetBytes(msg); socketClient.Send(data, data.Length, SocketFlags.None);//发送信息 } catch(Exception ex) { throw ex; } } //接收服务端发来信息的方法 public void RecMsg() { while (!isExit) //持续监听服务端发来的消息 { try { bool o = socketClient.Poll(10, SelectMode.SelectRead); if (o) break; //定义一个1024*200的内存缓冲区 用于临时性存储接收到的信息 byte[] arrRecMsg = new byte[1024 * 200]; //将客户端套接字接收到的数据存入内存缓冲区, 并获取其长度 int length = socketClient.Receive(arrRecMsg); if (length == 0) return; string recMsg = Encoding.Default.GetString(arrRecMsg, 0, length); ReceivedMsg(new RecMsgArgs(recMsg)); } catch (SocketException ex) { ReceivedError(new RecErrArgs(ex.Message)); } } } /// <summary> /// 断开链接 /// </summary> public void StopConnect() { if (socketClient != null) { socketClient.Close(); isExit = true; } } } }
1 using System; 2 using System.Collections.Generic; 3 using System.Text; 4 using System.Net.Sockets; 5 6 namespace HY_RFID 7 { 8 public class ReadWriteObject 9 { 10 public TcpClient client; 11 public NetworkStream netStream; 12 public byte[] readBytes; 13 public byte[] write; 14 public ReadWriteObject(TcpClient client) 15 { 16 this.client = client; 17 netStream = client.GetStream(); 18 readBytes = new byte[client.ReceiveBufferSize]; 19 write=new byte[client.SendBufferSize]; 20 } 21 public void InitReadArray() 22 { 23 readBytes = new byte[client.ReceiveBufferSize]; 24 } 25 public void InitWriteArray() 26 { 27 write=new byte[client.SendBufferSize]; 28 } 29 } 30 }