/******************************
* 说明: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;
}
}
}
}