/****************************** * 说明:Socket传输基类 * 创建人:龚宇超 * 创建日期:2018-01-23 * 修改人: * 修改日期: * 修改备注: * 版本:1.0.0.0 ******************************/ using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Net.Sockets; using Lskj.SocketService; namespace Lskj.SocketClient { /// /// 异步Socket调用对象,所有的协议处理都从本类继承 /// public class SyncSocketInvokeElement { private bool _netByteOrder; /// /// TCP客户端 /// protected TcpClient _tcpClient; /// /// 服务器地址 /// protected string _host; /// /// 端口 /// protected int _port; /// /// 传输标识 /// protected ProtocolFlag _protocolFlag; /// /// 传输时间设置 /// /// The socket time out ms. protected int SocketTimeOutMS { get { return _tcpClient.SendTimeout; } set { _tcpClient.SendTimeout = value; _tcpClient.ReceiveTimeout = value; } } /// /// 协议组装器,用来组装往外发送的命令 /// protected OutgoingDataAssembler _outgoingDataAssembler; /// /// 接收数据的缓存 /// protected DynamicBufferManager _recvBuffer; /// /// 收到数据的解析器,用于解析返回的内容 /// protected IncomingDataParser _incomingDataParser; /// /// 发送数据的缓存,统一写到内存中,调用一次发送 /// protected DynamicBufferManager _sendBuffer; /// /// 长度是否使用网络字节顺序 /// /// true if [net byte order]; otherwise, false. public bool NetByteOrder { get { return _netByteOrder; } set { _netByteOrder = value; } } public SyncSocketInvokeElement() { _tcpClient = new TcpClient(); _tcpClient.Client.Blocking = true; //使用阻塞模式,即同步模式 _protocolFlag = ProtocolFlag.None; SocketTimeOutMS = ProtocolConst.SocketTimeOutMS; _outgoingDataAssembler = new OutgoingDataAssembler(); _recvBuffer = new DynamicBufferManager(ProtocolConst.ReceiveBufferSize); _incomingDataParser = new IncomingDataParser(); _sendBuffer = new DynamicBufferManager(ProtocolConst.ReceiveBufferSize); } /// /// 说明:连接Socket服务器 /// 创建人:龚宇超 /// 创建日期:2018-01-24 /// 修改人: /// 修改日期: /// 修改备注: /// 版本:1.0 /// /// The host. /// The port. public void Connect(string host, int port) { _tcpClient.Connect(host, port); byte[] socketFlag = new byte[1]; socketFlag[0] = (byte)_protocolFlag; _tcpClient.Client.Send(socketFlag, SocketFlags.None); //发送标识 _host = host; _port = port; } /// /// 说明:关闭Socket连接 /// 创建人:龚宇超 /// 创建日期:2018-01-24 /// 修改人: /// 修改日期: /// 修改备注: /// 版本:1.0 /// public void Disconnect() { _tcpClient.Close(); _tcpClient = new TcpClient(); //_tcpClient.Client. } /// /// 说明:发送命令 /// 创建人:龚宇超 /// 创建日期:2018-01-24 /// 修改人: /// 修改日期: /// 修改备注: /// 版本:1.0 /// public void SendCommand() { string commandText = _outgoingDataAssembler.GetProtocolText(); byte[] bufferUTF8 = Encoding.UTF8.GetBytes(commandText); int totalLength = sizeof(int) + bufferUTF8.Length; //获取总大小 _sendBuffer.Clear(); _sendBuffer.WriteInt(totalLength, false); //写入总大小 _sendBuffer.WriteInt(bufferUTF8.Length, false); //写入命令大小 _sendBuffer.WriteBuffer(bufferUTF8); //写入命令内容 _tcpClient.Client.Send(_sendBuffer.Buffer, 0, _sendBuffer.DataCount, SocketFlags.None); //使用阻塞模式,Socket会一次发送完所有数据后才返回 } /// /// 说明:发送命令 /// 创建人:龚宇超 /// 创建日期:2018-01-24 /// 修改人: /// 修改日期: /// 修改备注: /// 版本:1.0 /// /// The buffer. /// The offset. /// The count. public void SendCommand(byte[] buffer, int offset, int count) { string commandText = _outgoingDataAssembler.GetProtocolText(); byte[] bufferUTF8 = Encoding.UTF8.GetBytes(commandText); int totalLength = sizeof(int) + bufferUTF8.Length + count; //获取总大小 _sendBuffer.Clear(); _sendBuffer.WriteInt(totalLength, false); //写入总大小 _sendBuffer.WriteInt(bufferUTF8.Length, false); //写入命令大小 _sendBuffer.WriteBuffer(bufferUTF8); //写入命令内容 _sendBuffer.WriteBuffer(buffer, offset, count); //写入二进制数据 _tcpClient.Client.Send(_sendBuffer.Buffer, 0, _sendBuffer.DataCount, SocketFlags.None); } /// /// 说明:接收命令 /// 创建人:龚宇超 /// 创建日期:2018-01-24 /// 修改人: /// 修改日期: /// 修改备注: /// 版本:1.0 /// /// true if XXXX, false otherwise. public bool RecvCommand() { _recvBuffer.Clear(); _tcpClient.Client.Receive(_recvBuffer.Buffer, sizeof(int), SocketFlags.None); int packetLength = BitConverter.ToInt32(_recvBuffer.Buffer, 0); //获取包长度 if (NetByteOrder) packetLength = System.Net.IPAddress.NetworkToHostOrder(packetLength); //把网络字节顺序转为本地字节顺序 _recvBuffer.SetBufferSize(sizeof(int) + packetLength); //保证接收有足够的空间 _tcpClient.Client.Receive(_recvBuffer.Buffer, sizeof(int), packetLength, SocketFlags.None); int commandLen = BitConverter.ToInt32(_recvBuffer.Buffer, sizeof(int)); //取出命令长度 string tmpStr = Encoding.UTF8.GetString(_recvBuffer.Buffer, sizeof(int) + sizeof(int), commandLen); if (!_incomingDataParser.DecodeProtocolText(tmpStr)) //解析命令 return false; else return true; } /// /// 说明:接收命令 /// 创建人:龚宇超 /// 创建日期:2018-01-24 /// 修改人: /// 修改日期: /// 修改备注: /// 版本:1.0 /// /// The buffer. /// The offset. /// The size. /// true if XXXX, false otherwise. public bool RecvCommand(out byte[] buffer, out int offset, out int size) { _recvBuffer.Clear(); _tcpClient.Client.Receive(_recvBuffer.Buffer, sizeof(int), SocketFlags.None); int packetLength = BitConverter.ToInt32(_recvBuffer.Buffer, 0); //获取包长度 if (NetByteOrder) packetLength = System.Net.IPAddress.NetworkToHostOrder(packetLength); //把网络字节顺序转为本地字节顺序 _recvBuffer.SetBufferSize(sizeof(int) + packetLength); //保证接收有足够的空间 _tcpClient.Client.Receive(_recvBuffer.Buffer, sizeof(int), packetLength, SocketFlags.None); int commandLen = BitConverter.ToInt32(_recvBuffer.Buffer, sizeof(int)); //取出命令长度 string tmpStr = Encoding.UTF8.GetString(_recvBuffer.Buffer, sizeof(int) + sizeof(int), commandLen); if (!_incomingDataParser.DecodeProtocolText(tmpStr)) //解析命令 { buffer = null; offset = 0; size = 0; return false; } else { buffer = _recvBuffer.Buffer; offset = commandLen + sizeof(int) + sizeof(int); size = packetLength - offset; return true; } } } }