3

サーバーが通信しているソケットのファイル記述子の fd_set を保持するある種のサーバー アプリケーション (C++ で) を作成しています。 \書き込みます。私は定期的に select() を (タイムアウトなしで) ブロックし、読み取り準備が整い、提供する 2 つの fd_set の例外的な状態を待ちます。

反対側で閉じられているソケットはすべてexceptfdsに表示されると考え始めましたが、読み進めるうちに、必ずしもそうではないことがわかりました。select()のman ページには、exceptfds が監視されている例外についてはあまり書かれていません。さらに、私の理解では、例外的な条件と見なされるものはOS によって異なります (私自身は Ubnubt 11.10 を使用しています)。例外。

また、socket(7) の man ページには、ソケットが送信できる 2 種類のシグナルが記載されています。

  1. SIGPIPE - シャットダウンされたソケットへの書き込み時に送信されます。
  2. SIGIO - I/O イベントが発生したときに送信されます。

残念ながら、何が I/O イベントであるかについては言及されていません。とにかく、シャットダウンはすべての人にとって I/O イベントとは見なされない可能性があります (私自身が良い例です)。

だから私が求めているのは、ソケットが閉じているときにシグナルを送信するか、それ自体をexceptfdsに挿入するか、または他の方法で積極的にプロンプ​​トを表示することはできますか?

ありがとう、シェイ

4

5 に答える 5

3

通常、ソケットがリモート ピアによって閉じられると、( の目的で)読み取り可能になり、そこから読み取るとゼロバイトが返されます。この 0 バイトの読み取りは、相手側がソケットを正常に閉じたことを示します。これは例外的な条件とは見なされません。select()

于 2012-06-19T20:15:41.187 に答える
2

私自身のアプリケーション内で、select()(読み取りイベントの) 呼び出しがファイル記述子に返されると、ioctl()読み取り用のバッファーにどれだけあるかを確認するために呼び出します。ゼロ バイトがある場合は、それを使用して接続が閉じていることを示します。

この答えからLinuxソケットを書き始めたとき、私は実際にこれを見つけましたここスタックオーバーフロー

于 2012-06-19T20:17:36.160 に答える
0

「アダプター」を使用して、このイベントを他の多くのイベントから抽象化することもできます。

たとえば、私のプロジェクトの1つから...

    #region Copyright
    /*
    This file came from Managed Media Aggregation, You can always find the latest version @ https://net7mma.codeplex.com/      
 */
#endregion

namespace Media.Sockets
{
    #region NetworkConnection

    /// <summary>
    /// Represents a <see cref="Connection"/> specific to the Network.
    /// </summary>
    public class NetworkConnection : Connection, Common.ISocketReference
    {
        #region NetworkConnectionState

        [System.Flags]
        protected enum NetworkConnectionState : long
        {
            None = 0,
            Initialized = 1,
            Bound = 2,
            Connected = 4,
        }

        #endregion

        #region Fields

        /// <summary>
        /// Created in <see cref="CreateWaitHandle"/>, Disposed in <see cref="Dispose"/>.
        /// </summary>
        Common.Extensions.WaitHandle.DisposableWaitHandle WaitHandle;

        /// <summary>
        /// The date and time when the Connection was started.
        /// </summary>
        protected System.DateTime LasRemoteConnectionStartedDateTime;

        /// <summary>
        /// The date and time when the Connection was started.
        /// </summary>
        protected System.DateTime LastRemoteConnectionCompletedDateTime;

        #endregion

        #region Properties

        /// <summary>
        /// Gets the amount of time taken to connect to the <see cref="RemoteEndPoint"/>
        /// </summary>
        public System.TimeSpan RemoteConnectionTime { get { return LastRemoteConnectionCompletedDateTime - LasRemoteConnectionStartedDateTime; } }

        /// <summary>
        /// The <see cref="System.Net.NetworkInformation.NetworkInterface"/> assoicated with the NetworkConnection.
        /// </summary>
        public System.Net.NetworkInformation.NetworkInterface NetworkInterface { get; protected set; }

        /// <summary>
        /// The <see cref="System.Net.Sockets.Socket"/> assoicated with the NetworkConnection.
        /// </summary>
        public System.Net.Sockets.Socket ConnectionSocket { get; protected set; }

        /// <summary>
        /// Indicates if the NetworkConnection has a <see cref="NetworkInterface"/> which is not null.
        /// </summary>
        public bool HasNetworkInterface { get { return NetworkInterface != null; } }

