从二进制写入到网络流接收数据

时间:2013-02-22 15:07:10

标签: .net vb.net networkstream binarywriter

这可以视为我之前thread.

的延续

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

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

正如您在屏幕截图中看到的,FileName变量中包含一些值。它是我发送的文件的名称。如果你注意到,变量包含 ello.cpp ,它必须是 hello.cpp hello.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

建议将受到高度赞赏。

提前致谢! :)

2 个答案:

答案 0 :(得分:0)

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

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

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

答案 1 :(得分:0)

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

我还要感谢Steven Doggart的所有努力和建议,特别是有关SOAP的建议。

非常感谢先生! :)