达到特定文件大小时抛出的内存不足异常

时间:2016-10-13 15:40:21

标签: vb.net file out-of-memory

我编写并修改了使用System.Net.Socket发送结束接收文件的代码。每当我发送200MB +文件时,我会在OutOfMemoryException获得Dim bytFbyte(intByteSize) As Byte,如果文件大小为250-300MB +?我也在OutOfMemoryException得到Dim bytFileDataByte() As Byte = File.ReadAllBytes(arrSplit(1))。(代码的位置有评论)如何更正此问题。这是我的代码。

DataSender.vb:

Imports System.IO
Imports System.Net.Sockets
Imports System.Text

Public Class DataSender

    Private strIp As String
    Private intPort As Integer

    Public Sub New(ByRef strIp As String, intPort As Integer, strFileName As String,
                   strFullFileName As String)
        Me.strIp = strIp
        Me.intPort = intPort
    End Sub

    Public Sub SendData(ByVal strArg As String, strMessage As String)
        Dim sckSock = New Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)
        sckSock.Connect(strIp, intPort)

        If strArg = "file" Then
            'MsgBox(strMessage)
            Dim arrSplit As String() = strMessage.Split(New Char() {"&"c})
            Dim bytFileNameByte() As Byte = Encoding.UTF8.GetBytes(arrSplit(0))
            Dim bytFileDataByte() As Byte = File.ReadAllBytes(arrSplit(1)) 'System.OutOfMemoryException 250-300MB+ file
            Dim bytFileLen() As Byte = BitConverter.GetBytes(bytFileNameByte.Length)
            Dim intByteSize As Integer = 4 + bytFileNameByte.Length + bytFileDataByte.Length
            Dim bytFbyte(intByteSize) As Byte 'System.OutOfMemoryException 200MB file
            Dim intIdxA As Integer = 0
            Dim intIdxB As Integer = bytFileLen.Length
            Dim intIdxC As Integer = intIdxB + bytFileNameByte.Length

            bytFileLen.CopyTo(bytFbyte, intIdxA)
            bytFileNameByte.CopyTo(bytFbyte, intIdxB)
            bytFileDataByte.CopyTo(bytFbyte, intIdxC)

            If sckSock.Send(bytFbyte) Then
                Dim bytReplyMessage(1024) As Byte
                Dim intBytesReceived As Integer = sckSock.Receive(bytReplyMessage)
                MsgBox(Encoding.UTF8.GetString(bytReplyMessage, 0, intBytesReceived))
            End If

        ElseIf strArg = "command" Then
            Dim test() As Byte = Encoding.UTF8.GetBytes(strMessage)
            sckSock.Send(test)
            Debug.WriteLine("Message sent!")
        End If
        sckSock.Close()
    End Sub
End Class

DataReceiver.vb:

Imports System.IO
Imports System.Net
Imports System.Net.Sockets
Imports System.Text
Imports System.Threading

Public Class DataReceiver

    Private frmBase As Form
    Private thdReceiveListener As Thread
    Private intReceiverPort As Integer
    Private intFlag As Integer = 0
    Private strReceivedPath As String = ""
    Private strReceivedDirPath As String
    Private strMessage As String
    Private rtbDisplay As RichTextBox
    Private Delegate Sub MyDelegate()

    Public Sub New(ByVal frmBase As Form, intReceiverPort As Integer, strReceivedDirPath As String, rtbDisplay As RichTextBox)
        Me.frmBase = frmBase
        Me.intReceiverPort = intReceiverPort
        Me.strReceivedDirPath = strReceivedDirPath
        Me.rtbDisplay = rtbDisplay
    End Sub

    Public Sub StartReceiving()
        thdReceiveListener = New Thread(AddressOf StartListening)
        thdReceiveListener.Start()
    End Sub

    Private Class StateObject
        Public sckWorkSocket As Socket = Nothing
        Public Const intBufferSize As Integer = 1024
        Public bfrBuffer As Byte() = New Byte(intBufferSize - 1) {}
    End Class

    Private Shared mreAllDone As New ManualResetEvent(False)

    Private Sub StartListening()
        Dim bytBytes As Byte() = New [Byte](1023) {}
        Dim ipEnd As New IPEndPoint(IPAddress.Any, intReceiverPort)
        Dim sckListener As New Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)

        Try
            sckListener.Bind(ipEnd)
            sckListener.Listen(100)
            While True
                mreAllDone.Reset()
                sckListener.BeginAccept(New AsyncCallback(AddressOf AcceptCallback), sckListener)
                mreAllDone.WaitOne()
            End While
        Catch ex As Exception
        End Try
    End Sub

    Private Sub AcceptCallback(ar As IAsyncResult)
        mreAllDone.[Set]()
        Dim sckListener As Socket = DirectCast(ar.AsyncState, Socket)
        Dim sckHandler As Socket = sckListener.EndAccept(ar)
        Dim soState As New StateObject()
        soState.sckWorkSocket = sckHandler
        sckHandler.BeginReceive(soState.bfrBuffer, 0, StateObject.intBufferSize, 0, New AsyncCallback(AddressOf ReadCallback), soState)
        intFlag = 0
    End Sub

    Private Sub ReadCallback(ar As IAsyncResult)
        Dim strFileNameLen As Integer = 1
        Dim strContent As [String] = [String].Empty
        Dim soState As StateObject = DirectCast(ar.AsyncState, StateObject)
        Dim sckHandler As Socket = soState.sckWorkSocket
        Dim intBytesRead As Integer = sckHandler.EndReceive(ar)
        Dim strFileName As String = ""

        If intBytesRead > 0 Then
            If intFlag = 0 Then
                strFileNameLen = BitConverter.ToInt32(soState.bfrBuffer, 0)
                Try
                    strFileName = Encoding.UTF8.GetString(soState.bfrBuffer, 4, strFileNameLen)
                    strReceivedPath = Convert.ToString(strReceivedDirPath) & strFileName
                    intFlag += 1
                Catch ex As ArgumentOutOfRangeException
                    Debug.WriteLine("Message received")
                    strMessage = Encoding.UTF8.GetString(soState.bfrBuffer)
                    frmBase.Invoke(New MyDelegate(AddressOf MessageWriter))
                End Try
            End If
            If intFlag >= 1 Then
                Dim wtrRriter As New BinaryWriter(File.Open(strReceivedPath, FileMode.Append))
                If intFlag = 1 Then
                    wtrRriter.Write(soState.bfrBuffer, 4 + strFileNameLen, intBytesRead - (4 + strFileNameLen))
                    Dim bytConfirmMessage() As Byte = Encoding.UTF8.GetBytes("File " & strFileName & " transfered. " & intBytesRead - (4 + strFileNameLen) & " bytes total")
                    sckHandler.Send(bytConfirmMessage)
                    strMessage = "File saved: " + strReceivedPath
                    frmBase.Invoke(New MyDelegate(AddressOf MessageWriter))
                    intFlag += 1
                Else
                    wtrRriter.Write(soState.bfrBuffer, 0, intBytesRead)
                End If
                wtrRriter.Close()
                sckHandler.BeginReceive(soState.bfrBuffer, 0, StateObject.intBufferSize, 0, New AsyncCallback(AddressOf ReadCallback), soState)
            End If
        Else
            frmBase.Invoke(New MyDelegate(AddressOf LabelWriter))
        End If
    End Sub

    Private Sub MessageWriter()
        rtbDisplay.AppendText(strMessage)
        rtbDisplay.AppendText(vbNewLine)
    End Sub

    Private Sub LabelWriter()
        'MsgBox("Data Received")
    End Sub

End Class

0 个答案:

没有答案