命名管道:服务器端如何知道客户端已断开连接?

Posted

技术标签:

【中文标题】命名管道:服务器端如何知道客户端已断开连接?【英文标题】:Named pipes: how server side can know that client has disconnected? 【发布时间】:2012-02-01 16:55:22 【问题描述】:

我有 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();
    

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

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

【问题讨论】:

【参考方案1】:

我认为您的 pipserver 设置不正确。

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

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

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

我猜他们正处于僵持状态,等待其中一个发送一些信息。

【讨论】:

在我的情况下 WaitForConnection 实际上没问题,因为客户端几乎会立即连接。但你是对的,问题是我的服务器正在从客户端读取 smth,而客户端也在做同样的事情。所以服务器无法向客户端发送任何东西,一直在尝试写东西。我没有意识到我不能等待来自客户端的输入并同时向它发送消息。

以上是关于命名管道:服务器端如何知道客户端已断开连接?的主要内容,如果未能解决你的问题,请参考以下文章

我的服务器如何知道客户端已断开连接?

在断开连接之前等待读取命名管道

C#命名管道,如何检测客户端断开连接

客户端断开连接后如何使命名管道不忙?

当客户端除了快速连接-断开之外啥都不做时,命名管道会失败

django 频道如何知道客户端已断开连接?