using System;
using System.Net;
using System.Net.Sockets;
using System.Threading.Tasks;
namespace TNet
{
public class TcpAcceptor: IDisposable
{
private readonly Socket socket;
private readonly SocketAsyncEventArgs asyncEventArgs = new SocketAsyncEventArgs();
public TcpAcceptor(string ip, ushort port, int backLog = 100)
{
this.socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
this.asyncEventArgs.Completed += OnArgsCompletion;
this.socket.Bind(new IPEndPoint(IPAddress.Parse(ip), port));
this.socket.Listen(backLog);
}
public void Dispose()
{
this.socket.Dispose();
}
///
/// SocketAsyncEventArgs Accept回调函数,回调可能已经到了另外的线程
///
///
public Task AcceptAsync()
{
var tcs = new TaskCompletionSource();
try
{
this.asyncEventArgs.UserToken = tcs;
bool ret = this.socket.AcceptAsync(this.asyncEventArgs);
if (!ret)
{
if (this.asyncEventArgs.SocketError == SocketError.Success)
{
var acceptSocket = this.asyncEventArgs.AcceptSocket;
this.asyncEventArgs.AcceptSocket = null;
return Task.FromResult(new NetworkStream(acceptSocket, true));
}
tcs.TrySetException(
new InvalidOperationException(
this.asyncEventArgs.SocketError.ToString()));
}
}
catch (Exception ex)
{
tcs.TrySetException(ex);
}
return tcs.Task;
}
private static void OnArgsCompletion(object sender, SocketAsyncEventArgs e)
{
var tcs = (TaskCompletionSource) e.UserToken;
if (e.SocketError != SocketError.Success)
{
tcs.TrySetException(new InvalidOperationException(e.SocketError.ToString()));
return;
}
var acceptSocket = e.AcceptSocket;
e.AcceptSocket = null;
tcs.SetResult(new NetworkStream(acceptSocket, true));
}
}
}