c# - 命名管道 : how server side can know that client has disconnected?

标签 c# named-pipes

我有 2 个应用程序使用命名管道进行通信。

主程序调用客户端程序并创建管道服务器与之通信。客户端程序创建管道客户端。主程序可以向客户端程序发送任何消息,它们应该以某种方式在客户端进行处理。当客户端程序退出时,它正在向主程序发送任何消息,这意味着服务器管道应该关闭。

我在使用带有 PipeDirection.Out 的服务器和带有 PipeDirection.In 的客户端实现第一部分(从服务器向客户端发送消息)时没有遇到任何问题。但是当我尝试修改代码以使服务器和客户端都具有 PipeDirection.InOut(以便能够从客户端向服务器发送消息)时,代码停止工作。当我执行 writer.Flush(在服务器端)或 writer.WriteByte(在客户端)时程序挂起。现在它挂起的地方被标记为[HANGS HERE]。

服务器是这样创建的:

public static void CreatePipeServerStream()    
{
    var namedPipeServerStream = new NamedPipeServerStream("somename", PipeDirection.InOut);
    namedPipeServerStream.WaitForConnection();

    // This thread is wating for message from client
    ThreadStart starter = () => WaitForSignalFromClient(namedPipeServerStream);
    new Thread(starter).Start();
}

private static void WaitForSignalFromClient(NamedPipeServerStream namedPipeServerStream)
{
    if (namedPipeServerStream.IsConnected)
    {
        namedPipeServerStream.ReadByte();
        // we'll get here after something is read
        // and if we got here, we should close the server pipe
        // now I can get here only if I shut down the client program using Task manager
        namedPipeServerStream.Close();
    }
}

向客户端发送消息的过程正在执行此操作(用于在服务器具有管道方向 == Out 且客户端具有管道方向 == In 时工作):

public static void SendMessageUsingPipe(NamedPipeServerStream namedPipeServerStream)
{
    if (namedPipeServerStream.IsConnected)
    {
        var sw = new StreamWriter(namedPipeServerStream);
        sw.WriteLine("smth");
        // [HANGS HERE]
        sw.Flush();
    }
}

在客户端,这段代码在单独的线程中运行:

private void WaitServerCommands()
{
    _pipe = new NamedPipeClientStream(".", "somename", PipeDirection.InOut);
    using (var rdr = new StreamReader(_pipe))
    {
        while (true)
        {
            if (!_pipe.IsConnected)
            {
                _pipe.Connect();
            }
            rdr.ReadLine();
            // I don't care what was sent by server, I just need to know that something was sent
            Invoke(_handleCommand);
        }
    }
}

应该向服务器发送消息的代码:

private void ClosePipes()
{
    if (_pipe != null && _pipe.IsConnected)
    {
        // [HANGS HERE]
        _pipe.WriteByte(113);
        _pipe.WaitForPipeDrain();
        _pipe.Close();
    }
}

知道代码有什么问题吗?或者也许我错过了一些基本的东西?

实际问题是我需要在服务器端知道客户端已断开连接。也许可以通过其他方式实现?

最佳答案

我认为您没有正确设置 pipserver。

namedPipeServerStream.WaitForConnection() 将阻塞当前线程,直到客户端连接。

当客户端确实连接时,您会从客户端读取一个字节,同时您让客户端从服务器读取一行。

namedPipeServerStream.ReadByte();
rdr.ReadLine();

我猜他们陷入僵局,等待其中之一发送一些信息。

关于c# - 命名管道 : how server side can know that client has disconnected?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9099849/

相关文章:

c++ - 命名管道和 "GetNamedPipeHandleState"

.net - 在 IIS 中添加 net.pipe 绑定(bind)时出现 "Object reference not set"

c# - 如何使用 lambda 表达式来过滤数据行?

windows - Win32 命名管道和消息大小限制 - 旧的 64K 限制是否仍然适用?

linux - 为什么 mkfifo 的管道只在 ~25 秒后更新?

JavascriptExecutor (Selenium WebDriver C#) 不断返回空对象

.net - 如何使命名管道在 C++ 和 .NET 之间工作?

c# - MVC Application_start localhost 重定向你太多次

c# - 使用 CaSTLe ActiveRecord,当两个类具有相同名称但命名空间不同时,我得到一个 NHibernate DuplicateMappingException

c# - 'result is T' 与 'typeof(T).IsInstanceOfType(result)' 之间有显着差异吗?