        /// <summary>
        /// The <see cref="System.Net.EndPoint"/> from which this NetworkConnection connects to the <see cref="RemoteEndPoint"/>
        /// </summary>
        public System.Net.EndPoint LocalEndPoint { get; protected set; }

        /// <summary>
        /// Indicates if this NetworkConnection has a <see cref="LocalEndPoint"/> which is not null.
        /// </summary>
        public bool HasLocalEndPoint { get { return LocalEndPoint != null; } }

        /// <summary>
        /// The <see cref="System.Net.EndPoint"/> from which this NetworkConnection is connected to via the <see cref="LocalEndPoint"/>
        /// </summary>
        public System.Net.EndPoint RemoteEndPoint { get; protected set; }

        /// <summary>
        /// Indicates if this NetworkConnection has a <see cref="RemoteEndPoint"/> which is not null.
        /// </summary>
        public bool HasRemoteEndPoint { get { return RemoteEndPoint != null; } }

        /// <summary>
        /// Indicates the <see cref="NetworkConnectionState"/> assoicated with this NetworkConnection
        /// </summary>
        protected NetworkConnectionState NetworkConnectionFlags
        {
            get { return (NetworkConnectionState)Flags; }
            set { Flags = (long)value; }
        }

        #endregion

        #region Constructor

        public NetworkConnection()
            : base() { }

        public NetworkConnection(string name, bool shouldDispose)
            : base(name, shouldDispose) { }

        public NetworkConnection(System.Net.Sockets.Socket existingSocket, bool ownsHandle, bool shouldDispose)
            : this("System.Net.Socket-" + ownsHandle.ToString(), shouldDispose)
        {
            if (existingSocket == null) throw new System.ArgumentNullException("existingSocket");

            //Assign the ConnectionSocket
            ConnectionSocket = existingSocket;

            //Flag Initialized.
            FlagInitialized();

            //Assign the NetworkInterface
            NetworkInterface = Common.Extensions.NetworkInterface.NetworkInterfaceExtensions.GetNetworkInterface(ConnectionSocket);

            //Create a WaitHandle 
            CreateWaitHandle(ConnectionSocket.Handle, ownsHandle);

            //Check IsBound
            if (ConnectionSocket.IsBound)
            {
                //Flag Bound.
                FlagBound();

                //Serialize and Assign LocalEndPoint
                LocalEndPoint = existingSocket.LocalEndPoint;
            }

            //Check Connected
            if (ConnectionSocket.Connected)
            {
                //Sample the clock
                LasRemoteConnectionStartedDateTime = System.DateTime.UtcNow;

                //Serialize and Assign RemoteEndPoint
                RemoteEndPoint = existingSocket.RemoteEndPoint;

                //Call Connect to FlagConnected and call base logic.
                Connect();

                //Sample the clock
                LastRemoteConnectionCompletedDateTime = System.DateTime.UtcNow;
            }
        }

        #endregion

        #region NetworkChange Event Handlers

        void NetworkChange_NetworkAvailabilityChanged(object sender, System.Net.NetworkInformation.NetworkAvailabilityEventArgs e)
        {
            Refresh();
        }

        void NetworkChange_NetworkAddressChanged(object sender, System.EventArgs e)
        {
            Refresh();
        }

        #endregion

        #region Bound

        protected void FlagBound()
        {
            //Indicate Bound
            Flags |= (long)NetworkConnectionState.Bound;
        }

        protected void UnFlagBound()
        {
            //Indicate not Bound
            Flags &= (long)NetworkConnectionState.Bound;
        }

        #endregion

        #region Initialize

        protected void FlagInitialized()
        {
            //Indicate Connected
            Flags |= (long)NetworkConnectionState.Initialized;
        }

        protected void UnFlagInitialized()
        {
            //Indicate Not Connected
            Flags &= (long)NetworkConnectionState.Initialized;
        }

        public virtual void Initialize(bool registerForEvents)
        {
            //Check not already Initialized.
            if (false == NetworkConnectionFlags.HasFlag(NetworkConnectionState.Initialized))
            {
                //Indicate Initialized
                FlagInitialized();

                if (registerForEvents)
                {
                    //Attach events
                    System.Net.NetworkInformation.NetworkChange.NetworkAddressChanged += NetworkChange_NetworkAddressChanged;

                    System.Net.NetworkInformation.NetworkChange.NetworkAvailabilityChanged += NetworkChange_NetworkAvailabilityChanged;
                }
            }
        }

        #endregion

        #region Refresh

