我正在尝试创建一个防御性命名管道服务器,其他应用程序可以读取简单的状态值。我只对单个命名管道实例感兴趣,客户端可以在其中连接、读取状态并断开连接。
我遇到的问题是试图保护我的管道免遭不当使用;特别是防止单个进程获得控制权并且永远不会放开我的命名管道。我试图在超时后强制断开/关闭管道以终止连接;该尝试允许我的服务器继续,但是,当我结束连接时,不会调用异步回调。
我的代码的最小化版本如下(.NET 3.5)...
服务器端]
static AutoResetEvent autoEvent = new AutoResetEvent(false);
static void Main(string[] args)
{
NamedPipeServerStream pipe = new NamedPipeServerStream("TestSimplePipe", PipeDirection.Out);
Console.WriteLine("Waiting for client...");
pipe.WaitForConnection();
Console.WriteLine("About to BeginWrite...");
pipe.BeginWrite(new byte[1] { 0x00 }, 0, 1, new AsyncCallback(ProcessWrite), pipe);
Console.WriteLine("Waiting...");
bool hasSignal = autoEvent.WaitOne(5000);
if (hasSignal == false)
{
Console.WriteLine("Client took to long.");
}
Console.WriteLine("Closing pipe.");
pipe.Close();
Console.ReadLine();
}
static void ProcessWrite(IAsyncResult result)
{
try
{
Console.WriteLine("Ending write...");
NamedPipeServerStream pipe = result.AsyncState as NamedPipeServerStream;
pipe.EndWrite(result);
Console.WriteLine("Wrote successfully!");
}
catch (Exception)
{
Console.WriteLine("Write not completed.");
}
autoEvent.Set();
}
客户端]
static void Main(string[] args)
{
using (NamedPipeClientStream npcs = new NamedPipeClientStream(".", "TestSimplePipe", PipeDirection.In))
{
Console.WriteLine("Connecting to server...");
npcs.Connect();
Console.WriteLine("Connected!");
//Thread.Sleep(15000);
Console.WriteLine("Reading byte...");
npcs.ReadByte();
Console.WriteLine("Byte read!");
}
Console.WriteLine("Done!");
Console.ReadLine();
}
如果一切都按计划设计,我会得到以下输出:
服务器端]
Waiting for client...
About to BeginWrite...
Waiting...
Ending write...
Wrote successfully!
Closing pipe.
客户端]
Connecting to server...
Connected!
Reading byte...
Byte read!
Done!
但是,如果我在客户端代码中启用 sleep ,服务器将不会从回调中输出任何内容:
Waiting for client...
About to BeginWrite...
Waiting...
Client took to long.
Closing pipe.
我假设在关闭时,将调用回调并抛出“ObjectDisposeException”。相反,当我关闭服务器管道时,不会调用回调。
还让我害怕的是,如果我等待客户端 sleep 的整个持续时间而不结束服务器管道应用程序,则将在服务器上调用回调,并且我将收到服务器的以下输出:
Waiting for client...
About to BeginWrite...
Waiting...
Client took to long.
Closing pipe.
Ending write...
Write not completed.
我并不担心清理异步调用,但担心它由于第三方应用程序而以某种方式保持事件状态。当我终止回调所附加的管道时,如何正确清理异步回调?
最佳答案
您可以多次打开同一个命名管道。您应该同时接受多个客户。这样,没有任何客户端可以阻止端点。 This is shown in a native code example on MSDN.您可以将该代码移植到 .NET。也许,您应该使用异步 IO,这样您就不会用完许多客户端的线程。
另一方面,恶意客户端可能会导致资源耗尽,或者通过向服务器发送垃圾邮件连接而导致其他客户端无法连接。我不知道有什么方法可以防止这种情况。
关于c# - 如何从强制终止管道中正确清除异步回调?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18644631/