我正在使用带有tcp的套接字将数据发送到远程服务器。我正在使用ManualResetEvent和System.Timers.Timer来缓解无法连接到远程主机的情况。要么使用成功的连接调用ConnectedCallback,否则连接将设置ManualResetEvent或它无法连接,并退回到计时器,计时器应关闭套接字并告诉主线程继续并处理未连接状态。
该逻辑工作正常,因为我使用简单的布尔值进行了尝试,不确定是否使用了ManualResetEvent对象?
我还应该添加一个针对.NET Frameworks 4.6的类库,它位于Mono中 代码:
public void StartConnect()
{
ConnectCue.Reset();
// Retrieve server config
var serverConfig = LocalConfig.GetConfig<VmeServerConfig>();
var ipHostInfo = Dns.GetHostEntry(serverConfig.BaseAddress);
var ipAddress = ipHostInfo.AddressList[0];
#if DEBUG
var remoteEp = new IPEndPoint(IPAddress.Loopback, Port);
#else
var remoteEp = new IPEndPoint(ipAddress, Port);
#endif
// Create a TCP/IP socket.
TcpSocket = new Socket(ipAddress.AddressFamily,
SocketType.Stream, ProtocolType.Tcp)
{
ReceiveTimeout = serverConfig.Timeout * 1000,
SendTimeout = serverConfig.Timeout * 1000
};
// Connect to the remote endpoint
TcpSocket.BeginConnect(remoteEp,
new AsyncCallback(ConnectedCallback), TcpSocket);
// Timer that will signal main thread to continue
var timeoutTimer = new System.Timers.Timer()
{
Interval = serverConfig.Timeout * 1000,
AutoReset = false,
Enabled = true
};
// Event to singal thread to continue if connection takes long
timeoutTimer.Elapsed += delegate (object sender, ElapsedEventArgs args)
{
// Nothing to do here
if (IsConnected)
return;
#if DEBUG
Interface.RootLogger.Write(LogType.Warning, "TICK: Not connected");
#endif
ConnectCue.Set();
TcpSocket.Shutdown(SocketShutdown.Both);
TcpSocket.Close();
};
timeoutTimer.Start();
// Cue the main thread
ConnectCue.WaitOne();
if (IsConnected) return;
//Not connected, handle stuff...
}
/// <summary>
/// Invoked when a connection to the service has been made or not been made
/// </summary>
/// <param name="ar"></param>
private void ConnectedCallback(IAsyncResult ar)
{
// Retrieve the socket from the state object.
var tcpSocket = (Socket)ar.AsyncState;
// If we couldn't then its been handled by timeout
if (!tcpSocket.Connected)
return;
try
{
//doing stuff..
}
catch (System.Exception)
{
tcpSocket.Close();
throw;
}
// Signal the main thread that the connection has been made.
ConnectCue.Set();
}