如何使用 system.io.pipes 发送请求并获得响应

Posted

技术标签:

【中文标题】如何使用 system.io.pipes 发送请求并获得响应【英文标题】:How to send a request and get a response using system.io.pipes 【发布时间】:2011-09-14 16:17:02 【问题描述】:

我正在尝试编写一个通过命名管道进行通信的客户端和服务器。我需要客户端能够向服务器发送查询并让服务器发送响应。 System.IO.pipes 的所有 Web 示例要么向客户端发送单个字符串,要么向服务器发送单个字符串。我找到了一些关于如何使用旧的 Win32 管道做到这一点的例子。但是,我不能使用它。

这是我目前所拥有的。我知道这是很多代码。但是,我认为问题可能出在管道流的构造函数之一中。

客户代码

Private Sub cmdSend_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cmdSend.Click
    Dim strMsg As String = ""
    Dim strRequest As String = "Send Key"
    Dim strErrMsg As String = ""

    PrintText("Creating new pipe client")
    'pipeStream = New NamedPipeClientStream(strPipeName)
    'pipeStream = New NamedPipeClientStream(strPipeName, PipeDirection.InOut, 1, PipeTransmissionMode.Message, PipeOptions.None)
    pipeStream = New NamedPipeClientStream(strServerName, strPipeName, PipeDirection.InOut, PipeOptions.None, Security.Principal.TokenImpersonationLevel.None)

    PrintText("Connecting to server")
    pipeStream.Connect()
    pipeStream.ReadMode = PipeTransmissionMode.Message

    PrintText("Sending request")
    'Send Request
    If SendPipeMessage(pipeStream, strRequest, strErrMsg) Then
    Else
        PrintText(strErrMsg)
    End If

    PrintText("Receiving response")
    'Process Response
    If ReadPipeMessage(pipeStream, strMsg, strErrMsg) Then
        PrintText(strMsg)
    Else
        PrintText(strErrMsg)
    End If

    pipeStream.Dispose()
    pipeStream = Nothing

End Sub

Private Function SendPipeMessage(ByRef pipeStream As NamedPipeClientStream, ByVal strMsg As String, ByRef strErrMsg As String) As Boolean
    Dim blnRetVal As Boolean = True
    Dim bytMessage() As Byte = Nothing
    Dim encoding As UTF8Encoding = Nothing

    Try
        encoding = New UTF8Encoding
        bytMessage = encoding.GetBytes(strMsg)
        pipeStream.Write(bytMessage, 0, bytMessage.Length)

    Catch ex As Exception
        blnRetVal = False
        strErrMsg = ex.ToString
    End Try
    Return blnRetVal
End Function


Private Function ReadPipeMessage(ByRef pipeStream As NamedPipeClientStream, ByRef strPipeText As String, ByRef strErrMsg As String) As Boolean
    Dim blnRetVal As Boolean = True
    Dim strTextChunck As String = ""
    Dim intNumBytes As Integer = 0
    Dim intNumChars As Integer = 0
    Dim bytMessage(10) As Byte
    Dim chars(10) As Char
    Dim decoder As Decoder = Nothing

    Try
        decoder = Encoding.UTF8.GetDecoder
        strPipeText = ""
        Do
            strTextChunck = ""
            Do
                intNumBytes = pipeStream.Read(bytMessage, 0, bytMessage.Length)
                intNumChars = decoder.GetChars(bytMessage, 0, intNumBytes, chars, 0)
                strTextChunck = strTextChunck & New String(chars, 0, intNumChars)
            Loop While Not pipeStream.IsMessageComplete
            strPipeText = strPipeText & strTextChunck
        Loop While intNumBytes <> 0

    Catch ex As Exception
        blnRetVal = False
        strErrMsg = ex.ToString
    End Try
    Return blnRetVal
End Function

服务器代码

Private Sub cmdListen_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cmdListen.Click
    bw.RunWorkerAsync()
End Sub

