using Apewer;
using Apewer.Internals;
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
namespace Apewer.Network
{
/// TCP 客户端。
public class TcpClient
{
#region event
/// Exception。
public event Event Excepted;
/// 已发送数据。
public event Event Sent;
/// 已接收数据。
public event Event Received;
/// 已连接。
public event Event Connected;
/// 已断开。
public event Event Closed;
#region raise
private void RaiseConnected() { if (Connected != null) Connected(this, new EventArgs()); }
private void RaiseClosed() { if (Closed != null) Closed(this, new EventArgs()); }
private void RaiseSent(byte[] value) { if (Sent != null) Sent(this, value); }
private void RaiseReceived(byte[] value) { if (Received != null) Received(this, value); }
private void RaiseExcepted(Exception value) { if (Excepted != null) Excepted(this, value); }
#endregion
#endregion
#region definition
private Thread _listener = null;
private Thread _provider = null;
private Socket _socket = null;
private Queue _queue = null;
// private AutoResetEvent _are = null;
private bool _break = false;
private int _timeout = 1000;
private string _localip, _remoteip;
private int _localport = 0, _remoteport = 0;
private bool _background = true;
/// 构造函数。
public TcpClient()
{
RemoteIP = "127.0.0.1";
RemotePort = 0;
Timeout = 1000;
}
/// 构造函数。
public TcpClient(string ip, int port, int timeout = 1000)
{
RemoteIP = ip;
RemotePort = port;
Timeout = timeout;
}
#endregion
#region accessor
/// 获取或设置监听线程是否为后台线程,默认为“是”。
public bool Background
{
get { return _background; }
set
{
_background = value;
try { if (_listener != null) _listener.IsBackground = value; }
catch (Exception ex) { RaiseExcepted(ex); }
}
}
/// 获取或设置远程计算机的 IP 地址。
public string RemoteIP
{
get { return _remoteip; }
set
{
string vip = value;
if (!NetworkUtility.IsIP(vip)) vip = NetworkUtility.Resolve(vip);
if (!NetworkUtility.IsIP(vip)) vip = "127.0.0.1";
_remoteip = vip;
}
}
/// 获取或设置远程计算机的 TCP 端口号。
public int RemotePort
{
get { return _remoteport; }
set
{
int vport = value;
if (vport < 0) vport = 0;
if (vport > 65535) vport = 65535;
_remoteport = vport;
}
}
/// 获取或设置本地计算机的 IP 地址。
public string LocalIP
{
get { return _localip; }
private set { _localip = string.IsNullOrEmpty(value) ? "" : value; }
}
/// 获取或设置本地计算机的 TCP 端口号。
public int LocalPort
{
get { return _localport; }
private set
{
int vport = value;
if (vport < 0) vport = 0;
if (vport > 65535) vport = 65535;
_localport = vport;
}
}
/// 获取或设置超时时间。
public int Timeout
{
get { return _timeout; }
set { _timeout = (value > 0) ? value : 1; }
}
/// 开始连接,并初始化发送队列。
public void Start()
{
Close(false);
_queue = new Queue();
_provider = new Thread(Provider);
_provider.IsBackground = true;
_provider.Start();
// _are.WaitOne(1000);
}
/// 断开连接。
/// 是否引导 Closed 事件。
public void Close(bool @event = true)
{
CloseThread(ref _provider);
CloseThread(ref _listener);
CloseSocket();
CloseQueue();
_queue = null;
// _are = null;
if (@event) RaiseClosed();
}
/// 向服务端发送数据。
/// 字节数组。
public bool Send(byte[] bytes)
{
if (_socket != null)
{
_queue.Enqueue(bytes);
return true;
}
else
{
var vse = new SocketException(10057);
RaiseExcepted(vse);
return false;
}
}
/// 是否已连接。
public bool Online
{
get
{
try { if (_socket != null) return _socket.Connected; }
catch (Exception ex) { RaiseExcepted(ex); }
return false;
}
}
#endregion
#region logic
private void Listener()
{
var vb = new byte[TcpBuffer.Size];
var vf = 0;
while (true)
{
try
{
if (_socket.Poll(50, SelectMode.SelectWrite))
{
_socket.Blocking = true;
vf = _socket.Receive(vb);
if (vf > 0)
{
var vms = new MemoryStream(vb);
vms.SetLength(vf);
RaiseReceived(vms.ToArray());
vms.Dispose();
}
else
{
if (_socket != null) break;
}
}
}
catch (SocketException ex)
{
if (ex.ErrorCode != 10060) RaiseExcepted(ex);
if (ex.ErrorCode == 10054) break;
}
catch (Exception ex)
{
RaiseExcepted(ex);
// break;
}
}
if (_provider != null)
{
if (_provider.IsAlive) _provider.Abort();
_provider = null;
}
if (_socket != null)
{
_socket.Disconnect(true);
_socket.Close();
_socket = null;
}
CloseThread(ref _provider);
CloseSocket();
CloseQueue();
RaiseClosed();
}
private void Provider()
{
_break = false;
_socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
_socket.SendTimeout = _timeout;
_socket.ReceiveTimeout = _timeout;
//_are = new AutoResetEvent(false);
try
{
_socket.Blocking = true;
_socket.Connect(_remoteip, _remoteport);
if (_socket.Connected)
{
_socket.SendBufferSize = TcpBuffer.Size;
_socket.ReceiveBufferSize = TcpBuffer.Size;
var vrep = (IPEndPoint)_socket.RemoteEndPoint;
var vlep = (IPEndPoint)_socket.LocalEndPoint;
_remoteip = vrep.Address.ToString();
_localip = vlep.Address.ToString();
_localport = vlep.Port;
RaiseConnected();
_listener = new Thread(Listener);
_listener.Start();
// _are.Set();
}
else
{
Close();
return;
}
}
catch (Exception ex)
{
RaiseExcepted(ex);
}
while ((!_break) && (_socket != null))
{
if (_queue.Count > 0)
{
var vb = _queue.Dequeue();
if (vb.Length > 0)
{
try
{
_socket.Send(vb);
RaiseSent(vb);
}
catch (Exception ex)
{
RaiseExcepted(ex);
}
}
else
{
Thread.Sleep(1);
}
}
}
}
private void CloseSocket()
{
if (_socket != null)
{
try
{
_socket.Disconnect(false);
_socket.Close();
}
catch (SocketException ex) { RaiseExcepted(ex); }
catch (Exception ex) { RaiseExcepted(ex); }
_socket = null;
}
}
private void CloseThread(ref Thread thread)
{
if (thread != null)
{
if (thread.IsAlive) thread.Abort();
thread = null;
}
}
private void CloseQueue()
{
if (_queue != null) _queue.Clear();
}
#endregion
}
}