using System;
using System.Net;
using System.Net.Sockets;
using System.Threading;
namespace Splash.Net.Sockets
{
/// <summary>
/// 异步连接状态对象
/// </summary>
internal class AsyncConnectStateObject
{
public ManualResetEvent eventDone;
public TcpClient client;
public Exception exception;
}
/// <summary>
/// 实现TcpClient的异步连接
/// </summary>
public partial class TcpClientPlus
{
/// <summary>
/// 设置连接超时值
/// </summary>
public Int32 ConnectTimeout = Timeout.Infinite;
/// <summary>
/// 异步连接
/// </summary>
/// <param name="hostname">主机名</param>
/// <param name="port">端口号</param>
public void AsyncConnect(String hostname, Int32 port)
{
// 用户定义对象
AsyncConnectStateObject State = new AsyncConnectStateObject
{ // 将事件状态设置为非终止状态,导致线程阻止
eventDone = new ManualResetEvent(false),
client = this,
exception = null
};
// 开始一个对远程主机连接的异步请求
BeginConnect(hostname, port, new AsyncCallback(AsyncConnectCallback), State);
// 等待操作完成信号
if (State.eventDone.WaitOne(ConnectTimeout, false))
{ // 接收到信号
if (State.exception != null) throw State.exception;
}
else
{ // 超时异常
Close();
throw new TimeoutException();
}
}
/// <summary>
/// 异步连接
/// </summary>
/// <param name="address">IP地址</param>
/// <param name="port">端口号</param>
public void AsyncConnect(IPAddress address, Int32 port)
{
// 用户定义对象
AsyncConnectStateObject State = new AsyncConnectStateObject
{ // 将事件状态设置为非终止状态,导致线程阻止
eventDone = new ManualResetEvent(false),
client = this,
exception = null
};
// 开始一个对远程主机连接的异步请求
BeginConnect(address, port, new AsyncCallback(AsyncConnectCallback), State);
// 等待操作完成信号
if (State.eventDone.WaitOne(ConnectTimeout, false))
{ // 接收到信号
if (State.exception != null) throw State.exception;
}
else
{ // 超时异常
Close();
throw new TimeoutException();
}
}
/// <summary>
/// 异步连接回调函数
/// </summary>
/// <param name="ar">异步操作结果</param>
private static void AsyncConnectCallback(IAsyncResult ar)
{
AsyncConnectStateObject State = ar.AsyncState as AsyncConnectStateObject;
try
{ // 异步接受传入的连接尝试
State.client.EndConnect(ar);
}
catch (Exception e)
{ // 异步连接异常
State.exception = e;
}
finally
{ // 将事件状态设置为终止状态,线程继续
State.eventDone.Set();
}
}
}
}