C#里创建一个TCP客户端连接类
TCP客户端,一般分为两种,一种是同步收发数据,这种需要开发线程来处理。
如果连接比较多,就会消耗比较多线程。
另外一种,就是使用异步连接,这样只需要一个线程,就可以连接很多个。
在这里使用异步的方式来连接,例子的代码如下:
cs
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;
namespace ModbusTCP.Modbus
{
class MyTcp : TcpClient
{
public delegate void Connect_Resp(); //声明委托
public delegate void Recv_Resp(byte[] data); //声明委托
private Connect_Resp _ConnectSucces;
private Connect_Resp _ConnectFail;
private Recv_Resp _Recv_Resp;
public event Action _SendSuccess;
public event Action _SendFail;
internal class StateObject
{
public TcpClient client = null;
public int totalBytesRead = 0;
public const int BufferSize = 1024;
public string readType = null;
public byte[] buffer = new byte[BufferSize];
public StringBuilder messageBuffer = new StringBuilder();
}
public string ErrorString { get; set; }
public MyTcp(Connect_Resp con_succes, Connect_Resp con_fail, Recv_Resp recv)
{
_ConnectSucces = con_succes;
_ConnectFail = con_fail;
_Recv_Resp = recv;
}
public void ClientConnect(string strIP, int port)
{
BeginConnect(strIP, port, new AsyncCallback(ConnectCallback), this);
}
public virtual void ConnectCallback(IAsyncResult ar)
{
MyTcp t = (MyTcp)ar.AsyncState;
try
{
if (t != null && t.Client != null)
{
t.EndConnect(ar);
if (t.Connected)
{
OnConnectSuccess(t);
}
else
{
OnConnectFailure("连接失败");
}
}
else
{
OnConnectFailure("连接对象为空");
}
}
catch (SocketException se)
{
OnConnectFailure($"连接发生套接字错误: {se.SocketErrorCode} - {se.Message}");
}
catch (Exception ex)
{
OnConnectFailure($"连接发生未知错误: {ex.Message}");
}
}
private void OnConnectSuccess(MyTcp tcpClient)
{
_ConnectSucces?.Invoke();
AsyncRead(tcpClient);
}
private void OnConnectFailure(string errorMessage)
{
ErrorString = errorMessage;
_ConnectFail?.Invoke();
}
/// <summary>
/// 异步读TCP数据
/// </summary>
/// <param name="sock"></param>
private void AsyncRead(MyTcp sock)
{
StateObject state = new StateObject
{
client = sock
};
NetworkStream stream = sock.GetStream();
if (stream.CanRead)
{
try
{
IAsyncResult ar = stream.BeginRead(state.buffer, 0, StateObject.BufferSize,
new AsyncCallback(TCPReadCallBack), state);
}
catch (Exception e)
{
ErrorString = "Network IO problem " + e.ToString();
_ConnectFail?.Invoke();
}
}
}
/// <summary>
/// TCP读数据的回调函数
/// </summary>
/// <param name="ar"></param>
private void TCPReadCallBack(IAsyncResult ar)
{
StateObject state = (StateObject)ar.AsyncState;
//主动断开时
if ((state.client == null) || (!state.client.Connected))
return;
NetworkStream nas = state.client.GetStream();
try
{
int numberOfBytesRead = nas.EndRead(ar);
if (numberOfBytesRead > 0)
{
state.totalBytesRead += numberOfBytesRead;
byte[] dd = new byte[numberOfBytesRead];
Array.Copy(state.buffer, 0, dd, 0, numberOfBytesRead);
//接收数据
_Recv_Resp?.Invoke(dd);
nas.BeginRead(state.buffer, 0, StateObject.BufferSize,
new AsyncCallback(TCPReadCallBack), state);
}
else
{
//被动断开时
nas.Close();
state.client.Close();
nas = null;
state = null;
_ConnectFail?.Invoke();
}
}
catch (Exception)
{
nas = null;
state = null;
_ConnectFail?.Invoke();
}
}
public void Send(byte[] buffer, int offset, int size)
{
NetworkStream stream = GetStream();
if (stream.CanWrite)
{
stream.BeginWrite(buffer, offset, size, new AsyncCallback(TCPSendCallBack), this);
}
}
private void TCPSendCallBack(IAsyncResult ar)
{
try
{
MyTcp tcp = (MyTcp)ar.AsyncState;
NetworkStream stream = tcp.GetStream();
stream.EndWrite(ar);
_SendSuccess?.Invoke();
}
catch (Exception ex)
{
ErrorString = $"发送数据时发生错误: {ex.Message}";
_SendFail?.Invoke();
}
}
//组合两个缓冲区的数据,并产生一个新的缓冲区返回
public static byte[] CombineBytes(byte[] firstBytes, int firstIndex, int firstLength,
byte[] secondBytes, int secondIndex, int secondLength)
{
MemoryStream ms = new MemoryStream();
ms.Write(firstBytes, firstIndex, firstLength);
ms.Write(secondBytes, secondIndex, secondLength);
byte[] bytes = ms.ToArray();
ms.Close();
return bytes;
}
}
}