Получение данных от двоичного устройства записи в сетевой поток

Это можно рассматривать как продолжение моей предыдущей темы.

Я сделал некоторые разработки и исправил некоторые вещи в своем приложении для обмена файлами, но теперь я столкнулся с другой проблемой. Это не так сложно, я думаю, просто у меня сейчас не хватает умственных способностей, чтобы заняться этим. Я считаю, что это можно сделать лучше.

Вот скриншот ошибки, которую я получаю.

Как вы можете видеть на скриншоте, 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 ответа

Решение

Я разобрался, как это решить. Благодаря одному из предложений моего друга в Facebook, другой программист. Что я сделал, так это отправил какую-то строку, которая сигнализирует серверной части о получении файла. Теперь все хорошо.:)

Я хотел бы также поблагодарить Стивена Доггарта за все его усилия и предложения, особенно в отношении SOAP.

Большое спасибо, сэр!:)

Я бы рекомендовал всегда читать все данные в сетевом потоке и добавлять их в буфер / очередь связи. Каждый раз, когда в очередь добавляется больше данных, анализируйте данные во всей очереди, чтобы увидеть, не содержит ли они полные сообщения. Если так, удалите их из очереди и затем обработайте их. Например, вы можете создать класс, который реализует такой интерфейс:

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

Реализовать такую ​​функциональность будет проще, если сообщения имеют фиксированную ширину или разделены предварительно определенным разделителем. Кроме того, я бы порекомендовал иметь блок заголовка в начале каждого сообщения, который содержит, если не больше, символ типа сообщения.

Другие вопросы по тегам