NETリモーティング(TCP) 双方向通信


くまきち  2010-08-31 11:22:33  No: 147149  IP: [192.*.*.*]

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

編集 削除
三木谷浩  2010-08-31 21:11:34  No: 147150  IP: [192.*.*.*]

ぷっ。
村人には不要ですよ。

編集 削除
YuO  2010-09-06 14:50:32  No: 147151  IP: [192.*.*.*]

非常に面倒くさいですが……。

・イベントオブジェクトをSerailizableにする
・TcpChannelを作成する時に,BinaryServerFormatterSinkProviderを指定する (TypeFilterLevel = Full)
・クライアント側ではブリッジオブジェクトを用意して,そちらにイベントを登録する

といった作業が必要です。
意味合い的にはブリッジオブジェクトはMarshalByRefである必要があるだけなので,
Formのメソッドを指定する場合はブリッジオブジェクトはおそらく不要です。


とりあえず,サンプルを作ってみました (VB 2010 Express)。
http://pub.idisk-just.com/fview/98fI_0mdha_U3o_4lKdf8e4NKDp3qGN8dbfcUu0I0c7ZiYNto3nQzOKlYVSaloz_1vCF3sTCiMReHw1ALOL7YA.zip
あまり綺麗ではないですが,確認はできるかと思います。

編集 削除
YuO  2010-09-08 16:15:09  No: 147152  IP: [192.*.*.*]

Eratta:
誤)・イベントオブジェクトをSerailizableにする
正)・イベントオブジェクトをSerializableにする

編集 削除