automaticly send large data as packages

This commit is contained in:
schedpas
2020-06-09 09:35:06 +02:00
parent 6e33874df6
commit bf77505f42
3 changed files with 112 additions and 26 deletions

View File

@@ -4,7 +4,10 @@ Imports Newtonsoft.Json.Linq
Public MustInherit Class ConnectionManagerBase Public MustInherit Class ConnectionManagerBase
Private Const HEADER_LENGTH As Integer = 12
Private listening As Boolean = False Private listening As Boolean = False
Private ReadOnly dicData As New Dictionary(Of Integer, Dictionary(Of Integer, Byte()))
Public ReadOnly Property Port As Integer Public ReadOnly Property Port As Integer
Public Property UseAssemblyQualifiedName As Boolean = False Public Property UseAssemblyQualifiedName As Boolean = False
@@ -31,6 +34,7 @@ Public MustInherit Class ConnectionManagerBase
Public MustOverride Sub Start() Public MustOverride Sub Start()
Public MustOverride Sub [Stop]() Public MustOverride Sub [Stop]()
Protected MustOverride Sub SendData(endPoint As IPEndPoint, data As Byte()) Protected MustOverride Sub SendData(endPoint As IPEndPoint, data As Byte())
Protected MustOverride Function GetBufferSize() As Integer
Public Overridable Sub Send(empfängerIP As String, cmd As String) Public Overridable Sub Send(empfängerIP As String, cmd As String)
Send(empfängerIP, cmd, String.Empty) Send(empfängerIP, cmd, String.Empty)
@@ -45,21 +49,108 @@ Public MustInherit Class ConnectionManagerBase
End Sub End Sub
Protected Sub ProcessRetrivedData(senderIP As String, buf As Byte()) Protected Sub ProcessRetrivedData(senderIP As String, buf As Byte())
Dim contentstring As String = Text.Encoding.Default.GetString(buf) Dim readInteger =
Dim content As Object = Nothing Function(index As Integer) As Integer
Dim cmd As String = String.Empty Return (CInt(buf(index)) << 24) Or (CInt(buf(index + 1)) << 16) Or (CInt(buf(index + 2)) << 8) Or buf(index + 3)
End Function
Try Dim dataID As Integer = readInteger(0)
Dim res = DecodeFromBytes(buf) Dim packageID As Integer = readInteger(4)
cmd = res.cmd Dim packageCount As Integer = readInteger(8)
content = res.content Dim resolveData As Boolean = True
Catch ex As Exception
End Try
RaiseRetriveData(senderIP, cmd, content) 'Remember data
Dim data As Byte() = buf.Skip(HEADER_LENGTH).ToArray
Dim dicMyData As Dictionary(Of Integer, Byte())
If dicData.ContainsKey(dataID) Then
dicMyData = dicData(dataID)
If dicMyData.ContainsKey(packageID) Then
dicMyData(packageID) = data
Else
dicMyData.Add(packageID, data)
End If
Else
dicMyData = New Dictionary(Of Integer, Byte()) From {{packageID, data}}
dicData.Add(dataID, dicMyData)
End If
If dicMyData.Count < packageCount Then
resolveData = False
End If
'Resolve Data
If resolveData Then
If dicMyData Is Nothing Then
dicMyData = dicData(dataID)
End If
Dim myData As New List(Of Byte)
For Each kvp In dicMyData.OrderBy(Function(n) n.Key)
myData.AddRange(kvp.Value)
Next
dicMyData.Remove(dataID)
Dim content As Object = Nothing
Dim cmd As String = String.Empty
Try
Dim res = DecodeFromBytes(myData.ToArray)
cmd = res.cmd
content = res.content
Catch ex As Exception
End Try
RaiseRetriveData(senderIP, cmd, content)
End If
End Sub End Sub
Protected Shared Function EncodeToBytes(cmd As String, content As Object, useAssemblyQualifiedName As Boolean) As Byte() Public Sub Send(empfängerIP As String, cmd As String, content As Object)
Static rnd As New Random
Dim ep As New IPEndPoint(GetIPFromHost(empfängerIP).MapToIPv4, Port)
Dim finalBuffer As New List(Of Byte)
Dim maxBufferSize As Integer = GetBufferSize()
Dim maxDataSize As Integer = maxBufferSize - HEADER_LENGTH
Dim data As Byte() = EncodeToBytes(cmd, content, UseAssemblyQualifiedName)
Dim dataID As Integer = rnd.Next
'Some methods for later user
Dim send = Sub() SendData(ep, finalBuffer.ToArray)
Dim addInteger =
Sub(value As Integer)
finalBuffer.AddRange({(value >> 24) And &HFF, (value >> 16) And &HFF, (value >> 8) And &HFF, value And &HFF})
End Sub
Dim addHeader =
Sub(packageID As Integer, packagesCount As Integer)
addInteger(dataID) 'Data ID
addInteger(packageID) 'Package ID
addInteger(packagesCount) 'Packages Count
End Sub
'Send data (this if statement and else content might be useless)
If data.Length > maxDataSize Then
Dim curIndex As Integer = 0
Dim curID As Integer = 0
Dim packagesCount As Integer = Math.Ceiling(data.Length / maxDataSize)
Do While curIndex < data.Length
finalBuffer.Clear()
addHeader(curID, packagesCount)
For i As Integer = 1 To maxDataSize
If curIndex < data.Length Then
finalBuffer.Add(data(curIndex))
curIndex += 1
End If
Next
send()
curID += 1
Loop
Else
addHeader(0, 1)
finalBuffer.AddRange(data)
send()
End If
End Sub
Private Shared Function EncodeToBytes(cmd As String, content As Object, useAssemblyQualifiedName As Boolean) As Byte()
Dim ms As New MemoryStream() Dim ms As New MemoryStream()
Dim bw As New BinaryWriter(ms) Dim bw As New BinaryWriter(ms)
Dim obj As New JObject Dim obj As New JObject
@@ -81,7 +172,7 @@ Public MustInherit Class ConnectionManagerBase
Return buf Return buf
End Function End Function
Protected Shared Function DecodeFromBytes(buf As Byte()) As (cmd As String, content As Object) Private Shared Function DecodeFromBytes(buf As Byte()) As (cmd As String, content As Object)
Dim contentstring As String = Text.Encoding.Default.GetString(buf) Dim contentstring As String = Text.Encoding.Default.GetString(buf)
Dim content As Object = Nothing Dim content As Object = Nothing
Dim contentobj As JObject = JObject.Parse(contentstring) Dim contentobj As JObject = JObject.Parse(contentstring)
@@ -98,11 +189,4 @@ Public MustInherit Class ConnectionManagerBase
Return (cmd, content) Return (cmd, content)
End Function End Function
Public Sub Send(empfängerIP As String, cmd As String, content As Object)
Dim ep As New IPEndPoint(GetIPFromHost(empfängerIP).MapToIPv4, Port)
Dim buf As Byte() = EncodeToBytes(cmd, content, UseAssemblyQualifiedName)
SendData(ep, buf)
End Sub
End Class End Class

