2019-03-22 22:19:09 +08:00
#Region "Microsoft.VisualBasic::08c8213225e73b35bd9d520458dbcf8b, Microsoft.VisualBasic.Core\ApplicationServices\Parallel\MMFProtocol\MMFChannel.vb"
2018-08-02 20:14:48 +08:00
2018-10-06 00:02:05 +08:00
' Author:
'
' asuka (amethyst.asuka@gcmodeller.org)
' xie (genetics@smrucc.org)
' xieguigang (xie.guigang@live.com)
'
' Copyright (c) 2018 GPL3 Licensed
'
'
' GNU GENERAL PUBLIC LICENSE (GPL3)
'
'
' This program is free software: you can redistribute it and/or modify
' it under the terms of the GNU General Public License as published by
' the Free Software Foundation, either version 3 of the License, or
' (at your option) any later version.
'
' This program is distributed in the hope that it will be useful,
' but WITHOUT ANY WARRANTY; without even the implied warranty of
' MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
' GNU General Public License for more details.
'
' You should have received a copy of the GNU General Public License
' along with this program. If not, see <http://www.gnu.org/licenses/>.
2018-08-02 20:14:48 +08:00
2018-10-06 00:02:05 +08:00
' /********************************************************************************/
2018-08-02 20:14:48 +08:00
2018-10-06 00:02:05 +08:00
' Summaries:
2018-08-02 20:14:48 +08:00
2018-10-06 00:02:05 +08:00
' Delegate Sub
'
'
' Delegate Sub
'
'
' Class MMFSocket
'
' Properties: NewMessageCallBack, URI
'
' Constructor: (+2 Overloads) Sub New
'
' Function: CreateObject, getMessage, Ping, ReadData, ReadString
' SendMessage, ToString, WriteMessage
'
' Sub: __dataArrival, (+2 Overloads) Dispose, (+3 Overloads) SendMessage
'
'
'
'
'
' /********************************************************************************/
2018-08-02 20:14:48 +08:00
#End Region
Imports Microsoft . VisualBasic . CommandLine . Reflection
Imports Microsoft . VisualBasic . Net . Protocols
2018-10-05 22:12:45 +08:00
Imports Microsoft . VisualBasic . Parallel . MMFProtocol . MapStream
2018-08-02 20:14:48 +08:00
Imports Microsoft . VisualBasic . Text
2018-10-05 22:12:45 +08:00
Namespace Parallel . MMFProtocol
2018-08-02 20:14:48 +08:00
''' <summary>
''' 客户端接受到的数据需要经过反序列化解码方能读取
''' </summary>
''' <param name="data"></param>
''' <remarks></remarks>
Public Delegate Sub DataArrival ( data As Byte ( ) )
''' <summary>
'''
''' </summary>
''' <param name="message">UTF8 string</param>
Public Delegate Sub ReadNewMessage ( message As String )
''' <summary>
''' MMFProtocol socket object for the inter-process communication on the localhost, this can be using for the data exchange between two process.
''' </summary>
''' <remarks></remarks>
<[Namespace]("MMFSocket", Description:="MMFProtocol socket object for the inter-process communication on the localhost, this can be using for the data exchange between two process.")>
Public Class MMFSocket : Implements IDisposable
Dim _MMFReader As MSIOReader , _MMFWriter As MSWriter
Dim _UpdateFlag As Long
Dim _callBacks As DataArrival
Public Property NewMessageCallBack As ReadNewMessage
Public ReadOnly Property URI As String
''' <summary>
'''
''' </summary>
''' <param name="uri"></param>
''' <param name="chunkSize">默认的区块大小为100KB, 这个对于一般的小文本传输已经足够了</param>
Sub New ( uri As String , Optional chunkSize As Long = 100 * 1024 )
_MMFWriter = New MSWriter ( uri , chunkSize )
_MMFReader = New MSIOReader ( uri , AddressOf __dataArrival , chunkSize )
_URI = uri
End Sub
Public Const MMF_PROTOCOL As String = " mmf:// "
''' <summary>
'''
''' </summary>
''' <param name="uri"></param>
''' <param name="dataArrivals">
''' Public Delegate Sub <see cref="__dataArrival"/>(byteData As <see cref="System.Byte"/>())
''' 会优先于事件<see cref="__dataArrival"></see>的发生</param>
''' <remarks></remarks>
Sub New ( uri As String , dataArrivals As DataArrival )
Call Me . New ( uri )
_callBacks = dataArrivals
End Sub
Public Sub SendMessage ( byteData As Byte ( ) )
Me . _UpdateFlag = _MMFReader . Read . udtBadge + 1
Dim bytData As Byte ( ) = New MMFStream With {
. byteData = byteData ,
. udtBadge = Me . _UpdateFlag
} . Serialize
Call _MMFReader . Update ( Me . _UpdateFlag )
Call _MMFWriter . WriteStream ( bytData )
End Sub
''' <summary>
''' 直接从映射文件之中读取数据
''' </summary>
''' <returns></returns>
Public Function ReadData ( ) As Byte ( )
Return _MMFReader . Read . byteData
End Function
Public Sub SendMessage ( raw As RawStream )
Call SendMessage ( raw . Serialize )
End Sub
''' <summary>
'''
''' </summary>
''' <param name="s"><see cref="System.Text.Encoding.UTF8"/></param>
Public Sub SendMessage ( s As String )
Dim buf As Byte ( ) = System . Text . Encoding . UTF8 . GetBytes ( s )
Call Me . SendMessage ( buf )
End Sub
Public Function ReadString ( ) As String
Dim buf As Byte ( ) = ReadData ( )
Dim s As String = System . Text . Encoding . UTF8 . GetString ( buf )
Return s
End Function
#Region "IDisposable Support"
Private disposedValue As Boolean ' To detect redundant calls
' IDisposable
Protected Overridable Sub Dispose ( disposing As Boolean )
If Not Me . disposedValue Then
If disposing Then
' TODO: dispose managed state (managed objects).
Call Me . _MMFWriter . Free
Call Me . _MMFReader . Free
End If
' TODO: free unmanaged resources (unmanaged objects) and override Finalize() below.
' TODO: set large fields to null.
End If
Me . disposedValue = True
End Sub
' TODO: override Finalize() only if Dispose( disposing As Boolean) above has code to free unmanaged resources.
'Protected Overrides Sub Finalize()
' ' Do not change this code. Put cleanup code in Dispose( disposing As Boolean) above.
' Dispose(False)
' MyBase.Finalize()
'End Sub
' This code added by Visual Basic to correctly implement the disposable pattern.
Public Sub Dispose ( ) Implements IDisposable . Dispose
' Do not change this code. Put cleanup code in Dispose(disposing As Boolean) above.
Dispose ( True )
GC . SuppressFinalize ( Me )
End Sub
#End Region
Public Overrides Function ToString ( ) As String
Return $ " {MMF_PROTOCOL}{_URI} "
End Function
Public Function Ping ( ) As Boolean
Call SendMessage ( s : = _PING_MESSAGE )
Call Threading . Thread . Sleep ( 100 )
If PingResult = True Then
PingResult = False
Return True
Else
Return False
End If
End Function
Private Const _PING_MESSAGE As String = " PINT_REQUEST::{BAB0B3FA-C3F3-42F2-A577-9AF57EBDB9C7} "
Private Const _PING_RETURNS As String = " PING_RETURNS::{BAB0B3FA-C3F3-42F2-A577-9AF57EBDB9C7} "
Dim PingResult As Boolean = False
Private Sub __dataArrival ( data ( ) As Byte )
Dim s_MSG As String = System . Text . Encoding . Unicode . GetString ( data )
If String . Equals ( s_MSG , _PING_MESSAGE ) Then
Call SendMessage ( _PING_RETURNS )
ElseIf String . Equals ( s_MSG , _PING_RETURNS ) Then
PingResult = True
Else
If Not _callBacks Is Nothing Then
Call _callBacks ( data )
End If
If Not NewMessageCallBack Is Nothing Then
Call NewMessageCallBack ( ) ( s_MSG )
End If
End If
End Sub
#Region "ShellScript API"
<ExportAPI("MMFProtocol.New")>
Public Shared Function CreateObject ( hostName As String , Optional handler As Action ( Of Generic . IEnumerable ( Of Byte ) ) = Nothing ) As MMFProtocol . MMFSocket
Dim CallBackHandle As DataArrival = New DataArrival ( Sub ( data As Byte ( ) ) handler ( data ) )
Return New MMFSocket ( hostName , CallBackHandle )
End Function
<ExportAPI("SendMessage")>
Public Shared Function SendMessage ( socket As MMFSocket , data As Generic . IEnumerable ( Of Byte ) ) As Boolean
Try
Call socket . SendMessage ( data . ToArray )
Return True
Catch ex As Exception
Return False
End Try
End Function
<ExportAPI("getMessage")>
Public Shared Function getMessage ( data As Generic . IEnumerable ( Of Byte ) , Optional encoding As String = " " ) As String
Return TextFileEncodingDetector . ToString ( data , encoding )
End Function
<ExportAPI("Print.Message")>
Public Shared Function WriteMessage ( data As Generic . IEnumerable ( Of Byte ) ) As String
Dim Message As String = getMessage ( data )
Call Console . WriteLine ( Message )
Return Message
End Function
#End Region
End Class
End Namespace