我编写并修改了使用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