        public override void Refresh()
        {
            base.Refresh();
        }

        #endregion

        #region CreateConnectionSocket

        public void CreateConnectionSocket(System.Net.Sockets.AddressFamily addressFamily, System.Net.Sockets.SocketType socketType, System.Net.Sockets.ProtocolType protocolType)
        {
            if (ConnectionSocket == null)
            {
                ConnectionSocket = new System.Net.Sockets.Socket(addressFamily, socketType, protocolType);

                CreateWaitHandle(ConnectionSocket.Handle, true);
            }
        }

        #endregion

        #region CreateWaitHandle

        public void CreateWaitHandle(System.IntPtr handle, bool ownsHandle)
        {
            if (WaitHandle == null)
            {
                WaitHandle = new Common.Extensions.WaitHandle.DisposableWaitHandle(handle, ownsHandle);
            }
        }

        #endregion

        #region Connect

        protected void FlagConnected()
        {
            //Indicate Connected
            Flags |= (long)NetworkConnectionState.Connected;
        }

        protected void UnFlagConnected()
        {
            //Indicate Not Connected
            Flags &= (long)NetworkConnectionState.Connected;
        }

        public override void Connect()
        {
            //Check not already Connected.
            if (false == NetworkConnectionFlags.HasFlag(NetworkConnectionState.Connected))
            {
                //Check IsEstablished
                if (IsEstablished) return;

                if (NetworkInterface == null) throw new System.InvalidOperationException("NetworkInterface must be assigned before calling Connect.");

                if (LocalEndPoint == null) throw new System.InvalidOperationException("LocalEndPoint must be assigned before calling Connect.");

                if (RemoteEndPoint == null) throw new System.InvalidOperationException("RemoteEndPoint must be assigned before calling Connect.");

                //Set established
                base.Connect();

                //Indicate Connected
                FlagConnected();

                //Refresh the connection
                Refresh();
            }
        }

        /// <summary>
        /// Creates the <see cref="CreateConnectionSocket"/> using the specified options and connects the socket.
        /// Assigns <see cref="LocalEndPoint"/> and <see cref="RemoteEndPoint"/>
        /// </summary>
        /// <param name="addressFamily"></param>
        /// <param name="socketType"></param>
        /// <param name="protocolType"></param>
        /// <param name="addressList"></param>
        /// <param name="port"></param>
        public virtual void Connect(System.Net.Sockets.AddressFamily addressFamily, System.Net.Sockets.SocketType socketType, System.Net.Sockets.ProtocolType protocolType, System.Net.IPAddress[] addressList, int port)
        {
            try
            {
                //Create the socket
                CreateConnectionSocket(addressFamily, socketType, protocolType);

                //Sample the clock
                LasRemoteConnectionStartedDateTime = System.DateTime.UtcNow;

                //Connect the socket
                ConnectionSocket.Connect(addressList, port);

                //Sample the clock
                LastRemoteConnectionCompletedDateTime = System.DateTime.UtcNow;
            }
            finally
            {
                //Assign the NetworkInterface
                NetworkInterface = Common.Extensions.NetworkInterface.NetworkInterfaceExtensions.GetNetworkInterface(ConnectionSocket);

                //Assign the LocalEndPoint
                LocalEndPoint = (System.Net.IPEndPoint)ConnectionSocket.LocalEndPoint;

                //Assign the RemoteEndPoint
                RemoteEndPoint = (System.Net.IPEndPoint)ConnectionSocket.RemoteEndPoint;

                //Call Connect to FlagConnected and call base logic.
                Connect();
            }
        }

        #endregion

        #region Disconnect

        public virtual void Disconnect(bool allowReuse = false)
        {
            //Check not already Connected.
            if (((NetworkConnectionState)Flags).HasFlag(NetworkConnectionState.Connected))
            {
                ConnectionSocket.Disconnect(allowReuse);

                base.Disconnect();

                UnFlagConnected();

                Refresh();
            }
        }

        public override void Disconnect()
        {
            Disconnect(false);
        }

        #endregion

        #region Dispose

        protected override void Dispose(bool disposing)
        {
            base.Dispose(disposing);

            using (WaitHandle)
            {
                System.Net.NetworkInformation.NetworkChange.NetworkAddressChanged -= NetworkChange_NetworkAddressChanged;

                System.Net.NetworkInformation.NetworkChange.NetworkAvailabilityChanged -= NetworkChange_NetworkAvailabilityChanged;

                ConnectionSocket = null;

                LocalEndPoint = RemoteEndPoint = null;

                NetworkInterface = null;
            }
        }

