ConnectAsync超时后如何处理套接字?

时间:2017-06-16 18:28:10

标签: c# sockets mono

这篇文章中的答案

建议使用Timer使用ConnectAsync暂停连接尝试。如果发生超时,我不确定如何处理Socket

考虑以下示例

public static void Main (string[] args)
{
    IPEndPoint ep = new IPEndPoint (new IPAddress (new byte []{ 127, 0, 0, 1 }), 9042);
    var socket = new Socket(ep.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
    var connectTimeoutMs = 50;
    var tcs = new TaskCompletionSource<bool> ();
    new Timer ((t) => {
        tcs.SetException(new ConnectionTimeoutException());
        ((Timer) t).Dispose();
    }).Change (connectTimeoutMs, Timeout.Infinite);

    var eventArgs = new SocketAsyncEventArgs { RemoteEndPoint = ep };
    eventArgs.Completed += Finisher (tcs);

    if (socket.ConnectAsync (eventArgs)) {
        // dealt synchronously
    }
    try {
        tcs.Task.Wait (); // actually a ContinueWith 
    } catch (AggregateException e) {
        if (e.InnerException is ConnectionTimeoutException) {
            socket.Dispose (); // is this the appropriate place for this?
        }
    }
    Thread.Sleep (10000);
}
public static EventHandler<SocketAsyncEventArgs> Finisher(TaskCompletionSource<bool> tcs) {
    return (sender, e) => {
        if (e.SocketError != SocketError.Success) {
            tcs.TrySetException (new SocketException ((int)e.SocketError));
        } else {
            tcs.TrySetResult (true);
        }
        e.Dispose ();
    };
}
class ConnectionTimeoutException : SocketException {
    public ConnectionTimeoutException(): base((int) SocketError.TimedOut){}
}

在Mono-3.10.0上,如果发生超时,则会导致致命(未被捕获)ObjectDisposedException

Unhandled Exception:
System.ObjectDisposedException: The object was used after being disposed.
  at System.Net.Sockets.Socket.EndConnect (IAsyncResult result) [0x00016] in /home/user/dev/mono-3.10/mono-3.10.0/mcs/class/System/System.Net.Sockets/Socket.cs:1274 
  at System.Net.Sockets.SocketAsyncEventArgs.ConnectCallback (IAsyncResult ares) [0x00000] in /home/user/dev/mono-3.10/mono-3.10.0/mcs/class/System/System.Net.Sockets/SocketAsyncEventArgs.cs:260 
  at System.Net.Sockets.SocketAsyncEventArgs.DispatcherCB (IAsyncResult ares) [0x000aa] in /home/user/dev/mono-3.10/mono-3.10.0/mcs/class/System/System.Net.Sockets/SocketAsyncEventArgs.cs:234 

因为打电话给

socket.Dispose()

实际上完成了SocketAsyncEventArgs,但首先验证相应的Socket是否已被处置。 This was "corrected" in newer versions of Mono,但它让我想到这是否是在Socket上超时连接尝试的合适模式。是吗?并且Completed事件应该在基础Dispose的{​​{1}}上提出(Socket,不能少)?

解决方案看起来像

SocketError.Success

0 个答案:

没有答案