NETリモーティング(TCP)にて双方向通信を行いたい
環境(VB2008 or VB2010)
Client → Server = OK
Server → Client = NG (色々試したが・・・)
以下がソースです。宜しくお願いします。
------ 共有クラス ------------------
( 送受信用に2つのクラスを作成 )
Imports System.Runtime.Remoting
'メッセージクラス
Public Class MessageClass
Inherits MarshalByRefObject
' 受信イベント(サーバ)
Public Event RecvMsg_Server(ByVal msg As String)
' 受信イベント(クライアント)
Public Event RecvMsg_Client(ByVal msg As String)
' 送信メソッド(クライアント)
Public Sub SendMsg_Client(ByVal msg As String)
' 受信用イベント発生
RaiseEvent RecvMsg_Server(msg)
End Sub
' 送信メソッド(サーバ)
Public Sub SendMsg_Server(ByVal msg As String)
' 受信用イベント発生
RaiseEvent RecvMsg_Client(msg)
End Sub
End Class
------ サーバ ----------------------
Imports System.Runtime.Remoting
Imports System.Runtime.Remoting.Channels
Imports System.Runtime.Remoting.Channels.Tcp
Public Class Fm_Server
' 受信用のチャンネル
Private RecvCh As TcpChannel
' 送受信用のメッセージクラス
Private WithEvents MesObj As New Serviceclass.MessageClass
Private Sub Form1_Load(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles MyBase.Load
' HTTPチャンネルを設定する
RecvCh = New TcpChannel(9000)
ChannelServices.RegisterChannel(RecvCh, False)
Dim ref1 As ObjRef = RemotingServices.Marshal(MesObj, "TaskManager")
' ハンドルを登録する
AddHandler MesObj.RecvMsg_Server, AddressOf RecvMsg
' 受付を開始する
RecvCh.StartListening(Nothing)
End Sub
Private Sub RecvMsg(ByVal msg As String)
' メッセージを受信
Me.LabelMessage.Text = msg
Dim SendObj As Serviceclass.MessageClass = New Serviceclass.MessageClass
' メッセージを送信
SendObj.SendMsg_Client("受け取りました")
End Sub
End Class
------- クライアント ----------------------
(ハンドルを登録部分を色々と変えてみたが・・・)
Imports System.Runtime.Remoting
Imports System.Runtime.Remoting.Channels
Imports System.Runtime.Remoting.Channels.Tcp
Public Class Fm_Client
' 受信用のチャンネル
Private SendCh As TcpChannel
Private WithEvents MesObj As Serviceclass.MessageClass
Private Sub Button1_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles Button1.Click
MesObj = New Serviceclass.MessageClass
' メッセージを送信する
MesObj.SendMsg_Client(TextBox1.Text)
' ハンドルを登録
'AddHandler MesObj.RecvMsg_Client, AddressOf RecvMsg
End Sub
Private Sub Fm_Client_Load(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles MyBase.Load
' 送信用のチャンネル
SendCh = New TcpChannel()
ChannelServices.RegisterChannel(SendCh, False)
RemotingConfiguration.RegisterWellKnownClientType( _
GetType(Serviceclass.MessageClass), _
"tcp://localhost:9000/TaskManager")
End Sub
Private Sub RecvMsg(ByVal msg As String)
' メッセージを受信
Me.TextBox2.Text = msg
End Sub
End Class
ぷっ。
村人には不要ですよ。
非常に面倒くさいですが……。
・イベントオブジェクトをSerailizableにする
・TcpChannelを作成する時に,BinaryServerFormatterSinkProviderを指定する (TypeFilterLevel = Full)
・クライアント側ではブリッジオブジェクトを用意して,そちらにイベントを登録する
といった作業が必要です。
意味合い的にはブリッジオブジェクトはMarshalByRefである必要があるだけなので,
Formのメソッドを指定する場合はブリッジオブジェクトはおそらく不要です。
とりあえず,サンプルを作ってみました (VB 2010 Express)。
http://pub.idisk-just.com/fview/98fI_0mdha_U3o_4lKdf8e4NKDp3qGN8dbfcUu0I0c7ZiYNto3nQzOKlYVSaloz_1vCF3sTCiMReHw1ALOL7YA.zip
あまり綺麗ではないですが,確認はできるかと思います。
Eratta:
誤)・イベントオブジェクトをSerailizableにする
正)・イベントオブジェクトをSerializableにする