        #endregion

        System.Collections.Generic.IEnumerable<System.Net.Sockets.Socket> Common.ISocketReference.GetReferencedSockets()
        {
            yield return ConnectionSocket;
        }
    }

    #endregion
}

「接続」基本クラスが必要な場合は、これを参照できます

#region Copyright
/*
This file came from Managed Media Aggregation, You can always find the latest version @ https://net7mma.codeplex.com/

 Julius.Friedman@gmail.com / (SR. Software Engineer ASTI Transportation Inc. http://www.asti-trans.com)   
 * v//
 */
#endregion


namespace Media.Sockets
{
    #region Connection

    /// <summary>
    /// Provides a base class to facilitate the concept of a Connection.
    /// </summary>
    public abstract class Connection : Common.BaseDisposable
    {
        #region Statics

        /// <summary>
        /// A string with the format of:
        ///     `TypeName Id Flags Name`
        /// </summary>
        const string FormatString = "{0} {1} ({2}) {3}";

        #endregion

        #region Properties

        /// <summary>
        /// The unique identifier assoicated with this instance.
        /// </summary>
        public readonly System.Guid Id = System.Guid.NewGuid();

        /// <summary>
        /// The date and time the instance was created.
        /// </summary>
        public readonly System.DateTime Created = System.DateTime.UtcNow;

        /// <summary>
        /// The name assigned to this instance.
        /// </summary>
        public readonly string Name;

        /// <summary>
        /// Indicates if <see cref="Disconnect"/> will be called when disposing.
        /// </summary>
        public bool IsPersistent
        {
            get
            {
                return ShouldDispose == false;
            }
            set
            {
                ShouldDispose = value == false;
            }
        }

        /// <summary>
        /// Provided for derived implementations
        /// </summary>
        protected long Flags { get; set; }

        /// <summary>
        /// Indicates if the Connection is established.
        /// </summary>
        public virtual bool IsEstablished { get; protected set; }

        /// <summary>
        /// The date and time the Connection was established.
        /// </summary>
        public System.DateTime EstablishedDateTime { get; protected set; }

        /// <summary>
        /// The amount of time the connection has been established.
        /// </summary>
        public System.TimeSpan TimeEstablished { get { return IsEstablished ? System.DateTime.UtcNow - EstablishedDateTime : System.TimeSpan.Zero; } }

        #endregion

        #region Connect

        /// <summary>
        /// If <see cref="IsDisposed"/> is false, Sets <see cref="IsEstablished"/> to true.
        /// </summary>
        public virtual void Connect()
        {
            if (IsDisposed) return;

            EstablishedDateTime = System.DateTime.UtcNow;

            IsEstablished = true;
        }

        #endregion

        #region Disconnect

        /// <summary>
        /// If <see cref="IsDisposed"/> is false, Sets <see cref="IsEstablished"/> to false.
        /// </summary>
        public virtual void Disconnect()
        {
            if (IsDisposed) return;

            IsEstablished = false;
        }

        #endregion

        #region Refresh

        /// <summary>
        /// Refreshes the details of the Connection.
        /// Throws a <see cref="System.ObjectDisposedException"/> if <see cref="IsDisposed"/> is true.
        /// </summary>
        public virtual void Refresh()
        {
            CheckDisposed();
        }

        #endregion

        #region Dispose

        /// <summary>
        /// If <see cref="IsDisposed"/> is True the call returns immediately.
        /// Calls <see cref="Disconnect"/> if <see cref="IsPersistent"/> is False and calls <see cref="Common.BaseDisposable.Dispose"/>
        /// </summary>
        public override void Dispose()
        {
            if (IsDisposed) return;

            if (false == IsPersistent) Disconnect();

            base.Dispose();
        }

        #endregion

        #region Constructor

        public Connection(string name, bool shouldDispose)
            : base(shouldDispose)
        {
            Name = name;
        }

        public Connection()
            : this(string.Empty, true) { }

        #endregion

        #region ToString

        public override string ToString()
        {
            return string.Format(FormatString, GetType().Name.ToString(), Id.ToString(), Flags, Name);
        }

        #endregion

    }

    #endregion
}
于 2015-07-15T22:54:56.010 に答える
0

他のクラスを実装した IPNetworkConnection の例として、このコードを参照できます。

#region Copyright
/*
This file came from Managed Media Aggregation, You can always find the latest version @ https://net7mma.codeplex.com/      
 * v//
 */
#endregion

