TCPIP通信
最近在開(kāi)發(fā)TCPIP通信,封裝了3個(gè)類,望各位大神指點(diǎn)指點(diǎn)。 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 創(chuàng)建事件
21 //聲明事件參數(shù)
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)// 如果有對(duì)象注冊(cè)
51 {
52 OnWaitConnect(this, null);// 調(diào)用所有注冊(cè)對(duì)象的方法
53 }
54 }
55 //聲明委托
56 public delegate void SuccessConnectEventHandler(object sender, TcpClientArgs e);
57 //聲明事件
58 public event SuccessConnectEventHandler OnSuccessConnect;
59 //觸發(fā)方法
60 protected virtual void SuccessConnect(TcpClientArgs e)
61 {
62 if (OnSuccessConnect != null)// 如果有對(duì)象注冊(cè)
63 {
64 OnSuccessConnect(this, e);// 調(diào)用所有注冊(cè)對(duì)象的方法
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)// 如果有對(duì)象注冊(cè)
72 {
73 OnReadCallBack(this, e);// 調(diào)用所有注冊(cè)對(duì)象的方法
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)// 如果有對(duì)象注冊(cè)
81 {
82 OnReadErrorCallBack(this, e);// 調(diào)用所有注冊(cè)對(duì)象的方法
83 }
84 }
85 #endregion
86
87 //用于線程同步,初始狀態(tài)設(shè)為非終止?fàn)顟B(tài),使用手動(dòng)重置方式
88 private EventWaitHandle allDone = new EventWaitHandle(false, EventResetMode.ManualReset);
89 //服務(wù)端監(jiān)聽(tīng)方法
90 public void ServerListen(int port)
91 {
92 //由于服務(wù)器要為多個(gè)客戶服務(wù),所以需要?jiǎng)?chuàng)建一個(gè)線程監(jiān)聽(tīng)客戶端連接請(qǐng)求
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("當(dāng)前端口已被占用!");
102 }
103 }
104 /// <summary>
105 /// 檢測(cè)但錢(qián)端口是否被占用
106 /// </summary>
107 /// <param name="port"></param>
108 /// <returns></returns>
109 private bool PortInUse(int port)
110 {
111 bool inUse = false;
112 //獲取所有的監(jiān)聽(tīng)連接
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 //與客戶機(jī)取得連接
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 //引用在異步操作完成時(shí)調(diào)用的回調(diào)方法
135 AsyncCallback callback = new AsyncCallback(AcceptTcpClientCallback);
136 while (!isExit)
137 {
138
139 //將事件的狀態(tài)設(shè)為非終止
140 allDone.Reset();
141 //觸發(fā)等待事件
142 WaitConnect();
143 //開(kāi)始一個(gè)異步操作接受傳入的連接嘗試
144 listener.BeginAcceptTcpClient(callback, listener);
145 //阻塞當(dāng)前線程,直到收到客戶連接信號(hào)
146 allDone.WaitOne();
147 Thread.Sleep(100);
148 }
149 }
150 catch (Exception ex)
151 {
152 throw ex;
153 }
154 }
155 //獲取本機(jī)IP
156 public object GetLocalIpv4()
157 {
158 //獲取本機(jī)所有IP地址
159 try
160 {
161 IPAddress[] localips = Dns.GetHostAddresses(Dns.GetHostName());
162 foreach (IPAddress ip in localips)
163 {
164 //找到本地所有IP地址符合IPV4協(xié)議的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 // 連接客戶端的回調(diào)函數(shù)
178 //ar是IAsyncResult類型的接口,表示異步操作的狀態(tài)是由listener.BeginAcceptTcpClient(callback, listener)傳遞過(guò)來(lái)的
179 private void AcceptTcpClientCallback(IAsyncResult ar)
180 {
181 lock (this)
182 {
183 try
184 {
185 if (isExit) return;
186 //將事件狀態(tài)設(shè)為終止?fàn)顟B(tài),允許一個(gè)或多個(gè)等待線程繼續(xù)
187 allDone.Set();
188 TcpListener myListener = (TcpListener)ar.AsyncState;
189 //異步接收傳入的連接,并創(chuàng)建新的TcpClient對(duì)象處理遠(yuǎn)程主機(jī)通信
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 //觸發(fā)客戶端連接成功事件
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 + "【斷開(kāi)】");
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 + "【斷開(kāi)】");
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 /// 停止服務(wù)
273 /// </summary>
274 public void StopServer()
275 {
276 isExit = true;
277 allDone.Set();
278 if (listener != null)
279 listener.Stop();
280 }
281 }
282 } TCPServer類 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 創(chuàng)建事件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)// 如果有對(duì)象注冊(cè)
{OnReceived(this, e);// 調(diào)用所有注冊(cè)對(duì)象的方法
}}public delegate void ReceivedErrorEventHandler(object sender, RecErrArgs e);public event ReceivedErrorEventHandler OnReceivedErr;protected virtual void ReceivedError(RecErrArgs e){if (OnReceivedErr != null)// 如果有對(duì)象注冊(cè)
{OnReceivedErr(this, e);// 調(diào)用所有注冊(cè)對(duì)象的方法
}}#endregionprivate bool isExit;private Socket socketClient = null;//連接服務(wù)端方法public void ClientConnect(string IP, string Port){isExit = false;//定義一個(gè)套字節(jié)監(jiān)聽(tīng) 包含3個(gè)參數(shù)(IP4尋址協(xié)議,流式連接,TCP協(xié)議)socketClient = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);//需要獲取文本框中的IP地址IPAddress ipaddress = IPAddress.Parse(IP);//將獲取的ip地址和端口號(hào)綁定到網(wǎng)絡(luò)節(jié)點(diǎn)endpoint上IPEndPoint endpoint = new IPEndPoint(ipaddress, int.Parse(Port));//這里客戶端套接字連接到網(wǎng)絡(luò)節(jié)點(diǎn)(服務(wù)端)用的方法是Connect 而不是Bind
socketClient.Connect(endpoint);//創(chuàng)建一個(gè)線程 用于監(jiān)聽(tīng)服務(wù)端發(fā)來(lái)的消息Thread threadClient = new Thread(RecMsg);//將窗體線程設(shè)置為與后臺(tái)同步threadClient.IsBackground = true;//啟動(dòng)線程
threadClient.Start();}// 發(fā)送節(jié)目全屏byte串信息到服務(wù)端的方法public void ClientSendMsg(string msg){try{if (socketClient.Poll(10, SelectMode.SelectRead) && (socketClient.Available == 0) || !socketClient.Connected){throw new Exception(socketClient.RemoteEndPoint + "已斷開(kāi)!");}Byte[] data = System.Text.Encoding.Default.GetBytes(msg);socketClient.Send(data, data.Length, SocketFlags.None);//發(fā)送信息
}catch(Exception ex){throw ex;}}//接收服務(wù)端發(fā)來(lái)信息的方法public void RecMsg(){while (!isExit) //持續(xù)監(jiān)聽(tīng)服務(wù)端發(fā)來(lái)的消息
{try{bool o = socketClient.Poll(10, SelectMode.SelectRead);if (o) break;//定義一個(gè)1024*200的內(nèi)存緩沖區(qū) 用于臨時(shí)性存儲(chǔ)接收到的信息byte[] arrRecMsg = new byte[1024 * 200];//將客戶端套接字接收到的數(shù)據(jù)存入內(nèi)存緩沖區(qū), 并獲取其長(zhǎng)度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>/// 斷開(kāi)鏈接/// </summary>public void StopConnect(){if (socketClient != null){socketClient.Close();isExit = true;}}}
} TCPClient類 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 } ReadWriteObject類
?
轉(zhuǎn)載于:https://www.cnblogs.com/tangxf/p/3692990.html
總結(jié)
- 上一篇: 【Maven入门教程】Maven的基本概
- 下一篇: 四叶草efi_Clover Config