Private Sub bw_DoWork(ByVal sender As System.Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles bw.DoWork
    Dim strRequest As String = ""

    Dim strErrMsg As String = ""

    bw.ReportProgress(0, "Create new pipe server stream")
    pipeStream = New NamedPipeServerStream(strPipeName, PipeDirection.InOut, 1, PipeTransmissionMode.Message, PipeOptions.None)

    'Wait for connection
    bw.ReportProgress(0, "Listening for connection")
    pipeStream.WaitForConnection()

    bw.ReportProgress(0, "Receiving request")
    'Receive Request
    If ReadPipeMessage(pipeStream, strRequest, strErrMsg) Then
        bw.ReportProgress(0, "Request : " & strRequest)
    Else
        bw.ReportProgress(0, strErrMsg)
    End If

    'Get response
    strResponse = GetResponse(strRequest)

    bw.ReportProgress(0, "Sending response")
    'Send Response
    If SendPipeMessage(pipeStream, strResponse, strErrMsg) Then
        bw.ReportProgress(0, "Sent response")
    Else
        bw.ReportProgress(0, strErrMsg)
    End If
    bw.ReportProgress(0, "Done!")

    pipeStream.Disconnect()
    pipeStream.Dispose()
    pipeStream = Nothing

End Sub

Private Sub bw_ProgressChanged(ByVal sender As Object, ByVal e As System.ComponentModel.ProgressChangedEventArgs) Handles bw.ProgressChanged
    PrintText(e.UserState)
End Sub

Private Sub bw_RunWorkerCompleted(ByVal sender As Object, ByVal e As System.ComponentModel.RunWorkerCompletedEventArgs) Handles bw.RunWorkerCompleted
    PrintText(e.Result)
End Sub


Private Function SendPipeMessage(ByRef pipeStream As NamedPipeServerStream, ByVal strMsg As String, ByRef strErrMsg As String) As Boolean
    Dim blnRetVal As Boolean = True
    Dim bytMessage() As Byte = Nothing
    Dim encoding As UTF8Encoding = Nothing

    Try
        encoding = New UTF8Encoding
        bytMessage = encoding.GetBytes(strMsg)
        pipeStream.Write(bytMessage, 0, bytMessage.Length)

    Catch ex As Exception
        blnRetVal = False
        strErrMsg = ex.ToString
    End Try
    Return blnRetVal
End Function

Private Function ReadPipeMessage(ByRef pipeStream As NamedPipeServerStream, ByRef strPipeText As String, ByRef strErrMsg As String) As Boolean
    Dim blnRetVal As Boolean = True
    Dim strTextChunck As String = ""
    Dim intNumBytes As Integer = 0
    Dim intNumChars As Integer = 0
    Dim bytMessage(10) As Byte
    Dim chars(10) As Char
    Dim decoder As Decoder = Nothing

    Try
        decoder = Encoding.UTF8.GetDecoder
        strPipeText = ""
        Do
            strTextChunck = ""
            Do
                intNumBytes = pipeStream.Read(bytMessage, 0, bytMessage.Length)
                intNumChars = decoder.GetChars(bytMessage, 0, intNumBytes, chars, 0)
                strTextChunck = strTextChunck & New String(chars, 0, intNumChars)
            Loop While Not pipeStream.IsMessageComplete
            strPipeText = strPipeText & strTextChunck
        Loop While intNumBytes <> 0

    Catch ex As Exception
        blnRetVal = False
        strErrMsg = ex.ToString
    End Try
    Return blnRetVal
End Function

当我启动客户端时,它在 ReadPipMessage() 上挂起,而服务器在 ReceivingRequest() 上挂起。如果我杀死客户端,服务器会读取客户端发送的请求。但是,由于客户端不再运行,它会在发送响应时发生故障。

服务器不能在同一个连接中发送和接收消息吗?我认为这就是 PipeDirection.InOut 的意思。

谢谢,

迈克

【问题讨论】:

【参考方案1】:

您可能想查看 WCF 的命名管道绑定。有很多很好的例子来说明如何使用它,例如:http://www.jmedved.com/2010/03/named-pipes-in-wcf/

【讨论】:

以上是关于如何使用 system.io.pipes 发送请求并获得响应的主要内容,如果未能解决你的问题,请参考以下文章

我正在制作一个 synapse x custom ui,但我不断收到此错误

如何中止使用 wininet 发送的请求?

如何检查请求是不是使用 JavaScript (Mocha) 发送

如何使用 WinInet 发送 HTTPS 请求?

如何使用 C# 在 POST 请求中发送 json 请求正文数据

如何使用 HttpURLConnection 在请求正文中发送数据?