ProtocolInstance Class | 
Namespace: Demo3D.Net
public abstract class ProtocolInstance : ProtocolSocket
The ProtocolInstance type exposes the following members.
| Name | Description | |
|---|---|---|
| ProtocolInstance | 
            Constructs a new ProtocolInstance.
              | 
| Name | Description | |
|---|---|---|
| Address | 
            The protocol address used by this instance.
              (Overrides ProtocolSocketAddress.) | |
| DownStream | 
            The downstream socket.
              (Inherited from ProtocolSocket.) | |
| ID | 
            A description of this instance.
              (Overrides ProtocolSocketID.) | |
| InternalRunning | 
            Indicates whether the instance is still running.
              | |
| Log | 
            Log messages.
              (Inherited from ProtocolSocket.) | |
| Protocol | 
            The protocol.
              | |
| ProtocolProperties | 
            Protocol property bag.
              | |
| Running | 
            Returns whether the instance is still running.
              (Overrides ProtocolSocketRunning.) | 
| Name | Description | |
|---|---|---|
| AddAspect | 
            Adds an aspect to a socket.
              (Inherited from ProtocolSocket.) | |
| AddOrUpdateAspect | 
            Adds or updates an aspect of the socket.
              (Inherited from ProtocolSocket.) | |
| BeginEditAsync | 
            Start batch editing.
              (Inherited from ProtocolSocket.) | |
| CloseAsync | 
            Closes the socket.
              (Overrides ProtocolSocket.CloseAsync(Boolean).) | |
| EndEditAsync | 
            End batch editing.
              (Inherited from ProtocolSocket.) | |
| FindAspect(Type) | 
            Returns an aspect of the given type, or return null.
              (Inherited from ProtocolSocket.) | |
| FindAspectT | 
            Returns an aspect of the given type, or return null.
              (Inherited from ProtocolSocket.) | |
| FindService(Type, ServiceBindingFlags, String) | 
            Returns an object that implements a specific API, or null.
            For example, an IO API such as IPacketIOService.
              (Overrides ProtocolSocketFindService(Type, ServiceBindingFlags, String).) | |
| FindServiceT(ServiceBindingFlags, String) | 
            Returns an object that implements a specific API, or null.
            For example, an IO API such as IPacketIOService.
              (Inherited from ProtocolSocket.) | |
| GetDownStream | 
            Returns the downstream socket.
              (Inherited from ProtocolSocket.) | |
| GetHead | 
            Returns the protocol head.
              (Overrides ProtocolSocketGetHead.) | |
| GetOrAddAspect | 
            Adds an aspect to a socket by using the specified function, if the key does not already exist.
              (Inherited from ProtocolSocket.) | |
| GetServiceT | 
            Returns an object that implements a specific API, or throws an exception.
            For example, an IO API such as IPacketIOService.
              (Inherited from ProtocolSocket.) | |
| GetStream | 
            Returns the head of the protocol stream (the first protocol instance).
              (Inherited from ProtocolSocket.) | |
| InitializeAsync | 
            When overridden in a derived class, initializes the socket.
              (Inherited from ProtocolSocket.) | |
| InternalCloseAsync | 
            Performs a controlled close.
              | |
| InternalOpenAsync | 
            Opens or reopens the instance.
              | |
| InternalShutdownAsync | 
            Forcibly shuts down the underlying protocol, causing all other users to throw an error.
              | |
| NotifyEditBegunAsync | 
            Notify EditBegunAsync raised.
              (Overrides ProtocolSocketNotifyEditBegunAsync(Boolean).) | |
| NotifyEditEndedAsync | 
            Notify EditEndedAsync raised.
              (Overrides ProtocolSocketNotifyEditEndedAsync(Boolean).) | |
| NotifyPropertyChanged(PropertyChangedEventArgs) | 
            Raises the PropertyChanged event.
              (Inherited from ProtocolSocket.) | |
| NotifyPropertyChanged(String) | 
            Raises the PropertyChanged event.
              (Inherited from ProtocolSocket.) | |
| OpenAsync | 
            Opens (or reopens) the socket.
              (Overrides ProtocolSocketOpenAsync(Boolean, Flags).) | |
| RegisterClosing | 
            Registers a function to call when Close has been called but before the socket has been closed.
              (Inherited from ProtocolSocket.) | |
| RegisterOpen | 
            Registers a function to call after the socket is opened, but before the OnOpenedAsync event is fired.
              (Inherited from ProtocolSocket.) | |
| RemoveAspect | 
            Removes an aspect from a socket.
              (Inherited from ProtocolSocket.) | |
