Skip to content

Commit

Permalink
Change client method for waiting for data
Browse files Browse the repository at this point in the history
Exceptionhandling instead of null when it times out. Gives better controll on how to handle timeouts. Update v1.1.4.4 on nuget also
  • Loading branch information
large committed Sep 20, 2020
1 parent dd6b2fc commit 9a8c371
Show file tree
Hide file tree
Showing 10 changed files with 93 additions and 24 deletions.
25 changes: 25 additions & 0 deletions Client/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace Client
Expand All @@ -11,6 +12,9 @@ class Program
{
static void Main(string[] args)
{
Console.WriteLine("Waiting 2 second before creating and connecting client");
Thread.Sleep(2000);

//Create client with a simple event for disconnect
var client = new SimpleCrossFrameworkIPC.Client<IMySimpleService>();
client.ClientDisconnected += (sndr, arguments) =>
Expand Down Expand Up @@ -39,6 +43,27 @@ static void Main(string[] args)
//Disconnect the client
client.Disconnect();
Console.WriteLine($"Connectionstate: {client.IsConnected()}");

//Testing new client with a different timeout
//Create client with a simple event for disconnect
Console.WriteLine("Test timeout for clients, max 3 waittime for 4 second function");
var client2 = new SimpleCrossFrameworkIPC.Client<IMySimpleService>(3000);
client2.ClientDataReceiveTimeout += (sndr, arguments) =>
Console.WriteLine("Client did not receive data in the given time set");
try
{
//Connect and give state of connection, return values
client2.Connect(Channel.Name, Channel.TimeoutMS);
var proxy = client2.GetProxy();
Console.WriteLine($"DelayedFunction: {proxy.DelayedFunction()}");
}
catch (Exception ex)
{
Console.WriteLine("Error: " + ex.ToString());
}

client2.Disconnect();

Console.WriteLine("Press any key to quit");
Console.ReadLine();
}
Expand Down
3 changes: 2 additions & 1 deletion Contract/Contract.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,13 @@ public interface IMySimpleService
int Count { get; set; }

int Function();
bool DelayedFunction();
}

//Simple common class to share name and timeouts
public class Channel
{
public static string Name = "ChannelName";
public static int TimeoutMS = 1000;
public static int TimeoutMS = 1000; //Connection timeout
}
}
19 changes: 13 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,19 @@ Simple IPC between .net and .core
This is a lightversion of a IPC to be used on either .net or .core and even mixed if you like.
The "fix" for the conversion is a hack and might not work for later releases.

As for 10.05.2020 it works as expected between netstandard 2.0 and .net 4.7.2.
As for 20.09.2020 it works as expected between netstandard 2.0 and .net 4.7.2.

Class is based on KrakenIPC: https://github.com/darksody/KrakenIPC and Full Duplex Pipes: https://www.codeproject.com/Articles/1179195/Full-Duplex-Asynchronous-Read-Write-with-Named-Pip