namespace Media.Sockets
{
#region IPNetworkConnection

/// <summary>
/// Represents a <see cref="NetworkConnection"/> which utilizes the IP Protocol.
/// </summary>
public class IPNetworkConnection : NetworkConnection
{
    #region Statics

    public static System.Net.NetworkInformation.IPGlobalProperties IPGlobalProperties
    {
        get { return System.Net.NetworkInformation.IPGlobalProperties.GetIPGlobalProperties(); }
    }

    #region CreateIPHostEntry

    public static System.Net.IPHostEntry CreateIPHostEntry(System.Net.IPAddress address, string hostName, params string[] aliases)
    {
        return CreateIPHostEntry(Common.Extensions.Object.ObjectExtensions.ToArray<System.Net.IPAddress>(address),
            hostName,
            aliases);
    }

    public static System.Net.IPHostEntry CreateIPHostEntry(string hostName, params System.Net.IPAddress[] address)
    {
        return CreateIPHostEntry(address, hostName, null);
    }

    public static System.Net.IPHostEntry CreateIPHostEntry(System.Net.IPAddress[] addresses, string hostName, params string[] aliases)
    {
        return new System.Net.IPHostEntry()
        {
            AddressList = Common.Extensions.Array.ArrayExtensions.IsNullOrEmpty(addresses) ? Common.Extensions.Object.ObjectExtensions.ToArray<System.Net.IPAddress>(System.Net.IPAddress.None) : addresses,
            Aliases = Common.Extensions.Array.ArrayExtensions.IsNullOrEmpty(aliases) ? Common.Extensions.Object.ObjectExtensions.ToArray<string>(string.Empty) : aliases,
            HostName = hostName ?? string.Empty
        };
    }

    #endregion

    #endregion

    #region Properties

    /// <summary>
    /// Gets the <see cref="System.Net.NetworkInformation.IPInterfaceProperties"/> assoicated with the <see cref="NetworkInterface"/>
    /// </summary>
    public System.Net.NetworkInformation.IPInterfaceProperties IPInterfaceProperties
    {
        get { return HasNetworkInterface ? NetworkInterface.GetIPProperties() : null; }
    }

    /// <summary>
    /// Indicates if the <see cref="RemoteIPEndPoint"/> has a <see cref="System.Net.NetworkInformation.NetworkInterface"/> on this computer.
    /// </summary>
    public bool IsLocalConnection { get { return HasRemoteIPEndPoint && Common.Extensions.NetworkInterface.NetworkInterfaceExtensions.GetNetworkInterface(RemoteIPEndPoint) != null; } }

    /// <summary>
    /// Indicates if the <see cref="RemoteIPEndPoint"/> is from within the same network as this computer.
    /// </summary>
    public bool IsIntranetConnection
    {
        get { return false == IsLocalConnection && Common.Extensions.IPAddress.IPAddressExtensions.IsOnIntranet(RemoteIPEndPoint.Address); }
    }

    #region Local        

    /// <summary>
    /// The <see cref="System.Net.IPHostEntry"/> assoicated with the <see cref="LocalIPEndPoint"/>
    /// </summary>
    public System.Net.IPHostEntry LocalIPHostEntry { get; protected set; }

    /// <summary>
    /// Indicates if the <see cref="LocalIPHostEntry"/> is not null.
    /// </summary>
    public bool HasLocalIPHostEntry { get { return LocalIPHostEntry != null; } }

    /// <summary>
    /// Gets or sets the <see cref="LocalEndPoint"/>.
    /// 
    /// If the <see cref="LocalEndPoint"/> is not a <see cref="System.Net.IPEndPoint"/> a <see cref="System.InvalidOperationException"/> will be thrown.
    /// </summary>
    public System.Net.IPEndPoint LocalIPEndPoint
    {
        get { return (System.Net.IPEndPoint)LocalEndPoint; }
        set
        {
            if (false == LocalEndPoint is System.Net.IPEndPoint) throw new System.InvalidOperationException("LocalEndPoint is not a System.Net.IPEndPoint");

            LocalEndPoint = value;
        }
    }

    /// <summary>
    /// Indicates if the <see cref="LocalIPEndPoint"/> is not null.
    /// </summary>
    public bool HasLocalIPEndPoint { get { return LocalIPEndPoint != null; } }

    #endregion

    #region Dhcp

