using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using Top.Api;
namespace Taobao.Top.Link.Channel.TCP
{
/// server channel bind on raw tcp, just impl an easy server
///
public class TcpServerChannel : ServerChannel
{
private bool _running;
private TcpListener _tcpListener;
private Thread _acceptWorker;
private IOWorker _ioWorker;
private int _ioWorkerCount;
private LinkedList _tcpClients;
public delegate void IOWorker(ITopLogger log, TcpServerChannel server, TcpClient tcpClient);
/// init tcp server channel
///
///
///
/// deal with networkstream
public TcpServerChannel(ITopLogger log
, int port
, IOWorker ioWorker)
: base(log
, port)
{
this._ioWorker = ioWorker;
this._tcpClients = new LinkedList();
}
public override void Start()
{
this._running = true;
this._tcpListener = new TcpListener(IPAddress.Any, this.Port);
this._tcpListener.Start();
this._acceptWorker = new Thread(() =>
{
while (this._running)
{
try
{
var client = this._tcpListener.AcceptTcpClient();
this._tcpClients.AddLast(client);
ThreadPool.QueueUserWorkItem((state) =>
{
try { this.AcceptSocket(client); }
catch (Exception e)
{
this.InternalOnError(e);
this._tcpClients.Remove(client);
}
});
}
catch (SocketException) { break; }
catch (Exception e)
{
this.InternalOnError(e);
break;
}
}
});
this._acceptWorker.IsBackground = true;
this._acceptWorker.Start();
}
public override void Stop()
{
this._running = false;
this._acceptWorker.Abort();
this._tcpListener.Stop();
}
private void AcceptSocket(TcpClient client)
{
if (this._ioWorker == null)
return;
var logName = "IO-Worker#" + (++this._ioWorkerCount);
ThreadPool.QueueUserWorkItem(o =>
this._ioWorker(Log.Instance, this, client));
}
private void InternalOnError(Exception e)
{
if (this.OnError != null)
this.OnError(this, new ChannelContext(e));
}
}
}