最近在项目中由于同步阻塞通讯带来程序效率过低学习了异步Socket通讯。这里粘贴Socket客户端异步非阻塞工具类代码。
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;
namespace com.qjcz.weighing.Utils
{
public class AsyncTCPClient
{
/// <summary>
/// 内部类,用于消息接收
/// </summary>
internal class SocketObject
{
public string KeyID = "";
public Socket WorkSocket = null;
public const int BufferSize = 1024;
public byte[] Buffer = new byte[BufferSize];
public StringBuilder sbBuffer = new StringBuilder();
}
#region 变量
private Socket mSocket = null;
private string localIPAddress = "";
private int localPort = 0;
private string remoteIPAddress = "";
private int remotePort = 0;
private string keyID = "";
private bool IsExit = false;
private SocketObject so = new SocketObject();
#endregion
#region 变量属性
/// <summary>
/// Socket标志
/// </summary>
public string KeyID
{
get
{
return keyID;
}
}
/// <summary>
/// 本机地址
/// </summary>
public string LocalIPAddress
{
get
{
return localIPAddress;
}
}
/// <summary>
/// 本机端口
/// </summary>
public int LocalPort
{
get
{
return localPort;
}
}
/// <summary>
/// 主机地址
/// </summary>
public string RemoteIPAddress
{
get
{
return remoteIPAddress;
}
}
/// <summary>
/// 主机端口
/// </summary>
public int RemotePort
{
get
{
return remotePort;
}
}
/// <summary>
/// 消息的终止判断符
/// </summary>
public static string EndChar
{
get
{
return new string((char)0, 1);
}
}
#endregion
#region 代理委托
/// <summary>
/// Socket异常错误事件
/// </summary>
/// <param name="aKeyID">异常错误所有者的标志值</param>
/// <param name="aErrorMessage">异常错误信息</param>
public delegate void SocketErrorHandler(string aKeyID, string aErrorMessage);
/// <summary>
/// 接收二进制数据
/// </summary>
/// <param name="aData">接收到的数据</param>
public delegate void BinaryDataAvailableHandler(byte[] aData);
/// <summary>
/// 接收字符串数据
/// </summary>
/// <param name="aData">接收到的数据</param>
public delegate void StringDataAvailableHandler(string aData);
#endregion
#region 事件声明
public event SocketErrorHandler OnSocketError;
public event BinaryDataAvailableHandler OnBinaryDataAvailable;
public event StringDataAvailableHandler OnStringDataAvailable;
#endregion
#region 事件代理方法
/// <summary>
/// 显示异常错误信息
/// </summary>
/// <param name="aKeyID">异常错误所有者的标志值</param>
/// <param name="aErrorMessage">异常错误信息</param>
private void DisplayError(string aKeyID, string aErrorMessage)
{
if (OnSocketError != null)
{
OnSocketError(aKeyID, aErrorMessage);
}
}
/// <summary>
/// 接收二进制数据
/// </summary>
/// <param name="aData">接收到的数据</param>
private void BinaryDataAvailable(byte[] aData)
{
if (OnBinaryDataAvailable != null)
{
OnBinaryDataAvailable(aData);
}
}
/// <summary>
/// 接收字符串数据
/// </summary>
/// <param name="aData">接收到的数据</param>
private void StringDataAvailable(string aData)
{
if (OnStringDataAvailable != null)
{
OnStringDataAvailable(aData);
}
}
#endregion
#region 内部方法
/// <summary>
/// 异步接收数据
/// </summary>
/// <param name="ar">IAsyncResult接口对象</param>
private void AsyncDataReceive(IAsyncResult ar)
{
SocketObject so = (SocketObject)ar.AsyncState;
try
{
if (IsExit == false)
{
//接收的数据长度
int iReceiveCount = so.WorkSocket.EndReceive(ar);
if (iReceiveCount > 0)
{
//so.sbBuffer.Append(Encoding.Default.GetString(so.Buffer, 0, iReceiveCount));
//string strReceive = so.sbBuffer.ToString();
//if (strReceive.Substring(strReceive.Length - 1, 1) == EndChar)
//{
//本次接收
// strReceive = strReceive.Remove(strReceive.Length - 1, 1);
//通过接收事件调用外部用户接口方法
BinaryDataAvailable(so.Buffer);
//StringDataAvailable(strReceive);
//清空数据
so.sbBuffer.Remove(0, so.sbBuffer.Length);
// }
if (IsExit == false)
{
//递归实现连续接收
so.WorkSocket.BeginReceive(so.Buffer, 0, so.Buffer.Length, SocketFlags.None, new AsyncCallback(AsyncDataReceive), so);
}
}
else
{
Disconnect();
}
}
else
{
Disconnect();
}
}
catch (Exception ex)
{
DisplayError(KeyID, ex.Message);
}
}
/// <summary>
/// 异步发送消息
/// </summary>
/// <param name="ar">IAsyncResult接口对象</param>
private void AsyncSend(IAsyncResult ar)
{
try
{
int iSendCount = mSocket.EndSend(ar);
}
catch (Exception ex)
{
DisplayError(KeyID, ex.Message);
}
}
/// <summary>
/// 发送消息(异步发送)
/// </summary>
/// <param name="aData">要发送的消息</param>
private void Send(byte[] aData)
{
try
{
mSocket.BeginSend(aData, 0, aData.Length, SocketFlags.None, new AsyncCallback(AsyncSend), null);
}
catch (Exception ex)
{
DisplayError(KeyID, ex.Message);
}
}
/// <summary>
/// 异步连接完成回调函数
/// </summary>
/// <param name="ar"></param>
public void AsyncConnect(IAsyncResult ar)
{
Socket sock = (Socket)ar.AsyncState;
try
{
sock.EndConnect(ar);
if (sock.Connected)
{
//启动消息接收事件
so.KeyID = KeyID;
so.WorkSocket = sock;
if (IsExit == false)
{
so.WorkSocket.BeginReceive(so.Buffer, 0, so.Buffer.Length, SocketFlags.None, new AsyncCallback(AsyncDataReceive), so);
}
}
else
{
new Exception("Unable to connect to remote machine, Connect Failed!");
}
}
catch (Exception ex)
{
DisplayError(KeyID, ex.Message);
}
}
#endregion
#region 对外开发的接口方法
/// <summary>
/// 初始化本机Socket通信机制
/// </summary>
/// <param name="aLocalIPAddress">本机地址</param>
/// <param name="aLocalPort">本机端口</param>
/// <returns>返回操作是否成功</returns>
public bool InitSocket(string aLocalIPAddress, int aLocalPort)
{
bool bActive = false;
mSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
LingerOption lo = new LingerOption(false, 10);
mSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Linger, lo);
try
{
IPAddress ip = Dns.GetHostAddresses(aLocalIPAddress)[0];
if (aLocalPort == 0)
{
Random rd = new Random(5000);
aLocalPort = rd.Next(30000);
}
localIPAddress = ip.ToString();
localPort = aLocalPort;
IPEndPoint ipe = new IPEndPoint(ip, aLocalPort);
keyID = Guid.NewGuid().ToString();
mSocket.Bind(ipe);
bActive = true;
}
catch (Exception ex)
{
bActive = false;
DisplayError(KeyID, ex.Message);
}
return bActive;
}
/// <summary>
/// 连接主机
/// </summary>
/// <param name="aRemoteIPAddress">主机地址</param>
/// <param name="aRemotePort">主机端口</param>
/// <returns>返回操作是否成功</returns>
public bool Connect(string aRemoteIPAddress, int aRemotePort)
{
if (mSocket == null)
return false;
try
{
remoteIPAddress = aRemoteIPAddress;
remotePort = aRemotePort;
mSocket.Blocking = false;
mSocket.BeginConnect(remoteIPAddress, remotePort, new AsyncCallback(AsyncConnect), mSocket);
}
catch (Exception ex)
{
DisplayError(KeyID, ex.Message);
}
return mSocket.Connected;
}
/// <summary>
/// 断开与主机的连接
/// </summary>
/// <returns></returns>
public bool Disconnect()
{
try
{
if (mSocket != null)
{
if (mSocket.Connected)
{
mSocket.Shutdown(SocketShutdown.Both);
mSocket.Close();
mSocket = null;
}
else
{
mSocket = null;
}
}
return true;
}
catch (Exception ex)
{
DisplayError(keyID, ex.Message);
return false;
}
}
/// <summary>
/// 发送消息(异步发送)
/// </summary>
/// <param name="aMessage">要发送的消息</param>
public void Send(string aMessage)
{
string strMessage = aMessage;
//判断要发送的消息是不是以消息终止判断符号结尾,如果没有则自动加上
if (strMessage.Substring(strMessage.Length - 1, 1) != EndChar)
{
strMessage = strMessage + EndChar;
}
Send(Encoding.Default.GetBytes(strMessage));
}
/// <summary>
/// 发送消息(异步发送)
/// </summary>
/// <param name="aMessage">要发送的消息</param>
public void Send(byte[] aMessage, int aMessageLength)
{
StringBuilder SendBuffer = new StringBuilder();
SendBuffer.Append(Encoding.UTF8.GetString(aMessage, 0, aMessageLength));
string strSend = SendBuffer.ToString();
Send(strSend);
}
#endregion
}
}