    /// <summary>
    /// Gets the <see cref="System.Net.NetworkInformation.IPAddressCollection"/> assoicated with the <see cref="IPInterfaceProperties"/>
    /// </summary>
    public virtual System.Net.NetworkInformation.IPAddressCollection DhcpServerAddresses
    {
        get
        {
            return IPInterfaceProperties.DhcpServerAddresses;
        }
    }

    /// <summary>
    /// Indicates if the IPNetworkConnection utilized Dhcp
    /// </summary>
    public bool UsesDhcp
    {
        get
        {
            return DhcpServerAddresses.Count > 0; /* && DhcpLeaseLifetime != System.TimeSpan.MinValue;*/
        }
    }

    //Could make a Superset class of to unify paths..
    //System.Net.NetworkInformation.IPAddressInformationCollection ipAddressCollection;

    /// <summary>
    /// If <see cref="UsesDhcp"/> the amount of time of the IPAddress is leased according the <see cref="System.Net.NetworkInformation.IPAddressInformation"/> assoicated with the <see cref="LocalIPEndPoint"/>.
    /// 
    /// If the <see cref="LocalIPEndPoint"/> is not found in the leased <see cref="System.Net.NetworkInformation.IPAddressInformation"/> then <see cref="Common.Extensions.TimeSpan.TimeSpanExtensions.InfiniteTimeSpan"/> is returned.
    /// </summary>
    public System.TimeSpan DhcpLeaseLifetime
    {
        get
        {
            //If there is no Dhcp server the DhcpLeaveLifeTime is 0
            if (false == UsesDhcp) return System.TimeSpan.Zero;

            //Check Multicast if the address IsMulticast
            if (Common.Extensions.IPAddress.IPAddressExtensions.IsMulticast(LocalIPEndPoint.Address))
            {
                System.Net.NetworkInformation.MulticastIPAddressInformationCollection multicastIPAddressInformationCollection = IPInterfaceProperties.MulticastAddresses;

                foreach (System.Net.NetworkInformation.MulticastIPAddressInformation multicastIPAddressInformation in multicastIPAddressInformationCollection)
                {
                    if (multicastIPAddressInformation.Address.Equals(LocalIPEndPoint.Address))
                    {
                        return System.TimeSpan.FromSeconds(multicastIPAddressInformation.DhcpLeaseLifetime);
                    }
                }
            }
            else //Check Unicast otherwise
            {
                System.Net.NetworkInformation.UnicastIPAddressInformationCollection unicastIPAddressInformationCollection = IPInterfaceProperties.UnicastAddresses;

                foreach (System.Net.NetworkInformation.UnicastIPAddressInformation unicastIPAddressInformation in unicastIPAddressInformationCollection)
                {
                    if (unicastIPAddressInformation.Address.Equals(LocalIPEndPoint.Address))
                    {
                        return System.TimeSpan.FromSeconds(unicastIPAddressInformation.DhcpLeaseLifetime);
                    }
                }
            }

            //Could not find a an IPAddress which matched the LocalIPEndPoint, indicate infinite timeout.
            return Common.Extensions.TimeSpan.TimeSpanExtensions.InfiniteTimeSpan;
        }
    }

    /// <summary>
    /// If <see cref="UsesDhcp"/> Gets the number of seconds remaining during which this address is valid.
    /// 
    /// If the <see cref="LocalIPEndPoint"/> is not found in the leased <see cref="System.Net.NetworkInformation.IPAddressInformation"/> then <see cref="Common.Extensions.TimeSpan.TimeSpanExtensions.InfiniteTimeSpan"/> is returned.
    /// </summary>
    public System.TimeSpan DhcpAddressValidLifetime
    {
        get
        {
            //If there is no Dhcp server the DhcpLeaveLifeTime is 0
            if (false == UsesDhcp) return System.TimeSpan.Zero;

            //Check Multicast if the address IsMulticast
            if (Common.Extensions.IPAddress.IPAddressExtensions.IsMulticast(LocalIPEndPoint.Address))
            {
                System.Net.NetworkInformation.MulticastIPAddressInformationCollection multicastIPAddressInformationCollection = IPInterfaceProperties.MulticastAddresses;

                foreach (System.Net.NetworkInformation.MulticastIPAddressInformation multicastIPAddressInformation in multicastIPAddressInformationCollection)
                {
                    if (multicastIPAddressInformation.Address.Equals(LocalIPEndPoint.Address))
                    {
                        return System.TimeSpan.FromSeconds(multicastIPAddressInformation.AddressValidLifetime);
                    }
                }
            }
            else //Check Unicast otherwise
            {
                System.Net.NetworkInformation.UnicastIPAddressInformationCollection unicastIPAddressInformationCollection = IPInterfaceProperties.UnicastAddresses;

                foreach (System.Net.NetworkInformation.UnicastIPAddressInformation unicastIPAddressInformation in unicastIPAddressInformationCollection)
                {
                    if (unicastIPAddressInformation.Address.Equals(LocalIPEndPoint.Address))
                    {
                        return System.TimeSpan.FromSeconds(unicastIPAddressInformation.AddressValidLifetime);
                    }
                }
            }

            //Could not find a an IPAddress which matched the LocalIPEndPoint, indicate infinite timeout.
            return Common.Extensions.TimeSpan.TimeSpanExtensions.InfiniteTimeSpan;
        }
    }

    /// <summary>
    /// If <see cref="UsesDhcp"/> Gets the number of seconds remaining during which this address is the preferred address.
    /// 
    /// If the <see cref="LocalIPEndPoint"/> is not found in the leased <see cref="System.Net.NetworkInformation.IPAddressInformation"/> then <see cref="Common.Extensions.TimeSpan.TimeSpanExtensions.InfiniteTimeSpan"/> is returned.
    /// </summary>
    public System.TimeSpan DhcpAddressPreferredLifetime
    {
        get
        {
            //If there is no Dhcp server the DhcpLeaveLifeTime is 0
            if (false == UsesDhcp) return System.TimeSpan.Zero;

            //Check Multicast if the address IsMulticast
            if (Common.Extensions.IPAddress.IPAddressExtensions.IsMulticast(LocalIPEndPoint.Address))
            {
                System.Net.NetworkInformation.MulticastIPAddressInformationCollection multicastIPAddressInformationCollection = IPInterfaceProperties.MulticastAddresses;

                foreach (System.Net.NetworkInformation.MulticastIPAddressInformation multicastIPAddressInformation in multicastIPAddressInformationCollection)
                {
                    if (multicastIPAddressInformation.Address.Equals(LocalIPEndPoint.Address))
                    {
                        return System.TimeSpan.FromSeconds(multicastIPAddressInformation.AddressPreferredLifetime);
                    }
                }
            }
            else //Check Unicast otherwise
            {
                System.Net.NetworkInformation.UnicastIPAddressInformationCollection unicastIPAddressInformationCollection = IPInterfaceProperties.UnicastAddresses;

                foreach (System.Net.NetworkInformation.UnicastIPAddressInformation unicastIPAddressInformation in unicastIPAddressInformationCollection)
                {
                    if (unicastIPAddressInformation.Address.Equals(LocalIPEndPoint.Address))
                    {
                        return System.TimeSpan.FromSeconds(unicastIPAddressInformation.AddressPreferredLifetime);
                    }
                }
            }

            //Could not find a an IPAddress which matched the LocalIPEndPoint, indicate infinite timeout.
            return Common.Extensions.TimeSpan.TimeSpanExtensions.InfiniteTimeSpan;
        }
    }

    #endregion

    #region Remote

    /// <summary>
    /// Provides information about the <see cref="RemoteEndPoint"/>.Address
    /// </summary>
    public System.Net.NetworkInformation.IPAddressInformation RemoteAddressInformation { get; protected set; }

    /// <summary>
    /// Indicates if the <see cref="RemoteAddressInformation"/> is not null.
    /// </summary>
    public bool HasRemoteAddressInformation { get { return RemoteAddressInformation != null; } }

    /// <summary>
    /// The <see cref="System.Net.IPHostEntry"/> assoicated with the <see cref="RemoteIPEndPoint"/>
    /// </summary>
    public System.Net.IPHostEntry RemoteIPHostEntry { get; protected set; }

    /// <summary>
    /// Indicates if the <see cref="RemoteIPHostEntry"/> is not null.
    /// </summary>
    public bool HasRemoteIPHostEntry { get { return RemoteIPHostEntry != null; } }

    /// <summary>
    /// Gets or sets the <see cref="RemoteEndPoint"/>.
    /// 
    /// If the <see cref="RemoteEndPoint"/> is not a <see cref="System.Net.IPEndPoint"/> a <see cref="System.InvalidOperationException"/> will be thrown.
    /// </summary>
    public System.Net.IPEndPoint RemoteIPEndPoint
    {
        get { return (System.Net.IPEndPoint)RemoteEndPoint; }
        set
        {
            if (false == RemoteEndPoint is System.Net.IPEndPoint) throw new System.InvalidOperationException("RemoteEndPoint is not a System.Net.IPEndPoint");

            RemoteEndPoint = value;
        }
    }

