在现代软件开发中,跨平台和跨语言的通信变得越来越重要。本文将介绍如何使用Eneter Messaging Framework实现Silverlight客户端应用与Java服务应用之间的通信。Eneter Messaging Framework是一个免费的框架,支持多种通信场景,可以方便地实现不同应用程序之间的消息传递。
策略服务器是一种特殊的服务,它监听在端口943上。该服务接收策略文件请求(<policy-file-request>
),并响应策略文件,该文件指明谁被允许进行通信。Silverlight在创建TCP连接时会自动使用这个服务。它会在端口943上发送请求,并期待策略文件。如果策略服务器不存在,或者策略文件的内容不允许通信,那么TCP连接将不会被创建。
客户端是一个简单的Silverlight应用程序,包含一个按钮用于发送计算数字的请求。整个实现过程非常简单。以下是C#语言的实现代码:
using System;
using System.Windows;
using System.Windows.Controls;
using Eneter.Messaging.EndPoints.TypedMessages;
using Eneter.Messaging.MessagingSystems.MessagingSystemBase;
using Eneter.Messaging.MessagingSystems.TcpMessagingSystem;
namespace CalculatorClient
{
public partial class MainPage : UserControl
{
public class MyRequestMsg
{
public double Number1 { get; set; }
public double Number2 { get; set; }
}
public class MyResponseMsg
{
public double Result { get; set; }
}
// Sender sending MyRequestMsg and receiving responses of type MyResponseMsg.
private IDuplexTypedMessageSender<MyResponseMsg, MyRequestMsg> mySender;
public MainPage()
{
InitializeComponent();
OpenConnection();
}
private void OpenConnection()
{
// Create message sender.
IDuplexTypedMessagesFactory aSenderFactory = new DuplexTypedMessagesFactory();
mySender = aSenderFactory.CreateDuplexTypedMessageSender<MyResponseMsg, MyRequestMsg>();
// Subscribe to receive response messages.
mySender.ResponseReceived += OnResponseReceived;
// Create TCP messaging.
IMessagingSystemFactory aMessaging = new TcpMessagingSystemFactory();
IDuplexOutputChannel anOutputChannel = aMessaging.CreateDuplexOutputChannel("tcp://127.0.0.1:4502/");
// Attach the output channel to the message sender and be able to
// send messages and receive responses.
mySender.AttachDuplexOutputChannel(anOutputChannel);
}
private void UserControl_Unloaded(object sender, RoutedEventArgs e)
{
// Detach the output channel and stop listening to responses.
mySender.DetachDuplexOutputChannel();
}
private void CalculateBtn_Click(object sender, RoutedEventArgs e)
{
// Create the request message.
MyRequestMsg aRequestMsg = new MyRequestMsg();
aRequestMsg.Number1 = Double.Parse(Number1TextBox.Text);
aRequestMsg.Number2 = Double.Parse(Number2TextBox.Text);
// Send request to calculate two numbers.
mySender.SendRequestMessage(aRequestMsg);
}
// It is called when a response message is received.
// Note: By defaulut the response comes in the silverlight thread.
// If it is not desired, the routing to the Silverlight thread can be disabled.
private void OnResponseReceived(object sender, TypedResponseReceivedEventArgs<MyResponseMsg> e)
{
// Display the result.
ResultTextBox.Text = e.ResponseMessage.Result.ToString();
}
}
}
服务应用是一个简单的Java应用程序,通过TCP通信并计算数字。它还包含了Silverlight通信所需的TCP策略服务器。以下是Java语言的实现代码:
package calculator;
import java.io.*;
import eneter.messaging.diagnostic.EneterTrace;
import eneter.messaging.endpoints.typedmessages.*;
import eneter.messaging.messagingsystems.messagingsystembase.*;
import eneter.messaging.messagingsystems.tcpmessagingsystem.*;
import eneter.net.system.EventHandler;
public class Program
{
public static class MyRequestMsg
{
public double Number1;
public double Number2;
}
public static class MyResponseMsg
{
public double Result;
}
// Receiver receiving MyResponseMsg and responding MyRequestMsg
private static IDuplexTypedMessageReceiver<MyResponseMsg, MyRequestMsg> myReceiver;
public static void main(String[] args) throws Exception
{
// Start the TCP Policy server.
// Note: Silverlight requests the policy xml to check if the connection
// can be established.
TcpPolicyServer aPolicyServer = new TcpPolicyServer();
aPolicyServer.startPolicyServer();
// Create receiver that receives MyRequestMsg and
// responses MyResponseMsg
IDuplexTypedMessagesFactory aReceiverFactory = new DuplexTypedMessagesFactory();
myReceiver = aReceiverFactory.createDuplexTypedMessageReceiver(MyResponseMsg.class, MyRequestMsg.class);
// Subscribe to handle incoming messages.
myReceiver.messageReceived().subscribe(myOnMessageReceived);
// Create input channel listening to TCP.
// Note: Silverlight can communicate only on ports: 4502 - 4532
IMessagingSystemFactory aMessaging = new TcpMessagingSystemFactory();
IDuplexInputChannel anInputChannel = aMessaging.createDuplexInputChannel("tcp://127.0.0.1:4502/");
// Attach the input channel to the receiver and start the listening.
myReceiver.attachDuplexInputChannel(anInputChannel);
System.out.println("Calculator service is running. Press ENTER to stop.");
new BufferedReader(new InputStreamReader(System.in)).readLine();
// Detach the duplex input channel and stop the listening.
// Note: it releases the thread listening to messages.
myReceiver.detachDuplexInputChannel();
// Stop the TCP policy server.
aPolicyServer.stopPolicyServer();
}
private static void onMessageReceived(Object sender, TypedRequestReceivedEventArgs<MyRequestMsg> e)
{
// Calculate incoming numbers.
double aResult = e.getRequestMessage().Number1 + e.getRequestMessage().Number2;
System.out.println(e.getRequestMessage().Number1 +
" + " +
e.getRequestMessage().Number2 +
" = " + aResult);
// Response back the result.
MyResponseMsg aResponseMsg = new MyResponseMsg();
aResponseMsg.Result = aResult;
try
{
myReceiver.sendResponseMessage(e.getResponseReceiverId(), aResponseMsg);
}
catch (Exception err)
{
EneterTrace.error("Sending the response message failed.", err);
}
}
// Handler used to subscribe for incoming messages.
private static EventHandler<TypedRequestReceivedEventArgs<MyRequestMsg>> myOnMessageReceived
=
new EventHandler<TypedRequestReceivedEventArgs<MyRequestMsg>>()
{
@Override
public void onEvent(Object sender, TypedRequestReceivedEventArgs<MyRequestMsg> e)
{
onMessageReceived(sender, e);
}
};
}