WCF 名前付きパイプ サーバー、非 WCF 名前付きパイプ サーバー、WCF 名前付きパイプ クライアント、および非 wcf 名前付きパイプ クライアントがあります。
非 wcf クライアントは両方のサーバーに接続できます。wcf クライアントは、wcf サーバーにのみ接続できます。非 wcf クライアントに接続しようとすると、この例外が発生します。
Unhandled Exception: System.ServiceModel.EndpointNotFoundException: There was no endpoint
listening at net.pipe://localhost/PipePlusFive that could accept the message. This is
often caused by an incorrect address or SOAP action. See InnerException,
if present, for more details. ---> System.IO.PipeException: The pipe endpoint
'net.pipe://localhost/PipePlusFive' could not be found on your local machine.
--- 内部例外スタック トレースの終了 ---
これによると、パイプの実際の名前は、メモリ マップ ファイルに格納された GUID です。これは、wcf クライアントとサーバーに対して自動的に処理されると思います。非 wcf サーバーの場合、メモリ マップド ファイルを作成し、GUID を書き込み、その GUID を名前に使用してパイプを作成します。非 wcf クライアントでは、メモリ マップ ファイルを開き、そこからパイプ名を読み取り、その名前を使用してパイプに接続します。次に、何も変更せずに非 wcf クライアントを使用して両方のサーバーに接続できるという事実は、サーバーとクライアントの両方でこの部分を正しく実装していると信じさせます。
また、非 wcf サーバーを起動してから wcf サーバーを起動すると、別のエンドポイントが既にリッスンしているため、そのパイプ名をリッスンできないという 2 番目のクラッシュが発生します。
非 wcf クライアントが両方を見つけることができるのに、なぜ wcf クライアントが非 wcf サーバーを見つけられないのか疑問に思っています。リンク先のブログに記載されている以外に、wcf がエンドポイントを見つけるために使用するものはありますか?
アップデート:
WCF クライアントに使用しているコードは次のとおりです。
class Program
{
static void Main(string[] args)
{
ChannelFactory<IPlusFive> pipeFactory =
new ChannelFactory<IPlusFive>(new NetNamedPipeBinding(NetNamedPipeSecurityMode.None), new EndpointAddress("net.pipe://localhost/PipePlusFive"));
IPlusFive pipeProxy = pipeFactory.CreateChannel();
while (true)
{
string str = Console.ReadLine();
if (str.Equals("q"))
{ return; }
Console.WriteLine(pipeProxy.PlusFive(Int32.Parse(str)));
}
}
}
WCFサーバーに使用しているコードは次のとおりです。
class Program
{
static void Main(string[] args)
{
var inst = new PlusFiver();
using (ServiceHost host = new ServiceHost(inst,
new Uri[] { new Uri("net.pipe://localhost") }))
{
host.AddServiceEndpoint(typeof(IPlusFive), new NetNamedPipeBinding(NetNamedPipeSecurityMode.None), "PipePlusFive");
host.Open();
Console.WriteLine("Service is Available. Press enter to exit.");
Console.ReadLine();
host.Close();
}
}
}
非WCFサーバーに使用しているコードは次のとおりです。
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Creating Memory Mapped file...");
string fileName = GenerateFileMapName(String.Empty);
Guid pipeName = Guid.NewGuid();
Console.WriteLine(" writing pipe name: " + pipeName.ToString("D"));
MemoryMappedFile mmf = null;
var messageList = new List<byte>();
try
{
mmf = WritePipeName(fileName, pipeName);
Console.WriteLine("Creating Named Pipe");
Console.WriteLine("Pipe Name: " + GetPipeNameFromMappedFile(fileName, mmf));
using (var pipe = new NamedPipeServerStream(pipeName.ToString("D"), PipeDirection.InOut))
{
Console.WriteLine("pipe created");
Console.WriteLine("Waiting for connection");
pipe.WaitForConnection();
Console.WriteLine("Received Connection");
Console.WriteLine("Waiting to receive data");
var bytes = new byte[7];
pipe.Read(bytes, 0, 7);
messageList.AddRange(bytes);
bytes = new byte[messageList[6]];
pipe.Read(bytes, 0, messageList[6]);
messageList.AddRange(bytes);
bytes = new byte[2];
pipe.Read(bytes, 0, 2);
messageList.AddRange(bytes);
messageList.Add((byte)pipe.ReadByte());
pipe.WriteByte(0x0b);
WriteList(messageList);
Console.WriteLine("Finished reading from pipe");
PrintBytes(bytes);
Console.WriteLine("Closing Connection");
pipe.Disconnect();
Console.WriteLine("Pipe disconnected");
//Console.Read();
}
}
finally
{
mmf.Dispose();
}
}
private static void WriteList(List<byte> messageList)
{
foreach (var b in messageList)
{
Console.Write(b.ToString("x2") + " ");
}
Console.WriteLine();
}
private static void PrintBytes(byte[] bytes)
{
foreach (var b in bytes)
{
Console.Write(b.ToString("x2") + " ");
}
Console.WriteLine();
}
private static string GenerateFileMapName(string uri)
{
return "net.pipe:EbmV0LnBpcGU6Ly8rLw==";
}
private static MemoryMappedFile WritePipeName(string fileName, Guid pipeName)
{
var mmf = MemoryMappedFile.CreateNew(fileName, pipeName.ToByteArray().Count());
Console.WriteLine("Memory Mapped File Created.");
using (var accessor = mmf.CreateViewAccessor(4, 45))
{
Console.WriteLine("Writing pipe name to file");
accessor.Write(0, ref pipeName);
Console.WriteLine("Finished writing pipe name to file");
}
return mmf;
}
private static string GetPipeNameFromMappedFile(string filename, MemoryMappedFile mmf)
{
Guid pipeName;
using (var accessor = mmf.CreateViewAccessor(4, 45))
{
accessor.Read<Guid>(0, out pipeName);
}
return pipeName.ToString("D");
}
}