    /// <summary>
    /// Indicates if the <see cref="RemoteEndPoint"/> is a <see cref="System.Net.IPEndPoint"/>
    /// </summary>
    public bool HasRemoteIPEndPoint { get { return RemoteIPEndPoint != null; } }

    #endregion

    #endregion

    #region Constructor

    /// <summary>
    /// Creates a new NetworkConnection with the given.
    /// </summary>
    /// <param name="remoteIPHostEntry">given</param>
    public IPNetworkConnection(System.Net.IPHostEntry remoteIPHostEntry)
        : base()
    {
        if (remoteIPHostEntry == null) throw new System.ArgumentNullException("remoteIPHostEntry");

        RemoteIPHostEntry = remoteIPHostEntry;            
    }

    /// <summary>
    /// Creates a new NetworkConnection by resolving the given using <see cref="System.Net.Dns.GetHostEntry"/>
    /// </summary>
    /// <param name="hostNameOrAddress">given</param>
    public IPNetworkConnection(string hostNameOrAddress) :
        this(System.Net.Dns.GetHostEntry(hostNameOrAddress))
    {
        RemoteAddressInformation = new IPAddressInformation(System.Net.IPAddress.None, true, false);
    }

    /// <summary>
    /// Creates a new NetworkConnection and <see cref="new System.Net.IPHostEntry"/> using the given address.
    /// </summary>
    /// <param name="address">The address</param>
    public IPNetworkConnection(System.Net.IPAddress address) :
        this(CreateIPHostEntry(string.Empty, address))
    {
        RemoteAddressInformation = new IPAddressInformation(System.Net.IPAddress.None, false, false);
    }

    public IPNetworkConnection(System.Uri uri) : this(uri.DnsSafeHost) { }

    #endregion

    #region Refresh

    /// <summary>
    /// If <see cref="HasNetworkInterface"/> is True And <see cref="HasLocalIPEndPoint"/> then <see cref="NetworkInterface"/> is updated using <see cref="Common.Extensions.NetworkInterface.NetworkInterfaceExtensions.GetNetworkInterface"/>
    /// </summary>
    public void RefreshNetworkInterface()
    {
        if (HasNetworkInterface && HasLocalIPEndPoint)
        {                
            NetworkInterface = Common.Extensions.NetworkInterface.NetworkInterfaceExtensions.GetNetworkInterface(LocalIPEndPoint);
        }
    }

    /// <summary>
    /// If <see cref="HasRemoteAddressInformation"/> is True And <see cref="RemoteAddressInformation.IsDnsEligible"/> then the <see cref="RemoteIPHostEntry"/> is updated using <see cref="System.Net.Dns.GetHostEntry"/>
    /// </summary>
    public void RefreshRemoteIPHostEntry()
    {
        if (HasRemoteAddressInformation && RemoteAddressInformation.IsDnsEligible)
        {
            RemoteIPHostEntry = System.Net.Dns.GetHostEntry(RemoteIPEndPoint.Address);
        }
    }

    public override void Refresh()
    {
        if (IsDisposed) return;

        base.Refresh();

        RefreshNetworkInterface();

        RefreshRemoteIPHostEntry();
    }

    #endregion

    #region Connect

    public void Connect(int addressIndex, System.Net.NetworkInformation.NetworkInterface networkInterface, int port = 0)
    {
        if (ConnectionSocket == null) throw new System.InvalidOperationException("There must be a ConnectionSocket assigned before calling Connect.");

        if (addressIndex < 0) throw new System.IndexOutOfRangeException("addressIndex must be > 0 and < HostEntry.AddressList.Length");

        if (networkInterface == null) throw new System.ArgumentNullException("networkInterface");

        NetworkInterface = networkInterface;

        RemoteEndPoint = new System.Net.IPEndPoint(RemoteIPHostEntry.AddressList[addressIndex], port);

        Connect();

        LocalEndPoint = ConnectionSocket.LocalEndPoint;

        RemoteAddressInformation = new IPAddressInformation(RemoteIPEndPoint.Address, RemoteAddressInformation.IsDnsEligible, RemoteAddressInformation.IsTransient);
    }

    #endregion

    #region Dispose

    public override void Dispose()
    {
        base.Dispose();

        RemoteIPHostEntry = null;

        LocalEndPoint = RemoteEndPoint = null;

        NetworkInterface = null;
    }

    #endregion
}

#endregion
}
于 2015-07-15T22:56:49.037 に答える