| SetDownStream | 
            Sets the downstream socket.
              (Overrides ProtocolSocketSetDownStream(ProtocolSocket).) | |
| SetLog | 
            Sets the current log.
              (Inherited from ProtocolSocket.) | |
| Shutdown(Boolean) | 
            Forcibly shuts down the socket, without logging an error.
              (Inherited from ProtocolSocket.) | |
| Shutdown(Exception) | 
            Forcibly shuts down the socket, and then logs an error.
              (Inherited from ProtocolSocket.) | |
| Shutdown(String, Boolean) | 
            Forcibly shuts down the socket, and then logs an error.
              (Inherited from ProtocolSocket.) | |
| Shutdown(LogMessageLogLevel, String, Object) | 
            Forcibly shuts down the socket, and then logs an error.
              (Inherited from ProtocolSocket.) | |
| ShutdownAsync(Boolean, Boolean) | 
            Forcibly shuts down the socket, without logging an error.
              (Inherited from ProtocolSocket.) | |
| ShutdownAsync(Boolean, Exception) | 
            Forcibly shuts down the socket, and then logs an error.
              (Inherited from ProtocolSocket.) | |
| ShutdownAsync(Boolean, String, Boolean) | 
            Forcibly shuts down the socket, and then logs an error.
              (Inherited from ProtocolSocket.) | |
| ShutdownAsync(Boolean, LogMessageLogLevel, String, Object) | 
            Forcibly shuts down the socket, and then logs an error.
              (Inherited from ProtocolSocket.) | |
| ToString | 
            Returns a description of this socket.
              (Overrides ProtocolSocketToString.) | |
| TryCreateService | 
            Returns an object that implements a specific API, or null.
            For example, an IO API such as IPacketIOService.
              | |
| UnregisterClosing | 
            Unregister a previously registered function.
              (Inherited from ProtocolSocket.) | |
| UnregisterOpen | 
            Unregister a previously registered function.
              (Inherited from ProtocolSocket.) | 
| Name | Description | |
|---|---|---|
| EditBegunAsync | 
            Raised on the first call to BeginEdit.
              (Inherited from ProtocolSocket.) | |
| EditEndedAsync | 
            Raised on the last call to EndEdit.
              (Inherited from ProtocolSocket.) | |
| OnClosedAsync | 
            Occurs after the socket is closed.
              (Inherited from ProtocolSocket.) | |
| OnDisposed | 
            Occurs when the socket is disposed.
            A socket is disposed when it's closed and uncached from the connection registry.
            User script may retain a reference, and may resurrect the socket by calling OpenAsync(Boolean, OpenFlags).
              (Inherited from ProtocolSocket.) | |
| OnOpenedAsync | 
            Occurs after the socket is opened.
              (Inherited from ProtocolSocket.) | |
| OnShutdownAsync | 
            Occurs after the socket is shutdown.
              (Inherited from ProtocolSocket.) | |
| PropertyChanged | 
            Occurs when a property value changes.
              (Inherited from ProtocolSocket.) | 
