初學C#,因為項目需要寫的一個理論上不會斷幀Tcp幫助類
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Windows;
namespace FM000023.Helper
{
class TcpHelper
{
private string ip;
private int port;
//聲明委托
public delegate void DateReceiveDelegate(TcpHelper sender,byte[] data);
public delegate void ConnectDelegate(TcpHelper sender);
public delegate void SendDelegate(SendResult sendResult);
/// <summary>
/// 資料接收事件
/// </summary>
public event DateReceiveDelegate DataReceive;
/// <summary>
/// 連接配接成功事件
/// </summary>
public event ConnectDelegate ConnectSuccess;
/// <summary>
/// 連接配接失敗事件
/// </summary>
public event ConnectDelegate ConnectFailed;
/// <summary>
/// 發送成功完成事件
/// </summary>
public event SendDelegate SendDone;
/// <summary>
/// 循環讀取序列槽資料線程
/// </summary>
private Thread readSpDataThread;
/// <summary>
/// 工具類識别辨別
/// </summary>
public string name = "";
private TcpClient tcpClient = new TcpClient();
/// <summary>
/// 構造函數
/// </summary>
/// <param name="ip">ip</param>
/// <param name="port">port</param>
public TcpHelper(string ip,int port)
{
this.ip = ip;
this.port = port;
tcpClient.BeginConnect(ip, port,new AsyncCallback(connectDone),tcpClient);
}
/// <summary>
/// 連接配接完成
/// </summary>
/// <param name="ar"></param>
private void connectDone(IAsyncResult ar)
{
try
{
tcpClient = (TcpClient)ar.AsyncState;
tcpClient.EndConnect(ar);
if (tcpClient != null && tcpClient.Connected)
{
if(ConnectSuccess != null)
Application.Current.Dispatcher.Invoke(ConnectSuccess,this);
tcpClient.ReceiveTimeout = 30;
tcpClient.SendTimeout = 1000;
startReadDataOnNewThread();
}
else
{
if(ConnectFailed != null)
Application.Current.Dispatcher.Invoke(ConnectFailed,this);
}
}
catch(Exception e)
{
if (ConnectFailed != null)
Application.Current.Dispatcher.Invoke(ConnectFailed,this);
}
}
/// <summary>
/// 讀取資料
/// </summary>
private void startReadDataOnNewThread()
{
readSpDataThread = new Thread(readData);
readSpDataThread.IsBackground = true;
readSpDataThread.Start();
}
/// <summary>
/// 讀取資料方法
/// </summary>
private void readData()
{
while(tcpClient.Connected)
{
NetworkStream ns = tcpClient.GetStream();
if (ns.CanRead)
{
byte[] data = new byte[tcpClient.Available];
int readLength = 0;
try
{
readLength = ns.Read(data, 0, data.Length);
if (readLength > 0)
{
data = data.Take(readLength).ToArray();
DataReceive(this, data);
}
}
catch (Exception e)
{
if(readLength > 0)
{
data = data.Take(readLength).ToArray();
DataReceive(this, data);
}
}
}
}
}
/// <summary>
/// 發送資料
/// </summary>
/// <param name="data">資料</param>
public void sendData(byte[] data)
{
if(tcpClient != null && tcpClient.Connected)
{
NetworkStream ns = tcpClient.GetStream();
if (ns.CanWrite)
{
WriteStateObject wso = new WriteStateObject();
wso.ns = ns;
wso.sendCmd = data;
ns.BeginWrite(data, 0, data.Length, new AsyncCallback(sendDataDone), wso);
}
else
{
SendResult sendResult = new SendResult();
sendResult.sender = this;
sendResult.isSuccess = false;
sendResult.reason = "NetworkStream不可寫";
sendResult.sendCmd = data;
SendDone(sendResult);
}
}
else
{
SendResult sendResult = new SendResult();
sendResult.sender = this;
sendResult.isSuccess = false;
sendResult.reason = "TcpClient為空或者TcpClient已經斷開連接配接";
sendResult.sendCmd = data;
SendDone(sendResult);
}
}
/// <summary>
/// 發送資料完成方法
/// </summary>
/// <param name="ar"></param>
private void sendDataDone(IAsyncResult ar)
{
WriteStateObject wso = (WriteStateObject)ar.AsyncState;
try
{
wso.ns.EndWrite(ar);
SendResult sendResult = new SendResult();
sendResult.sender = this;
sendResult.isSuccess = true;
sendResult.sendCmd = wso.sendCmd;
SendDone(sendResult);
}
catch(Exception e)
{
SendResult sendResult = new SendResult();
sendResult.sender = this;
sendResult.isSuccess = false;
sendResult.reason = e.ToString();
sendResult.sendCmd = wso.sendCmd;
SendDone(sendResult);
}
}
/// <summary>
/// 重新連接配接
/// </summary>
/// <param name="ip">ip</param>
/// <param name="port">端口</param>
public void reConnect(string ip = "",int port = 0)
{
tcpClient.Close();
tcpClient = new TcpClient();
if (ip == "")
ip = this.ip;
if (port == 0)
port = this.port;
tcpClient.BeginConnect(ip, port, new AsyncCallback(connectDone), tcpClient);
}
/// <summary>
/// 檢查是否連接配接
/// </summary>
/// <returns></returns>
public bool isConnected()
{
return tcpClient != null && tcpClient.Client != null && tcpClient.Connected;
}
/// <summary>
/// 銷毀
/// </summary>
public void destoryHelper()
{
if(readSpDataThread != null)
readSpDataThread.Abort();
if(tcpClient != null)
tcpClient.Close();
}
/// <summary>
/// 發送結果實體類
/// </summary>
public class SendResult
{
/// <summary>
/// 發送者
/// </summary>
public TcpHelper sender { set; get; }
/// <summary>
/// 發送的指令
/// </summary>
public byte[] sendCmd { set; get; }
/// <summary>
/// 發送是否成功
/// </summary>
public bool isSuccess { set; get; }
/// <summary>
/// 發送失敗原因
/// </summary>
public string reason { set; get; }
}
/// <summary>
/// 發送資料的實體類
/// </summary>
private class WriteStateObject
{
/// <summary>
/// 輸入輸出流
/// </summary>
public NetworkStream ns { set; get; }
/// <summary>
/// 發送的指令
/// </summary>
public byte[] sendCmd { set; get; }
}
/// <summary>
/// 位元組數組轉十六進制字元串
/// </summary>
/// <param name="data">位元組數組</param>
/// <returns>傳回十六進制字元串</returns>
public static string byteToHexString(byte[] data)
{
string dataStr = "";
foreach (byte b in data)
{
dataStr += b.ToString("X2");
}
return dataStr;
}
/// <summary>
/// 十六進制字元串轉位元組數組
/// </summary>
/// <param name="data">十六進制字元串</param>
/// <returns>位元組數組</returns>
public static byte[] hexStringToByte(string data)
{
if (data.Count() % 2 != 0)
return null;
byte[] dataByte = new byte[data.Count() / 2];
for (int i = 0, j = 0; i < data.Count(); i += 2, j++)
{
dataByte[j] = (byte)Convert.ToInt32(data.Substring(i, 2), 16);
}
return dataByte;
}
/// <summary>
/// 計算校驗和
/// </summary>
/// <param name="data"></param>
/// <returns></returns>
public static int calcSum(byte[] data)
{
return 0xFF & data.Select(x => (int)x).Sum() % 256;
}
}
}