TransferFile.vb
- Imports System.SerializableAttribute
-
- <Serializable()> Public Class TransferFile
- Public FileName As String
- Public Data() As Byte
- End Class
TcpFileReceiver.vb
- Imports System.Net.Sockets
- Imports System.Net
- Imports System.IO
- Imports System.Threading
- Imports System.SerializableAttribute
- Imports System.Runtime.Serialization.Formatters.Binary
-
- Public Class TcpFileReceiver
-
- ' 預設寫入檔案資料夾
- Public SavePath As String = AppDomain.CurrentDomain.BaseDirectory
- ' 監聽器
- Private fileListener As TcpListener
- ' 暫存資料
- Private tempData As Dictionary(Of String, List(Of Byte))
-
- Public Sub New(ByVal ip As IPAddress, ByVal port As Integer)
- Me.fileListener = New TcpListener(New IPEndPoint(ip, port))
- Me.tempData = New Dictionary(Of String, List(Of Byte))
- End Sub
-
- ' 開始監聽
- Public Sub Start()
- Me.fileListener.Start()
- ' 建立接收連線的執行緒
- Dim listenThread As Thread = New Thread(New ThreadStart(AddressOf DeterminConnection))
- listenThread.IsBackground = True
- listenThread.Start()
- End Sub
-
- ' 結束監聽
- Public Sub StopListen()
- Me.fileListener.Stop()
- End Sub
-
- ' 偵測client端連接
- Private Sub DeterminConnection()
- Do
- Try
- ' 如果有連接
- If Me.fileListener.Pending Then
- ' 建立傳輸的執行緒
- Dim receiveThread As Thread = New Thread(New ThreadStart(AddressOf StartServerListener))
- receiveThread.IsBackground = True
- receiveThread.Start()
- End If
- Catch ex As Exception
- ' do something
- End Try
- GC.Collect()
- Thread.Sleep(1000)
- Loop
- End Sub
-
- ' 起始傳輸
- Private Sub StartServerListener()
- Do
- Try
- ' 建立傳輸通道
- Dim rSocket As Socket = Me.fileListener.AcceptSocket()
- If rSocket.Connected Then
- ' 接收連線的buffer
- Dim rBuffer(1024) As Byte
- ' 暫存資料的key
- Dim rGuid As String = Guid.NewGuid.ToString
- ' 開始接收
- SyncLock rSocket
- rSocket.BeginReceive(rBuffer, 0, 1024, SocketFlags.None, AddressOf GetData, New Object() {rSocket, rBuffer, rGuid})
- End SyncLock
- End If
- Catch ex As Exception
- Return
- End Try
- Loop
- End Sub
-
- Private Sub GetData(ByVal result As IAsyncResult)
- Try
- ' 目前傳輸的socket
- Dim rSocket As Socket = CType(result.AsyncState, Object())(0)
- ' 接收的資料
- Dim rBuffer() As Byte = CType(result.AsyncState, Object())(1)
- ' 暫存資料的key
- Dim rGuid As String = CType(result.AsyncState, Object())(2)
-
- ' 如果沒有資料, 建立暫存區
- If Not Me.tempData.ContainsKey(rGuid) Then
- Me.tempData.Add(rGuid, New List(Of Byte))
- End If
-
- ' 讀取的總數
- Dim readed As Integer = rSocket.EndReceive(result)
- If readed > 0 Then
-
- 'Dim data As List(Of Byte) = tempData(rGuid)
- 'For i As Integer = 0 To readed - 1
- ' Me.tempData(rGuid).Add(rBuffer(i))
- 'Next
-
- ' 存入暫存區
- Array.Resize(rBuffer, readed)
- Me.tempData(rGuid).AddRange(rBuffer)
-
- ' 讀取下一段資料
- ReDim rBuffer(1024)
- SyncLock rSocket
- rSocket.BeginReceive(rBuffer, 0, 1024, SocketFlags.None, AddressOf GetData, New Object() {rSocket, rBuffer, rGuid})
- End SyncLock
-
- Else
- rSocket = Nothing
- rBuffer = Nothing
-
- ' 反序列化
- Dim transferObj As TransferFile = Me.Deserialize(Me.tempData(rGuid).ToArray)
-
- ' 存檔
- File.WriteAllBytes(Me.SavePath & transferObj.FileName, transferObj.Data)
- ' 移除暫存資料
- Me.tempData(rGuid).Clear()
- Me.tempData.Remove(rGuid)
- rGuid = Nothing
- ' 資源回收
- GC.Collect()
- End If
- Catch ex As Exception
- ' do something
- End Try
- End Sub
-
- ' 反序列化
- Private Function Deserialize(ByRef data() As Byte) As TransferFile
- Dim ms As MemoryStream = New MemoryStream(data)
- Dim formater As BinaryFormatter = New BinaryFormatter
- Dim transferObj As TransferFile = formater.Deserialize(ms)
- ms.Close()
- Return transferObj
- End Function
-
- End Class
TcpFileSender.vb
- Imports System.IO
- Imports System.Net.Sockets
- Imports System.Net
- Imports System.Threading
- Imports System.SerializableAttribute
- Imports System.Runtime.Serialization.Formatters.Binary
-
- Public Class TcpFileSender
-
- Private client As TcpClient
-
- Public Sub New()
- Me.client = New TcpClient()
- End Sub
-
- Public Function ConnectServer(ByVal ip As IPAddress, ByVal port As Integer) As Boolean
- Try
- ' 連接至server
- Me.client.Connect(New IPEndPoint(ip, port))
- Return True
- Catch ex As Exception
- Return False
- End Try
- End Function
-
- Public Sub CloseConnection()
- Me.client.Close()
- GC.Collect()
- End Sub
-
- Public Sub Send(ByVal filepath As String)
- Dim thread As Thread = New Thread(New ParameterizedThreadStart(AddressOf SendFile))
- thread.IsBackground = True
- thread.Start(filepath)
- End Sub
-
- Public Sub SendFile(ByVal filepath As String)
- ' 檔案不存在
- If Not File.Exists(filepath) Then
- Throw New FileNotFoundException
- End If
-
- ' 建立要傳送的物件實體
- Dim transferObj As TransferFile = New TransferFile
- ' 取檔名
- Dim inputFile As FileInfo = New FileInfo(filepath)
- transferObj.FileName = inputFile.Name
-
- ' 讀取檔案
- Dim inputStream As FileStream = New FileStream(filepath, FileMode.Open)
- ReDim transferObj.Data(inputStream.Length)
- inputStream.Read(transferObj.Data, 0, transferObj.Data.Length)
- inputStream.Close()
-
- ' 序列化
- Dim transferData() As Byte = Me.Serialize(transferObj)
-
- If Me.client.Connected Then
- ' 防止檔案過大, 佇列已滿
- While True
- Try
- Me.client.GetStream.Write(transferData, 0, transferData.Length)
- GC.Collect()
- Exit While
- Catch ex As Exception
- Threading.Thread.Sleep(1000)
- End Try
- End While
- Else
- Throw New Exception("Not Connected!")
- End If
- End Sub
-
- ' 序列化物件
- Private Function Serialize(ByVal obj As Object) As Byte()
- Dim ms As MemoryStream = New MemoryStream
- Dim formater As BinaryFormatter = New BinaryFormatter
- formater.Serialize(ms, obj)
- Dim data() As Byte = ms.GetBuffer
- ms.Close()
- Return data
- End Function
- End Class