View File

@@ -23,9 +23,6 @@ Public Class TCPManager
End If End If
End Sub End Sub
''' <summary>
''' Stop listening on given port.
''' </summary>
Public Overrides Sub [Stop]() Public Overrides Sub [Stop]()
If IsListening Then If IsListening Then
IsListening = False IsListening = False
@@ -33,6 +30,10 @@ Public Class TCPManager
End If End If
End Sub End Sub
Protected Overrides Function GetBufferSize() As Integer
Return BufferSize
End Function
Private Sub CheckRetriveData() Private Sub CheckRetriveData()
Do While IsListening Do While IsListening
If listener.Pending Then If listener.Pending Then

View File

@@ -12,7 +12,7 @@ Public Class UDPManager
Private listenTask As Task = Nothing Private listenTask As Task = Nothing
Private ReadOnly cancelTokenSource As New CancellationTokenSource Private ReadOnly cancelTokenSource As New CancellationTokenSource
Private ReadOnly cancelToken As CancellationToken = cancelTokenSource.Token Private ReadOnly cancelToken As CancellationToken = cancelTokenSource.Token
Public ReadOnly Property MaxBufferSize As Integer = &H10000 Public ReadOnly Property MaxBufferSize As Integer = 8192
Public Sub New(port As Integer) Public Sub New(port As Integer)
MyBase.New(port) MyBase.New(port)
@@ -43,9 +43,6 @@ Public Class UDPManager
End Sub) End Sub)
End Sub End Sub
''' <summary>
''' Stop listening on given port.
''' </summary>
Public Overrides Sub [Stop]() Public Overrides Sub [Stop]()
If IsListening Then If IsListening Then
IsListening = False IsListening = False
@@ -54,6 +51,10 @@ Public Class UDPManager
End If End If
End Sub End Sub
Protected Overrides Function GetBufferSize() As Integer
Return MaxBufferSize
End Function
Private Sub RetriveAnyData(ct As CancellationToken) Private Sub RetriveAnyData(ct As CancellationToken)
Dim doExit = Sub() ct.ThrowIfCancellationRequested() Dim doExit = Sub() ct.ThrowIfCancellationRequested()
Dim receiveTask As Task(Of UdpReceiveResult) = client.ReceiveAsync() Dim receiveTask As Task(Of UdpReceiveResult) = client.ReceiveAsync()