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.) | |
| Properties |
Protocol and service properties.
(Overrides ProtocolSocketProperties.) | |
| 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.) | |
| Close |
Closes the socket.
(Overrides ProtocolSocket.Close.) | |
| 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.) | |
| InternalClose |
Performs a controlled close.
| |
| InternalOpenAsync |
Opens or reopens the instance.
| |
| InternalShutdown |
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 |
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) |
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.) | |
| 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.) | |
| OnClosed |
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.) | |
| OnShutdown |
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.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> 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 void InternalShutdown() { // Forcibly shut the connection down. } /// <summary> /// Performs a controlled close. /// </summary> protected override void InternalClose() { // Called to close the connection. InternalShutdown(); } // 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> 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 void Register() { Registry.Register(new ExampleProtocol()); } } }
Example showing a TCP client.
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 { 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 void InternalShutdown() { try { tcpClient?.Client?.Shutdown(SocketShutdown.Both); } catch { } } protected override void InternalClose() { if (tcpClient == null) return; InternalShutdown(); 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 void 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 { 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 void InternalShutdown() { try { tcpClient?.Client?.Shutdown(SocketShutdown.Both); } catch { } } protected override void InternalClose() { if (tcpClient == null) return; InternalShutdown(); 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 void InternalShutdown() { try { listener?.Server.Close(); } catch { } } protected override void InternalClose() { try { listener?.Stop(); } catch { } listener = null; } 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 void Register() { Registry.Register(new TcpServerProtocol()); } protected override ProtocolInstance NewInstance(ProtocolHead head, ProtocolAddress protocolAddress) { return new TcpServer(this, head, protocolAddress); } } }