The following example shows the most basic implementation of a ProtocolInstance.
using System; using System.Threading.Tasks; using Demo3D.Net; namespace Examples.Net.ExampleProtocol { /// <summary> /// An interface that describes the services (the IO methods) that your protocol supports. /// Typically a protocol would implement one of the standard services (such as <see cref="IPacketIOService"/>). /// </summary> interface IExampleService { // Put whatever methods users of your protocol would expect in here. } /// <summary> /// An instance of a protocol. Must inherit from <see cref="ProtocolInstance"/>, and should /// support a set of services. The simplest way to support services is to implement the /// services interface (<see cref="IExampleService"/>) and to advertise those services in the /// <see cref="ExampleProtocol.NewInstance(ProtocolHead, ProtocolAddress)"/> constructor. /// </summary> /// <remarks> /// See <see cref="TCPExample.Client.TcpClientProtocol.TcpClientConnection"/> for an /// example implementing the TCP protocol. /// </remarks> public class ExampleProtocolInstance : ProtocolInstance, IExampleService { public ExampleProtocolInstance(Protocol protocol, ProtocolHead head, ProtocolAddress address) : base(protocol, head, address, false, null) { } /// <summary> /// Initializes the socket. /// </summary> /// <param name="sync">If true, the Task returned must be guaranteed to be complete.</param> protected override Task InitializeAsync(bool sync) { // Any initialization code goes here. return Task.CompletedTask; } /// <summary> /// Indicates whether the instance is still running. /// </summary> protected override bool InternalRunning => base.InternalRunning; // Return true if the connection is established /// <summary> /// Opens or reopens the instance. /// </summary> /// <param name="sync">If true, the Task returned must be guaranteed to be complete.</param> /// <param name="flags">Additional flags.</param> protected override Task InternalOpenAsync(bool sync, Flags flags) { // Open your connection here. return Task.CompletedTask; } /// <summary> /// Forcibly shuts down the underlying protocol, causing all other users to throw an error. /// </summary> protected override Task InternalShutdownAsync(bool sync) { // Forcibly shut the connection down. return Task.CompletedTask; } /// <summary> /// Performs a controlled close. /// </summary> protected override Task InternalCloseAsync(bool sync) { // Called to close the connection. return InternalShutdownAsync(sync); } // Implement any IExampleService methods here. } /// <summary> /// A protocol inherits from <see cref="Protocol"/>. /// </summary> /// See <see cref="TCPExample.Client.TcpClientProtocol"/> for an example implementing the TCP protocol, /// or <see cref="TCPExample.Server.TcpServerProtocol"/> for an example implementing a TCP server. /// </remarks> sealed class ExampleProtocol : Protocol { /// <summary> /// Constructs a new protocol. /// You need to give your protocol a name, and advertise which services it supports. /// </summary> public ExampleProtocol() : base("Example", typeof(IExampleService)) { } /// <summary> /// Create a new server/client protocol instance. /// At the minimum, you need to implement this method to return a new instance of your protocol. /// </summary> /// <param name="head">The socket head which is a required parameter to the ProtocolInstance constructor.</param> /// <param name="protocolAddress">The protocol address.</param> /// <returns>A new ProtocolInstance.</returns> protected override ProtocolInstance NewInstance(ProtocolHead head, ProtocolAddress protocolAddress) { return new ExampleProtocolInstance(this, head, protocolAddress); } /// <summary> /// Registers the protocol with Demo3D.Net. /// You need to call this method somewhere in your code in order to register this protocol with Demo3D.Net. /// </summary> public static IDisposable Register() => Registry.Register(new ExampleProtocol()); } }
Example showing a TCP client.
using System; using System.ComponentModel; using System.IO; using System.Net.Sockets; using System.Threading.Tasks; using Demo3D.IO; using Demo3D.Net; using TcpClient = System.Net.Sockets.TcpClient; namespace Examples.Net.TCPExample.Client { /// <summary> /// TCP address editor. /// </summary> public class TcpAddressEditor : ProtocolAddressPropertyBagEditor { string host; int port; /// <summary> /// The server host. /// </summary> [Description("The server host.")] [Category("Connection")] public string Host { get { return host; } set { if (host != value) { host = value; NotifyPropertyChanged(); } } } /// <summary> /// The server port. /// </summary> [Description("The server port.")] [Category("Connection")] public int Port { get { return port; } set { if (port != value) { port = value; NotifyPropertyChanged(); } } } /// <summary> /// Returns a ProtocolAddress that represents the configuration defined by this object. /// </summary> /// <returns>The protocol address according to the current setting of the editor properties.</returns> public override ProtocolAddress GetAddress() { return new ProtocolAddressBuilder("tcp", host, port).Address; } /// <summary> /// Sets this configuration object properties from the ProtocolAddress given. /// </summary> /// <param name="address">The current address.</param> public override void SetAddress(ProtocolAddress address) { host = address.Host; port = address.Port; } /// <summary> /// Returns the next property that needs to be edited to complete the address. /// </summary> /// <returns>The name of the property, or null.</returns> public override string NextProperty() { if (string.IsNullOrWhiteSpace(this.Host)) return nameof(this.Host); if (this.Port <= 0) return nameof(this.Port); return null; } } [ProtocolAddressEditor(Editor = typeof(TcpAddressEditor))] public sealed class TcpClientProtocol : Protocol { sealed class TcpClientConnection : ProtocolInstance, IByteStreamService { TcpClient tcpClient; NetworkStream stream; internal TcpClientConnection(Protocol protocol, ProtocolHead head, ProtocolAddress peerAddress) : base(protocol, head, peerAddress, true, null) { } protected override bool InternalRunning { get { return tcpClient != null && tcpClient.Connected; } } protected override async Task InternalOpenAsync(bool sync, Flags flags) { string host = this.Address.Host; int port = this.Address.IsDefaultPort ? 0 : this.Address.Port; if (!this.Address.HasHost || port <= 0) { throw Exceptions.ProtocolError("Host or port not configured", this); } tcpClient = new TcpClient(); if (sync) tcpClient.Connect(host, port); else await tcpClient.ConnectAsync(host, port).ConfigureAwait(false); stream = tcpClient.GetStream(); } protected override Task InternalShutdownAsync(bool sync) { try { tcpClient?.Client?.Shutdown(SocketShutdown.Both); } catch { } return Task.CompletedTask; } protected override async Task InternalCloseAsync(bool sync) { if (tcpClient == null) return; await InternalShutdownAsync(sync).ConfigureAwait(false); try { tcpClient?.Client?.Close(); } catch { } try { tcpClient?.Close(); } catch { } stream = null; tcpClient = null; } bool IByteStreamService.DataAvailable { get { return stream.DataAvailable; } } Stream IByteStreamService.Stream { get { return stream; } } } TcpClientProtocol() : base("TCP", typeof(IByteStreamService)) { } public static IDisposable Register() => Registry.Register(new TcpClientProtocol()); protected override ProtocolInstance NewInstance(ProtocolHead head, ProtocolAddress protocolAddress) { return new TcpClientConnection(this, head, protocolAddress); } } }
Example showing a TCP server.
using System; using System.IO; using System.Net; using System.Net.Sockets; using System.Threading.Tasks; using Demo3D.IO; using Demo3D.Net; using TcpClient = System.Net.Sockets.TcpClient; namespace Examples.Net.TCPExample.Server { public sealed class TcpServerProtocol : Protocol { sealed class TcpServerConnection : ProtocolInstance, IByteStreamService { TcpClient tcpClient; NetworkStream stream; internal TcpServerConnection(TcpClient tcpClient, Protocol protocol, ProtocolHead head, ProtocolAddress peerAddress) : base(protocol, head, peerAddress, true, null) { this.tcpClient = tcpClient; stream = tcpClient.GetStream(); } protected override bool InternalRunning { get { return tcpClient != null && tcpClient.Connected; } } protected override Task InternalOpenAsync(bool sync, Flags flags) { throw new Exception("Cannot reconnect"); } protected override Task InternalShutdownAsync(bool sync) { try { tcpClient?.Client?.Shutdown(SocketShutdown.Both); } catch { } return Task.CompletedTask; } protected override async Task InternalCloseAsync(bool sync) { if (tcpClient == null) return; await InternalShutdownAsync(sync).ConfigureAwait(false); try { tcpClient?.Client?.Close(); } catch { } try { tcpClient?.Close(); } catch { } stream = null; tcpClient = null; } bool IByteStreamService.DataAvailable { get { return stream.DataAvailable; } } Stream IByteStreamService.Stream { get { return stream; } } } sealed class TcpServer : ProtocolInstance, IProtocolServerService { TcpListener listener; internal TcpServer(Protocol protocol, ProtocolHead head, ProtocolAddress protocolAddress) : base(protocol, head, protocolAddress, false, null) { } protected override bool InternalRunning { get { return listener != null; } } protected override async Task InternalOpenAsync(bool sync, Flags flags) { int port = this.Address.IsDefaultPort ? 0 : this.Address.Port; IPAddress ipAddress; switch (this.Address.Host) { case "": case ProtocolAddress.AnyHost: ipAddress = IPAddress.Any; break; default: ipAddress = await IPv4.HostToIPAddressAsync(sync, this.Address.Host).ConfigureAwait(false); break; } listener = new TcpListener(ipAddress, port); listener.Start(); } protected override Task InternalShutdownAsync(bool sync) { try { listener?.Server.Close(); } catch { } return Task.CompletedTask; } protected override Task InternalCloseAsync(bool sync) { try { listener?.Stop(); } catch { } listener = null; return Task.CompletedTask; } async Task<ProtocolInstance> IProtocolServerService.InternalAcceptAsync(bool sync, ProtocolHead head, ProtocolInstance downStreamConnection) { TcpClient client; if (sync) client = listener.AcceptTcpClient(); else client = await listener.AcceptTcpClientAsync().ConfigureAwait(false); var endPoint = (IPEndPoint)client.Client.RemoteEndPoint; var address = new ProtocolAddressBuilder("tcp", endPoint.Address.ToString(), endPoint.Port).Address; return new TcpServerConnection(client, this.Protocol, head, address); } } TcpServerProtocol() : base("TCP", typeof(IProtocolServerService), typeof(IByteStreamService)) { } public static IDisposable Register() => Registry.Register(new TcpServerProtocol()); protected override ProtocolInstance NewInstance(ProtocolHead head, ProtocolAddress protocolAddress) { return new TcpServer(this, head, protocolAddress); } } }