Commit 10a40296 authored by Kirill's avatar Kirill

Named Pipes

parent 7faed73a
/* The MIT License (MIT)
*
* Copyright (c) 2015 Marc Clifton
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
// From: http://stackoverflow.com/questions/34478513/c-sharp-full-duplex-asynchronous-named-pipes-net
// See Eric Frazer's Q and self answer
using System;
using System.IO.Pipes;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Clifton.Core.Pipes
{
public abstract class BasicPipe
{
public event EventHandler<PipeEventArgs> DataReceived;
public event EventHandler<EventArgs> PipeClosed;
protected PipeStream pipeStream;
protected Action<BasicPipe> asyncReaderStart;
public BasicPipe()
{
}
public void Close()
{
pipeStream.WaitForPipeDrain();
pipeStream.Close();
pipeStream.Dispose();
pipeStream = null;
}
/// <summary>
/// Reads an array of bytes, where the first [n] bytes (based on the server's intsize) indicates the number of bytes to read
/// to complete the packet.
/// </summary>
public void StartByteReaderAsync()
{
StartByteReaderAsync((b) => DataReceived?.Invoke(this, new PipeEventArgs(b, b.Length)));
}
/// <summary>
/// Reads an array of bytes, where the first [n] bytes (based on the server's intsize) indicates the number of bytes to read
/// to complete the packet, and invokes the DataReceived event with a string converted from UTF8 of the byte array.
/// </summary>
public void StartStringReaderAsync()
{
StartByteReaderAsync((b) =>
{
string str = Encoding.UTF8.GetString(b).TrimEnd('\0');
DataReceived?.Invoke(this, new PipeEventArgs(str));
});
}
public void Flush()
{
pipeStream.Flush();
}
public Task WriteString(string str)
{
return WriteBytes(Encoding.UTF8.GetBytes(str));
}
public Task WriteBytes(byte[] bytes)
{
var blength = BitConverter.GetBytes(bytes.Length);
var bfull = blength.Concat(bytes).ToArray();
return pipeStream.WriteAsync(bfull, 0, bfull.Length);
}
protected void StartByteReaderAsync(Action<byte[]> packetReceived)
{
int intSize = sizeof(int);
byte[] bDataLength = new byte[intSize];
pipeStream.ReadAsync(bDataLength, 0, intSize).ContinueWith(t =>
{
int len = t.Result;
if (len == 0)
{
PipeClosed?.Invoke(this, EventArgs.Empty);
}
else
{
int dataLength = BitConverter.ToInt32(bDataLength, 0);
byte[] data = new byte[dataLength];
pipeStream.ReadAsync(data, 0, dataLength).ContinueWith(t2 =>
{
len = t2.Result;
if (len == 0)
{
PipeClosed?.Invoke(this, EventArgs.Empty);
}
else
{
packetReceived(data);
StartByteReaderAsync(packetReceived);
}
});
}
});
}
}
}
\ No newline at end of file
/* The MIT License (MIT)
*
* Copyright (c) 2015 Marc Clifton
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
// From: http://stackoverflow.com/questions/34478513/c-sharp-full-duplex-asynchronous-named-pipes-net
// See Eric Frazer's Q and self answer
using System;
using System.IO.Pipes;
namespace Clifton.Core.Pipes
{
public class ClientPipe : BasicPipe
{
protected NamedPipeClientStream clientPipeStream;
public ClientPipe(string serverName, string pipeName, Action<BasicPipe> asyncReaderStart)
{
this.asyncReaderStart = asyncReaderStart;
clientPipeStream = new NamedPipeClientStream(serverName, pipeName, PipeDirection.InOut, PipeOptions.Asynchronous);
pipeStream = clientPipeStream;
}
public void Connect()
{
clientPipeStream.Connect();
asyncReaderStart(this);
}
}
}
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{B826097C-CC24-4CAC-8D31-8A65C4B76BE9}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>Clifton.Core.Pipes</RootNamespace>
<AssemblyName>Clifton.Core.Pipes</AssemblyName>
<TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Net.Http" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="BasicPipe.cs" />
<Compile Include="ClientPipe.cs" />
<Compile Include="PipeEventArgs.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="ServerPipe.cs" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>
\ No newline at end of file
/* The MIT License (MIT)
*
* Copyright (c) 2015 Marc Clifton
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
// From: http://stackoverflow.com/questions/34478513/c-sharp-full-duplex-asynchronous-named-pipes-net
// See Eric Frazer's Q and self answer
namespace Clifton.Core.Pipes
{
public class PipeEventArgs
{
public byte[] Data { get; protected set; }
public int Len { get; protected set; }
public string String { get; protected set; }
public PipeEventArgs(string str)
{
String = str;
}
public PipeEventArgs(byte[] data, int len)
{
Data = data;
Len = len;
}
}
}
\ No newline at end of file
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("Clifton.Core.Pipes")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("Microsoft")]
[assembly: AssemblyProduct("Clifton.Core.Pipes")]
[assembly: AssemblyCopyright("Copyright © Microsoft 2017")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("b826097c-cc24-4cac-8d31-8a65c4b76be9")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// 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.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]
/* The MIT License (MIT)
*
* Copyright (c) 2015 Marc Clifton
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
// From: http://stackoverflow.com/questions/34478513/c-sharp-full-duplex-asynchronous-named-pipes-net
// See Eric Frazer's Q and self answer
using System;
using System.IO.Pipes;
namespace Clifton.Core.Pipes
{
public class ServerPipe : BasicPipe
{
public event EventHandler<EventArgs> Connected;
protected NamedPipeServerStream serverPipeStream;
protected string PipeName { get; set; }
public ServerPipe(string pipeName, Action<BasicPipe> asyncReaderStart)
{
this.asyncReaderStart = asyncReaderStart;
PipeName = pipeName;
serverPipeStream = new NamedPipeServerStream(
pipeName,
PipeDirection.InOut,
NamedPipeServerStream.MaxAllowedServerInstances,
PipeTransmissionMode.Message,
PipeOptions.Asynchronous);
pipeStream = serverPipeStream;
serverPipeStream.BeginWaitForConnection(new AsyncCallback(PipeConnected), null);
}
protected void PipeConnected(IAsyncResult ar)
{
serverPipeStream.EndWaitForConnection(ar);
Connected?.Invoke(this, new EventArgs());
asyncReaderStart(this);
}
}
}
\ No newline at end of file
https://www.codeproject.com/Articles/1179195/Full-Duplex-Asynchronous-Read-Write-with-Named-Pip
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment