【问题标题】:Receving Data From Binary Writer To Network Stream从二进制写入接收数据到网络流
【发布时间】:2013-02-22 15:07:10
【问题描述】:

这可以算是我之前thread.的延续

我对我的文件共享应用程序进行了一些开发和修复,但现在我面临另一个问题。我想这个并不难,只是我目前正在耗尽脑力来解决这个问题。我相信这可以以更好的方式完成。

这是我收到的错误的屏幕截图。

正如您在屏幕截图中看到的,FileName 变量中有一些值。它是我要发送的文件的名称。如果您注意到,变量包含 ello.cpp,它必须是 hello.cpphello.cpp 是正在发送的文件的名称。尾随字符是文件的内容。尾随字符不再是问题,只要我能正确解决这个问题,文件名将是唯一存储在变量上的一个。

在读取网络流的过程中发生错误。我想要实现的是,我想防止网络流在不是日志消息时被读取。我需要将networkstream.read 放在某个地方,这样它就不会占用文件的第一个字母。也许某种过滤?或者,如果可能只有一个代码可以获取日志消息和文件名,那就太好了。文件名是使用二进制写入器发送的,我尝试使用网络流来检索文件名,但它不起作用。我在这里遗漏了什么吗?

这是服务器部分的代码。

    Try

        While FileSharingStarted

            If CBool(ClientSocket.Available) Then

                Dim ByteData(ClientSocket.ReceiveBufferSize) As Byte

                'This reading of the stream here causes the problem. That's why the
                'file name isn't read properly. This reading part here is actually
                'intended for the logging part. What happens is that when the string
                'for the logging part is sent by the client side, this is being read
                'using this. But when a file is sent, it is read here in this part
                'that's why when the algorithm for retrieving the file name below
                'kicks in, the first letter of the file name is missing, and ruins
                'the whole thing.
                networkStream.Read(ByteData, 0, CInt(ClientSocket.ReceiveBufferSize))

                fileLogMessage = Encoding.ASCII.GetString(ByteData)
                Dim ConnectionStatus() As String
                ConnectionStatus = fileLogMessage.Split(CChar(" "))

                If fileLogMessage.Contains("is connected." & Environment.NewLine) Then

                    'Creates a log when the user connects.

                ElseIf fileLogMessage.Contains("is disconnected." & Environment.NewLine) Then

                   'Creates a log when the user disconnects.

                Else

                    'Algorithm for receiving the files.

                    Dim FileName, FilePath As String
                    Dim FileLength As Long

                    'This part here conflicts with the `networkstream.read` above
                    Dim binaryReader As New BinaryReader(ClientSocket.GetStream)
                    FileName = binaryReader.ReadString()
                    FileLength = binaryReader.ReadInt64()
                    FilePath = Path.Combine(System.Environment.CurrentDirectory & "\home", FileName)

                    Dim FileData(8092) As Byte
                    Dim TotalData As Long = 0
                    Dim ReadBytes As Integer = -1

                    Using fileStream As New FileStream(FilePath, FileMode.Create, FileAccess.Write)

                        FileSharingStatusBar.Panels.Item(1).Text = "Receiving file . . ."

                        Do Until TotalData = FileLength

                            If ReadBytes = 0 Then
                                fileStream.Close()
                                FileTransferInterrupted = True
                                Exit Do
                            Else
                                ReadBytes = ClientSocket.GetStream.Read(FileData, 0, FileData.Length())
                                fileStream.Write(FileData, 0, ReadBytes)
                                TotalData += ReadBytes
                            End If

                        Loop

                    End Using

                    If FileTransferInterrupted Then

                        MessageBox.Show("File transfer interrupted.", "Message", MessageBoxButtons.OK, MessageBoxIcon.Information)
                        FileSharingStatusBar.Panels.Item(1).Text = "Idle."

                    Else

                        MessageBox.Show("File received.", "Message", MessageBoxButtons.OK, MessageBoxIcon.Information)
                        FileSharingStatusBar.Panels.Item(1).Text = "Idle."

                    End If

                End If

            End If

        End While

这是客户端的代码。

Try

        Dim fileInfo As New FileInfo(txtFilePath.Text)
        Dim binaryWriter As New BinaryWriter(fileClientSocket.GetStream())

        'Here's the part where it writes the file name on the
        'stream using the binary writer
        binaryWriter.Write(fileInfo.Name)
        binaryWriter.Write(fileInfo.Length)

        Using fileStream As New FileStream(txtFilePath.Text, IO.FileMode.Open, IO.FileAccess.Read)

            Dim FileData(8092) As Byte
            Dim ReadBytes As Integer = -1
            FileSharingStatusBar.Panels.Item(1).Text = "Sending file . . ."

            Do Until ReadBytes = 0

                If CBool(fileClientSocket.Available) Then

                    MessageBox.Show("File transfer interrupted.", "Message", MessageBoxButtons.OK, MessageBoxIcon.Information)
                    Exit Sub

                Else

                    ReadBytes = fileStream.Read(FileData, 0, FileData.Length)
                    fileClientSocket.GetStream.Write(FileData, 0, ReadBytes)

                End If

            Loop

        End Using

        txtFilePath.Text = ""
        MessageBox.Show("File sent.", "Message", MessageBoxButtons.OK, MessageBoxIcon.Information)
        FileSharingStatusBar.Panels.Item(1).Text = "Idle."

    Catch ex As Exception

        MessageBox.Show(ex.Message, "Message", MessageBoxButtons.OK, MessageBoxIcon.Information)

End Try

我们将不胜感激。

提前致谢! :)

【问题讨论】:

    标签: .net vb.net networkstream binarywriter


    【解决方案1】:

    我建议始终读取网络流中的所有数据并将其附加到通信缓冲区/队列中。每次向队列追加更多数据时,分析整个队列中的数据以查看它是否包含任何完整的消息。如果是这样,请将它们从队列中删除,然后处理它们。例如,您可以创建一个实现如下接口的类:

    Public Interface IIncomingDataBuffer
        Sub Append(ByVal data() As Byte)
        Event MessageReceived As EventHandler(Of MessageEventArgs)
    End Interface
    

    如果消息是固定宽度或由预定义的分隔符分隔,则实现此类功能会更容易。另外,我建议在每条消息的开头有一个标题块,如果没有其他内容,则包含一个消息类型字符。

    【讨论】:

    • 感谢您的回复。这似乎是个好主意。但问题是,只有当我能够获得正在发送的文件的文件名时,我才能这样做。只要我无法检索网络流上的文件名(因为它是用二进制写入器编写的),我就不能这样做,因为我不知道如何使用网络流来检索文件名。二进制写入器。此外,我只需要对代码进行一些适当的重组,特别是 networkstream.read 部分,以便在发送文件时不会干扰。
    • 嗯,据我了解,您发送两种不同类型的消息:日志消息和文件传输消息。在日志消息中,您只有一个有效负载字段:要记录的文本。但是在文件传输消息中,您有三个有效负载字段:文件名、文件大小和文件内容。因此,您不仅需要定义如何确定每条消息的开始和结束位置,还需要定义如何确定消息中每个字段的开始和结束位置。
    • 您本质上所做的是定义自己的协议。这绝不是一项不可能完成的任务,但它是您设计中非常关键的一步,不能简单地跳过或掩饰。如果您不想花时间设计一个好的协议,我建议您简单地使用一个已经存在的协议,例如 SOAP。 .NET 框架具有用于处理 SOAP 的内置类,Visual Studio IDE 甚至提供了方便的 WCF 和 ASMX Web 服务工具,用于开发基于 SOAP 的应用程序的客户端和服务器端。
    • 好的。在我搜索一些有关 SOAP 的文章之前,我想再问一个问题。没有其他方法可以检索使用网络流使用二进制写入器写入的文件名吗?可以消除在我的服务器代码中使用binaryReader.Readstring 并仅使用networkStream.Read 来检索文件名和日志消息的东西,它们都是字符串。如果不可能,为什么会这样?我只是问,为了简单起见。如果我能完成这项工作,我就快完成申请了。
    • 感谢您的回复。我稍后会尝试你的建议。现在是凌晨 3 点 24 分。我得休息一下。哈哈
    【解决方案2】:

    我想出了如何解决它。感谢我在 facebook 上的一位朋友的建议,一位程序员。我所做的是发送一些字符串,指示服务器部分接收文件。现在一切都好。 :)

    我还要感谢 Steven Doggart 所做的所有努力和建议,尤其是关于 SOAP。

    非常感谢楼主! :)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-04-21
      • 2016-01-15
      相关资源
      最近更新 更多