| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504 |
-
- using System;
- using System.Net.Sockets;
- using Curtain.Net.Sockets.PLC.ThreadLock;
- namespace Curtain.Net.Sockets.PLC
- {
- /// <summary>
- /// Socket 通信基类
- /// </summary>
- public abstract class PLCSocket : IDisposable
- {
- #region 变量
- #endregion
- #region 属性
- /// <summary>
- /// 销毁状态
- /// </summary>
- public bool IsDispose
- {
- get;
- protected set;
- }
- /// <summary>
- /// 通信用Socket
- /// </summary>
- public Socket Socket
- {
- get; protected set;
- }
- /// <summary>
- /// 线程锁
- /// </summary>
- public IThreadLock ThreadLock
- {
- get;
- protected set;
- } = new ReaderWriterThreadLock();
- #endregion
- #region 构造
- /// <summary>
- /// Socket 通信基类
- /// </summary>
- public PLCSocket()
- {
- }
- /// <summary>
- /// Socket 通信基类
- /// </summary>
- /// <param name="socket">Socket</param>
- public PLCSocket(Socket socket)
- {
- this.Socket = socket;
- }
- #endregion
- #region 连接&关闭
- /// <summary>
- /// 创建Socket
- /// </summary>
- /// <param name="addressFamily"></param>
- /// <param name="socketType"></param>
- /// <param name="protocolType"></param>
- public virtual void CreateSocket(AddressFamily addressFamily, SocketType socketType, ProtocolType protocolType)
- {
- if (Socket != null)
- {
- try
- {
- //if (Socket.Connected)
- //{
- // Socket.Close();
- //}
- Socket.Dispose();
- }
- catch
- {
- }
- }
- if (IsDispose)
- {
- IsDispose = false;
- }
- if (ThreadLock == null)
- {
- ThreadLock = new ReaderWriterThreadLock();
- }
- Socket = new Socket(addressFamily, socketType, protocolType);
- }
- /// <summary>
- /// 创建Socket
- /// </summary>
- public virtual void CreateSocket()
- {
- CreateSocket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
- }
- /// <summary>
- /// 连接Socket
- /// </summary>
- /// <param name="host"></param>
- /// <param name="port"></param>
- public virtual void Connect(string host, int port)
- {
- if (this.Socket == null)
- {
- this.CreateSocket();
- }
- //else
- //{
- // // 刷新 Connected 状态(服务端关闭连接时,客户端 Connected=true)。
- // try
- // {
- // bool b = Socket.EnableBroadcast;
- // }
- // catch
- // {
- // }
- //}
- if (!this.Socket.Connected)
- {
- try
- {
- this.Socket.Connect(host, port);
- this.OnSocketConnect();
- }
- //catch (InvalidOperationException ex)
- catch //(Exception ex)
- {
- this.Close();
- this.CreateSocket();
- this.Socket.Connect(host, port);
- this.OnSocketConnect();
- }
- }
- }
- /// <summary>
- /// Socket连接后PLC初始化
- /// </summary>
- public virtual void OnSocketConnect()
- {
- }
- /// <summary>
- /// 断开连接
- /// </summary>
- public virtual void Disconnect()
- {
- if (this.Socket == null)
- {
- return;
- }
- if (this.Socket.Connected)
- {
- try
- {
- this.Socket.Disconnect(true);
- }
- catch //(Exception ex)
- {
- this.Close();
- this.Socket = null;
- }
- }
- }
- /// <summary>
- /// 关闭Socket
- /// </summary>
- /// <returns></returns>
- public virtual bool Close()
- {
- if (Socket == null)
- {
- return true;
- }
- try
- {
- Socket.Close();
- Socket = null;
- }
- catch //(Exception ex)
- {
- return false;
- }
- return true;
- }
- /// <summary>
- /// 销毁
- /// </summary>
- public virtual void Dispose()
- {
- try
- {
- Socket?.Dispose();
- Socket = null;
- ThreadLock.Dispose();
- ThreadLock = null;
- }
- catch
- {
- }
- finally
- {
- IsDispose = true;
- }
- }
- #endregion
- #region Send
- /// <summary>
- /// 发送
- /// </summary>
- /// <param name="data"></param>
- /// <returns></returns>
- internal protected virtual PLCResult Send(byte[] data)
- {
- PLCResult plcResult = new PLCResult();
- if (data == null || data.Length == 0)
- {
- plcResult.Successed = false;
- plcResult.Message = "no command";
- return plcResult;
- }
- if (Socket == null)
- {
- plcResult.Successed = false;
- plcResult.Message = "no socket";
- return plcResult;
- }
- if (!Socket.Connected)
- {
- plcResult.Successed = false;
- plcResult.Message = "no connected";
- return plcResult;
- }
- try
- {
- //plcResult.Result = Socket.Send(data);
- Socket.Send(data);
- }
- catch (Exception ex)
- {
- plcResult.Successed = false;
- plcResult.Message = ex.Message;
- plcResult.MessageDetail = ex.ToString();
- Socket?.Close();
- Socket = null;
- }
- return plcResult;
- }
- /// <summary>
- /// 异步发送
- /// </summary>
- /// <param name="data"></param>
- /// <returns></returns>
- internal protected virtual PLCResult BeginSend(byte[] data)
- {
- PLCResult plcResult = new PLCResult();
- if (data == null || data.Length == 0)
- {
- plcResult.Successed = false;
- plcResult.Message = "no command";
- return plcResult;
- }
- if (Socket == null)
- {
- plcResult.Successed = false;
- plcResult.Message = "no socket";
- return plcResult;
- }
- if (!Socket.Connected)
- {
- plcResult.Successed = false;
- plcResult.Message = "no connected";
- return plcResult;
- }
- SocketAsyncState sas = new SocketAsyncState();
- try
- {
- sas.Data = data;
- sas.Size = data.Length;
- sas.Result = plcResult;
- Socket.BeginSend(sas.Data, sas.Offset, sas.Size, SocketFlags.None, SendCallBack, sas);
- }
- catch (Exception ex)
- {
- plcResult.Successed = false;
- plcResult.Message = ex.Message;
- plcResult.MessageDetail = ex.ToString();
- sas?.Close();
- sas = null;
- Socket?.Close();
- Socket = null;
- }
- sas?.WaitOne();
- sas?.Close();
- sas = null;
- return plcResult;
- }
- /// <summary>
- /// 发送结束
- /// </summary>
- /// <param name="iar"></param>
- private void SendCallBack(IAsyncResult iar)
- {
- if (iar.AsyncState is SocketAsyncState sas)
- {
- try
- {
- sas.Offset += Socket.EndSend(iar);
- if (sas.Offset < sas.Size)
- {
- Socket.BeginSend(sas.Data, sas.Offset, sas.Size - sas.Offset, SocketFlags.None, SendCallBack, iar);
- }
- else
- {
- sas.Set();
- }
- }
- catch (Exception ex)
- {
- sas.Result.Successed = false;
- sas.Result.Message = ex.Message;
- sas.Result.MessageDetail = ex.ToString();
- Socket.Close();
- Socket = null;
- sas.Set();
- }
- }
- }
- #endregion
- #region Receive
- /// <summary>
- /// 接收
- /// </summary>
- /// <param name="length"></param>
- /// <returns></returns>
- protected virtual PLCResult<byte[]> Receive(int length)
- {
- PLCResult<byte[]> plcResult = new PLCResult<byte[]>(new byte[length]);
- if (length == 0)
- {
- plcResult.Successed = false;
- plcResult.Message = "no length";
- return plcResult;
- }
- if (Socket == null)
- {
- plcResult.Successed = false;
- plcResult.Message = "no socket";
- return plcResult;
- }
- if (!Socket.Connected)
- {
- plcResult.Successed = false;
- plcResult.Message = "no connected";
- return plcResult;
- }
- try
- {
- //plcResult.Result = Socket.Receive(plcResult.Data);
- //Socket.Receive(plcResult.Data);
- Socket.Receive(plcResult.Data, 0, length, SocketFlags.None);
- }
- catch (Exception ex)
- {
- plcResult.Successed = false;
- plcResult.Message = ex.Message;
- plcResult.MessageDetail = ex.ToString();
- Socket?.Close();
- Socket = null;
- }
- return plcResult;
- }
- /// <summary>
- /// 异步接收
- /// </summary>
- /// <param name="length"></param>
- /// <returns></returns>
- protected virtual PLCResult<byte[]> BeginReceive(int length)
- {
- PLCResult<byte[]> plcResult = new PLCResult<byte[]>(new byte[length]);
- if (length == 0)
- {
- plcResult.Successed = false;
- plcResult.Message = "no length";
- return plcResult;
- }
- if (Socket == null)
- {
- plcResult.Successed = false;
- plcResult.Message = "no socket";
- return plcResult;
- }
- if (!Socket.Connected)
- {
- plcResult.Successed = false;
- plcResult.Message = "no connected";
- return plcResult;
- }
- SocketAsyncState sas = new SocketAsyncState();
- try
- {
- sas.Data = plcResult.Data;
- sas.Size = length;
- sas.Result = plcResult;
- Socket.BeginReceive(sas.Data, sas.Offset, sas.Size, SocketFlags.None, ReceiveCallback, sas);
- }
- catch (Exception ex)
- {
- plcResult.Successed = false;
- plcResult.Message = ex.Message;
- plcResult.MessageDetail = ex.ToString();
- sas?.Close();
- sas = null;
- Socket?.Close();
- Socket = null;
- }
- sas?.WaitOne();
- sas?.Close();
- sas = null;
- return plcResult;
- }
- /// <summary>
- /// 接收结束
- /// </summary>
- /// <param name="iar"></param>
- private void ReceiveCallback(IAsyncResult iar)
- {
- if (iar.AsyncState is SocketAsyncState sas)
- {
- try
- {
- int length = Socket.EndReceive(iar);
- if (length > 0)
- {
- sas.Offset += length;
- if (sas.Offset < sas.Size)
- {
- Socket.BeginReceive(sas.Data, sas.Offset, sas.Size - sas.Offset, SocketFlags.None, SendCallBack, iar);
- }
- else
- {
- sas.Set();
- }
- }
- else
- {
- sas.Result.Successed = false;
- sas.Result.Message = "other socket has closed";
- Socket.Close();
- Socket = null;
- sas.Set();
- }
- }
- catch (Exception ex)
- {
- sas.Result.Successed = false;
- sas.Result.Message = ex.Message;
- sas.Result.MessageDetail = ex.ToString();
- Socket.Close();
- Socket = null;
- sas.Set();
- }
- }
- }
- #endregion
- }
- }
|