using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
using System.Net.Sockets;
using System.Net;
using System.IO;
namespace TcpSvr
{
public class TcpCli
{
#region 字段
/// <summary>
/// 客户端与服务器之间的会话类
/// </summary>
private Session _session;
/// <summary>
/// 客户端是否已经连接服务器
/// </summary>
private bool _isConnected = false;
/// <summary>
/// 接收数据缓冲区大小64K
/// </summary>
public const int DefaultBufferSize = 64 * 1024;
/// <summary>
/// 报文解析器
/// </summary>
private DatagramResolver _resolver;
/// <summary>
/// 接收数据缓冲区
/// </summary>
private byte[] _recvDataBuffer = new byte[DefaultBufferSize];
#endregion
#region 事件定义
//需要订阅事件才能收到事件的通知,如果订阅者退出,必须取消订阅
/// <summary>
/// 已经连接服务器事件
/// </summary>
public event NetEvent ConnectedServer;
/// <summary>
/// 接收到数据报文事件
/// </summary>
public event NetEvent ReceivedDatagram;
/// <summary>
/// 连接断开事件
/// </summary>
public event NetEvent DisConnectedServer;
/// <summary>
/// 连接失败
/// </summary>
public event NetEvent ConnectedServerFail;
#endregion
#region 属性
/// <summary>
/// 返回客户端与服务器之间的会话对象
/// </summary>
public Session ClientSession
{
get
{
return _session;
}
}
/// <summary>
/// 返回客户端与服务器之间的连接状态
/// </summary>
public bool IsConnected
{
get
{
return _isConnected;
}
}
/// <summary>
/// 数据报文分析器
/// </summary>
public DatagramResolver Resovlver
{
get
{
return _resolver;
}
set
{
_resolver = value;
}
}
#endregion
#region 公有方法
/// <summary>
/// 连接服务器
/// </summary>
/// <param name="ip">服务器IP地址</param>
/// <param name="port">服务器端口</param>
public virtual void Connect(string ip, int port)
{
if (IsConnected)
{
//重新连接
Debug.Assert(_session != null);
Close();
}
Socket newsock = new Socket(AddressFamily.InterNetwork,
SocketType.Stream, ProtocolType.Tcp);
IPEndPoint iep = new IPEndPoint(IPAddress.Parse(ip), port);
newsock.BeginConnect(iep, new AsyncCallback(Connected), newsock);
}
/// <summary>
/// 发送数据报文
/// </summary>
/// <param name="datagram"></param>
public virtual void Send(byte[] data, Cmd cmds)
{
if (data.Length == 0)
{
return;
}
if (!_isConnected)
{
throw (new ApplicationException("没有连接服务器,不能发送数据"));
}
DatagramResolver datasend = new DatagramResolver(data, cmds);
_session.ClientSocket.BeginSend(datasend.Tobytes, 0, datasend.Tobytes.Length, SocketFlags.None,
new AsyncCallback(SendDataEnd), _session.ClientSocket);
}
/// <summary>
/// 关闭连接
/// </summary>
public virtual void Close()
{
if (!_isConnected)
{
return;
}
_session.Close();
_session = null;
_isConnected = false;
}
#endregion
#region 受保护方法
/// <summary>
/// 数据发送完成处理函数
/// </summary>
/// <param name="iar"></param>
protected virtual void SendDataEnd(IAsyncResult iar)
{
Socket remote = (Socket)iar.AsyncState;
int sent = remote.EndSend(iar);
Debug.Assert(sent != 0);
}
/// <summary>
/// 建立Tcp连接后处理过程
/// </summary>
/// <param name="iar">异步Socket</param>
protected virtual void Connected(IAsyncResult iar)
{
try
{
Socket socket = (Socket)iar.AsyncState;
socket.EndConnect(iar);
//创建新的会话
_session = new Session(socket);
_isConnected = true;
_resolver = new DatagramResolver();
//触发连接建立事件
if (ConnectedServer != null)
{
ConnectedServer(this, new NetEventArgs(_session));
}
//建立连接后应该立即接收数据
_session.ClientSocket.BeginReceive(_recvDataBuffer, 0,
DefaultBufferSize, SocketFlags.None,
new AsyncCallback(RecvData), socket);
}
catch (SocketException) {
if (ConnectedServerFail != null)
{
ConnectedServerFail(this, null);
}
}
}
/// <summary>
/// 数据接收处理函数
/// </summary>
/// <param name="iar">异步Socket</param>
protected virtual void RecvData(IAsyncResult iar)
{
Socket client = (Socket)iar.AsyncState;
try
{
int recv = client.EndReceive(iar);
if (recv == 0)
{
_session.TypeOfExit = Session.ExitType.NormalExit;
if (DisConnectedServer != null)
{
DisConnectedServer(this, new NetEventArgs(_session));
}
return;
}
if (_resolver.Resolver(ref _session, _recvDataBuffer))
{
_session.RecvDataLength = 0;
_session.TotalDataLength = 8;
if (ReceivedDatagram != null)
{
ICloneable copySession = (ICloneable)_session;
Session clientSession = (Session)copySession.Clone();
//发布一个报文消息
// Array.Clear(_recvDataBuffer,0,DefaultBufferSize);
ReceivedDatagram(this, new NetEventArgs(clientSession));
}
}
client.BeginReceive(_recvDataBuffer, 0, _recvDataBuffer.Length, SocketFlags.None,
new AsyncCallback(RecvData), client);
}
catch (SocketException ex)
{
//客户端退出
if (10054 == ex.ErrorCode)
{
//服务器强制的关闭连接,强制退出
_session.TypeOfExit = Session.ExitType.ExceptionExit;
if (DisConnectedServer != null)
{
DisConnectedServer(this, new NetEventArgs(_session));
}
}
else
{
throw (ex);
}
}
catch (ObjectDisposedException ex)
{
if (ex != null)
{
ex = null;
//DoNothing;
}
}
}
#endregion
}
}