我在C#中编写了一个简单的异步NamedPipeStreamServer进程,其核心是:
public void Listen()
{
bool shuttingDown = false;
while (!shuttingDown)
{
NamedPipeServerStream serverStream =
new NamedPipeServerStream(
"bobasdfpipe",
PipeDirection.InOut,
254,
PipeTransmissionMode.Message,
PipeOptions.Asynchronous);
IAsyncResult connectionResult =
serverStream.BeginWaitForConnection(
this.HandleConnection,
serverStream);
int waitResult =
WaitHandle.WaitAny(
new[]
{
this.ShutdownEvent,
connectionResult.AsyncWaitHandle
});
switch (waitResult)
{
case 0:
// this.ShutdownEvent
shuttingDown = true;
break;
case 1:
// connectionResult.AsyncWaitHandle
serverStream.EndWaitForConnection(connectionResult);
break;
}
}
}
我还为它写了一个简单的客户端。客户端(非异步)只是打开管道然后退出:
static void Main(string[] args)
{
using (
NamedPipeClientStream clientStream =
new NamedPipeClientStream(
".",
"bobasdfpipe",
PipeDirection.InOut))
{
clientStream.Connect();
}
}
如果我启动服务器,然后启动客户端或多个客户端,一切似乎都可以正常工作。
如果我在没有启动服务器的情况下启动客户端,则客户端会挂起Connect()调用,直到我启动服务器,但是当我启动服务器时,服务器崩溃并出现System.IO.Exception BeginWaitForConnection()调用,说“管道正在关闭。”
我发现其他人在BeginWaitForConnection()上出现“正在关闭管道”错误,但这些错误都是在同一个NamedPipeServerStream实例上尝试第二次BeginWaitForConnection()调用引起的。这不是正在发生的事情 - 我为每个BeginWaitForConnection()调用创建了一个不同的NamedPipeServerStream实例,即使我没有,它仍然在第一个BeginWaitForConnection()调用失败。
我做错了吗?或者这是否正常 - 等待服务器启动的命名管道客户端将导致服务器的第一个BeginWaitForConnection()调用上的“管道正在关闭”?
我注意到如果我再次尝试 - 即吸收异常并执行另一个BeginWaitForConnection() - 那么我为每个等待服务器出现的客户端得到一个这样的异常,但在处理完所有那些,服务器似乎在此后工作正常。
编辑:这是HandleConnection方法,但我认为它甚至不会出现此代码:
private void HandleConnection(IAsyncResult iar)
{
NamedPipeServerStream serverStream =
(NamedPipeServerStream)iar.AsyncState;
Log.Info("So, that happened.");
Thread.Sleep(1000);
Log.Info("Giving up.");
}
答案 0 :(得分:2)
似乎客户端在服务器完全处理之前关闭了连接。之所以会发生这种情况,是因为clientStream.Dispose()
在clientStream.Connect()
之后立即被调用,并且即将建立的连接将被终止。
提示:尝试在Thread.Sleep(100)
之后立即添加clientStream.Connect()
。
我做错了吗?或者这是正常的 - 一个命名管道 等待服务器启动的客户端将导致“管道 正在关闭“在服务器的第一个BeginWaitForConnection()调用?
无论客户端做什么,服务器代码都应该能够通过捕获IOException 和来丢弃服务器的管道句柄来优雅地处理这一系列事件。
NamedPipeServerStream serverStream =
new NamedPipeServerStream(
"bobasdfpipe",
PipeDirection.InOut,
254,
PipeTransmissionMode.Message,
PipeOptions.Asynchronous);
try
{
IAsyncResult connectionResult = serverStream.BeginWaitForConnection(
this.HandleConnection,
serverStream);
int waitResult =
WaitHandle.WaitAny(
new[]
{
this.ShutdownEvent,
connectionResult.AsyncWaitHandle
});
switch (waitResult)
{
case 0:
// this.ShutdownEvent
shuttingDown = true;
break;
case 1:
// connectionResult.AsyncWaitHandle
serverStream.EndWaitForConnection(connectionResult);
break;
}
}
catch(IOException)
{
// Connection terminated by client, close server pipe's handle
serverStream.Close();
continue;
}