## Pipes are old, why did you mesh this up
I had a asp.core application that needed to get data from a .net472 application and the only IPC that actually worked was gRPC ( https://grpc.io/ ).
gRPC was overkill for my project so I wanted something simpler and tiny.

#### Updated 20.09.2020 ####
Added a custom delay for the time to wait for server data for the client.
Changed return method to throw an exception instead of null, to make it easier to handle timeouts in the future.
Also an event is added, to ensure that you catch everything if you decide to suppress exceptions.

## Usage
Server and Client need to share a common interface.
```c#
Expand Down Expand Up @@ -49,7 +53,7 @@ Note that this pipe only works on localhost
//Stop server
handler.Stop();
}
catch(Exception ex) //
catch(Exception ex)
{
Console.WriteLine(ex.ToString());
}
Expand All @@ -58,20 +62,23 @@ Note that this pipe only works on localhost
When a client connects it will refer to the same interface.
After connection are used to receive data from the server



```c#
var client = new SimpleCrossFrameworkIPC.Client<IMySimpleService>();
int nWaitForServerDataDelay = 2000; //2 sec max waiting for data
var client = new SimpleCrossFrameworkIPC.Client<IMySimpleService>(nWaitForServerDataDelay);

try
{
//Connect with a 1 second timeout
//Connect with a 1 second connection timeout
client.Connect("Channel", 1000);
var proxy = client.GetProxy();

//Print proxy-data to the console
Console.WriteLine("Text: " + proxy.Text);
Console.WriteLine("Number: " + proxy.Number.ToString());
}
catch(Exception ex) //
catch(Exception ex)
{
Console.WriteLine(ex.ToString());
}
Expand Down
10 changes: 9 additions & 1 deletion Server/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace Server
Expand All @@ -13,7 +14,14 @@ public class MySimpleService : IMySimpleService
public int Number { get => 111; }
public string Text { get => "Some string"; }
public int Count { get; set; }


//Simple function to show how to handle the receiveclientTimeout event
public bool DelayedFunction()
{
Thread.Sleep(4000);
return true;
}

public int Function()
{
return Count * 12;
Expand Down
14 changes: 7 additions & 7 deletions SimpleCrossFrameworkIPC.core/SimpleCrossFrameworkIPC.core.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
<PropertyGroup>
<TargetFrameworks>netstandard2.0;net472</TargetFrameworks>
<SignAssembly>false</SignAssembly>
<Version>1.1.3.2</Version>
<Version>1.1.4.4</Version>
<Authors>Lars Werner</Authors>
<Description>Simple IPC across .core and .net.</Description>
<Copyright>Copyright © 2020</Copyright>
Expand All @@ -20,12 +20,12 @@
<PropertyGroup>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
<GenerateBindingRedirectsOutputType>true</GenerateBindingRedirectsOutputType>
<AssemblyVersion>1.1.3.2</AssemblyVersion>
<FileVersion>1.1.3.2</FileVersion>
<AssemblyVersion>1.1.4.4</AssemblyVersion>
<FileVersion>1.1.4.4</FileVersion>
<AssemblyName>SimpleCrossFrameworkIPC</AssemblyName>
<RootNamespace>SimpleCrossFrameworkIPC</RootNamespace>
<PackageRequireLicenseAcceptance>false</PackageRequireLicenseAcceptance>
<PackageIcon>SimpleIPC.jpg</PackageIcon>
<PackageIcon>icon.jpg</PackageIcon>
<PackageLicenseExpression>MIT</PackageLicenseExpression>
<PackageId>SimpleCrossFrameworkIPC</PackageId>
<Product>SimpleCrossFrameworkIPC</Product>
Expand All @@ -46,15 +46,15 @@
</ItemGroup>

<ItemGroup>
<PackageReference Include="Microsoft.CSharp" Version="4.5.0" />
<PackageReference Include="Microsoft.CSharp" Version="4.7.0" />
<PackageReference Include="System.IO.Pipes" Version="4.3.0" />
<PackageReference Include="System.IO.Pipes.AccessControl" Version="4.5.1" />
<PackageReference Include="System.Reflection.Emit" Version="4.3.0" />
<PackageReference Include="System.Reflection.Emit" Version="4.7.0" />
<PackageReference Include="Newtonsoft.Json" version="12.0.3" />
</ItemGroup>

<ItemGroup>
<None Include="..\..\..\..\Pictures\SimpleIPC.jpg">
<None Include="..\icon.jpg">
<Pack>True</Pack>
<PackagePath></PackagePath>
</None>
Expand Down
27 changes: 23 additions & 4 deletions SimpleCrossFrameworkIPC/Client/Client.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,17 +32,33 @@ public class Client<T> where T : class
//Event if client was disconnected
public event EventHandler<EventArgs> ClientDisconnected;

//Event if client timed out for waiting for data
public event EventHandler<EventArgs> ClientDataReceiveTimeout;

//Timeout variable (in ms) for waiting for data from server. Default 2000 ms (2 secs)
public int ClientReceiveTimeout { get; set; }

//Variable for connection-station
private bool bConnected;

/// <summary>
/// Proxy uses a callbackfunction that builds with the Response-class received from the server
/// Default constructor for 2000 ms wait time for data
/// </summary>
public Client()
public Client() : this(2000)
{
}

/// <summary>
/// Alternative creator for clients
/// </summary>
/// <param name="_ClientReceiveTimeout"></param>
public Client(int _ClientReceiveTimeout)
{
clientPipe = null;
proxy = ProxyHelper.GetInstance<T>(OnMethodCallback);
bConnected = false;
ClientReceiveTimeout = _ClientReceiveTimeout;
}

/// <summary>
Expand Down Expand Up @@ -150,8 +166,8 @@ private object OnMethodCallback(string methodName, List<object> parameterValues,
byte[] requestBytes = Encoding.ASCII.GetBytes(json);
clientPipe.WriteBytes(requestBytes, false);

//Wait for data to be received, then build the data (2 seconds max)
responseEvent.Wait(TimeSpan.FromMilliseconds(2000));
//Wait for data to be received, then build the data (user set timeout)
responseEvent.Wait(TimeSpan.FromMilliseconds(ClientReceiveTimeout));
if (responseEvent.IsSet)
{
Message message = JsonConvert.DeserializeObject<Message>(responseJson);
Expand Down Expand Up @@ -181,7 +197,10 @@ private object OnMethodCallback(string methodName, List<object> parameterValues,

}
else //If event is not set, then return nada
return null;
{
ClientDataReceiveTimeout?.Invoke(this, new EventArgs());
throw new Exception("Timeout waiting for data");
}
}

/// <summary>
Expand Down
2 changes: 1 addition & 1 deletion SimpleCrossFrameworkIPC/Common/BasicPipe.cs
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ public Task WriteBytes(byte[] bytes, bool InsertLengthFirst = true)
var blength = BitConverter.GetBytes(bytes.Length);
bfull = blength.Concat(bytes).ToArray();
}

return pipeStream.WriteAsync(bfull, 0, bfull.Length);
}

Expand Down
4 changes: 2 additions & 2 deletions SimpleCrossFrameworkIPC/Properties/AssemblyInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,5 +32,5 @@
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.1.3.2")]
[assembly: AssemblyFileVersion("1.1.3.2")]
[assembly: AssemblyVersion("1.1.4.4")]
[assembly: AssemblyFileVersion("1.1.4.4")]
13 changes: 11 additions & 2 deletions SimpleCrossFrameworkIPC/Server/Server.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.IO;
using System.IO.Pipes;
using System.Linq;
using System.Reflection;
Expand Down Expand Up @@ -65,11 +66,12 @@ private void CreateServer(string Pipename)

serverPipe.Disconnect += (sndr, args) =>
{
ClientDisconnected?.Invoke(this, new EventArgs());
ServerPipe sender = sndr as ServerPipe;
bool bPipeRemoved = serverPipes.Remove(sender);
if (!bPipeRemoved)
throw new Exception("Pipe not found, rare case ");
else
ClientDisconnected?.Invoke(this, new EventArgs());
};
}

Expand Down Expand Up @@ -153,7 +155,14 @@ private void OnMessageReceived(ServerPipe serverPipe, byte[] bytes)
var responseMessage = new Message<Response>(response);
var responseJson = JsonConvert.SerializeObject(responseMessage);
byte[] responseBytes = Encoding.ASCII.GetBytes(responseJson);
serverPipe.WriteBytes(responseBytes, false);

try
{
serverPipe.WriteBytes(responseBytes, false);
}
catch(IOException) //Catch this exception to ensure disconnect
{
}
}
}
}
Binary file added icon.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit 9a8c371

Please sign in to comment.