锐英源软件
第一信赖

精通

英语

开源

擅长

开发

培训

胸怀四海 

第一信赖

当前位置:锐英源 / C#开源英语 / .NET使用协议缓冲技术和安卓平台进行快速通信
服务方向
人工智能数据处理
人工智能培训
kaldi数据准备
小语种语音识别
语音识别标注
语音识别系统
语音识别转文字
kaldi开发技术服务
软件开发
运动控制卡上位机
机械加工软件
软件开发培训
Java 安卓移动开发
VC++
C#软件
汇编和破解
驱动开发
联系方式
固话:0371-63888850
手机:138-0381-0136
Q Q:396806883
微信:ryysoft

.NET使用协议缓冲技术和安卓平台进行快速通信


介绍

本文不适合初学者,适合有半年一年工作经验的朋友,对复杂环境能理解的朋友来学习跨平台序列化。熟悉MFC的CArchive类的朋友相对好理解些。
在跨平台(例如Android和.NET之间)进行通信时,进程间通信所面临的挑战之一是如何对消息进行编码(序列化),以便两种平台都能够理解它们。由平台提供的默认二进制序列化程序不兼容,因此常见的解决方案是将消息编码为某种文本格式,例如XML或JSON。在许多情况下,这可能完全可以,但对于使用文本格式的期望高性能的应用程序来说,可能不是最佳解决方案。
下面的示例演示了如何在Android和.NET应用程序的进程间通信中使用Protocol Buffers二进制序列化。

你需要下载


为了构建示例源代码,您需要将对相关库的引用添加到项目中。要获得这些库,你可以下载:
Eneter.ProtoBuf.Serializer – 适用于Eneter的协议缓冲器序列化程序,它还包含已编译的协议缓冲区库和'proto'文件的实用程序应用程序。
Eneter.Messaging.Framework - 通信框架。
Protocol Buffers库是开源项目,可以在以下网址找到:
protobuf - Google针对Java,C ++和Python的Protocol Buffers实现。
protobuf-net - 用于.NET平台的Marc Gravell的协议缓冲区实现。
Eneter.ProtoBuf.Serializer - 集成Protocol Buffers和Eneter Messaging Framework的开源项目。

将以下参考添加到您的项目中


进入.NET项目:
protobuf-net.dll - 由Marc Gravell开发的协议缓冲,适用于.NET, Windows Phone,Silverlight和Compact Framework。
Eneter.ProtoBuf.Serializer.dll - 使用protobuf-net.dll为Eneter Messaging Framework实现序列化程序。
Eneter.Messaging.Framework.dll - 用于进程间通信的轻量级跨平台框架。
进入Android项目:
protobuf.jar - 由Google开发的用于Java和Android的协议缓冲区序列化程序。
eneter-protobuf-serializer.jar - 使用Google的protobuf.jar实现Eneter Messaging Framework的序列化程序。
eneter-messaging.jar - 用于进程间通信的轻量级跨平台框架。
重要提示:请按照此过程(为Eclipse)中添加库到Android项目:
(添加库到项目,您需要导入它,而不是通过项目属性添加。
此外,还要确保Java兼容6.0。属性- > Java编译器 - > JDK合规性 - > 1.6。)
在您的项目中创建一个新的文件夹'libs'。(使用完全名称库)
右键点击'libs'并选择'Import ...' - >'General / File System' - >'Next'
然后点击“从目录”的“浏览器”按钮并导航到包含要添加的库的目录。
选择您想要添加的库的复选框。
按'完成'

协议缓冲区


协议缓冲区是Google最初开发的一种二进制序列化,用于在使用Java,C ++和Python等不同语言开发的应用程序之间共享数据。它成为开源软件,并被移植到其他语言和平台上。
协议缓冲区的最大优点是性能和多平台可用性,这得它在设计应用程序之间的通信时成为可选目标。
如果您有兴趣,可以在https://code.google.com/p/eneter-protobuf-serializer/wiki/PerformanceMeasurements上找到简单的性能测量。

使用协议缓冲区


以下过程针对跨平台通信定义消息进行了优化:( 
如果您只想在.NET中使用协议缓冲区,则不必通过'proto'文件声明消息,但可以直接在源代码中声明它们归类 - 与使用DataContractSerializer相同。)
在'proto'文件中声明消息。
将'proto'文件编译为源代码(C#和Java)。它将声明的消息转换为包含指定字段和序列化功能的类。
将生成的源文件包含到C#和Java项目中。
初始化Eneter通信组件以供使用EneterProtoBufSerializer。
buffer架构1

示例代码


下面的示例与我之前的文章Android完全相同:如何通过TCP与.NET应用程序进行通信。唯一的区别是本文中的代码使用EneterProtoBufSerializer代替XmlStringSerializer。
请参考Android:如果您需要有关如何在Android上使用TCP以及如何在模拟器中设置IP地址的详细信息,请通过TCP与.NET应用程序进行通信
buffer架构2

原型文件


'proto'文件表示描述应该用于交互的消息的协议。消息在平台中声明为中立protocol buffer language- 有关语法的详细信息,请参阅https://developers.google.com/protocol-buffers/docs/proto
我们示例中的消息在MessageDeclarations.proto文件中声明:


// Request Message
message MyRequest
{
required string Text = 1;
}

// Response Message
message MyResponse
{
required int32 Length = 1;
}

然后将'proto'文件编译为C#和Java源代码。声明的消息被转换为包含声明字段和序列化功能的类。
我们的例子中使用了以下命令来编译'proto'文件:


protogen.exe -i:MessageDeclarations.proto -o:MessageDeclarations.cs
protoc.exe -I=./ --java_out=./ ./MessageDeclarations.proto

Android客户端应用程序


Android客户端是一个非常简单的应用程序,允许用户放置一些文本消息并将请求发送到服务以获取文本的长度。
收到响应消息时,必须将其封送到UI线程以显示结果。

客户使用EneterProtoBufSerializer。它在openConnection()方法中实例化序列化程序,并将其引用提供给DuplexTypedMessagesFactory以保证消息发送方将使用协议缓冲区。

整个实施非常简单:


package net.client;

import message.declarations.MessageDeclarations.*;
import eneter.messaging.dataprocessing.serializing.ISerializer;
import eneter.messaging.diagnostic.EneterTrace;
import eneter.messaging.endpoints.typedmessages.*;
import eneter.messaging.messagingsystems.messagingsystembase.*;
import eneter.messaging.messagingsystems.tcpmessagingsystem.TcpMessagingSystemFactory;
import eneter.net.system.EventHandler;
import eneter.protobuf.ProtoBufSerializer;
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.*;

public class AndroidNetCommunicationClientActivity extends Activity
{
// UI controls
private Handler myRefresh = new Handler();
private EditText myMessageTextEditText;
private EditText myResponseEditText;
private Button mySendRequestBtn;


// Sender sending MyRequest and as a response receiving MyResponse.
private IDuplexTypedMessageSender<MyResponse, MyRequest> mySender;

/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);

// Get UI widgets.
myMessageTextEditText = (EditText) findViewById(R.id.messageTextEditText);
myResponseEditText = (EditText) findViewById(R.id.messageLengthEditText);
mySendRequestBtn = (Button) findViewById(R.id.sendRequestBtn);

// Subscribe to handle the button click.
mySendRequestBtn.setOnClickListener(myOnSendRequestClickHandler);

// Open the connection in another thread.
// Note: From Android 3.1 (Honeycomb) or higher
//       it is not possible to open TCP connection
//       from the main thread.
Thread anOpenConnectionThread = new Thread(new Runnable()
{
@Override
public void run()
{
try
{
openConnection();
}
catch (Exception err)
{
EneterTrace.error("Open connection failed.", err);
}
}
});
anOpenConnectionThread.start();
}

@Override
public void onDestroy()
{
// Stop listening to response messages.
mySender.detachDuplexOutputChannel();

super.onDestroy();
}

private void openConnection() throws Exception
{
// Instantiate Protocol Buffer based serializer.
ISerializer aSerializer = new ProtoBufSerializer();

// Create sender sending MyRequest and as a response receiving MyResponse
// The sender will use Protocol Buffers to serialize/deserialize messages.
IDuplexTypedMessagesFactory aSenderFactory = new DuplexTypedMessagesFactory(aSerializer);
mySender = aSenderFactory.createDuplexTypedMessageSender(MyResponse.class, MyRequest.class);

// Subscribe to receive response messages.
mySender.responseReceived().subscribe(myOnResponseHandler);

// Create TCP messaging for the communication.
// Note: 10.0.2.2 is a special alias to the loopback (127.0.0.1)
//       on the development machine.
IMessagingSystemFactory aMessaging = new TcpMessagingSystemFactory();

IDuplexOutputChannel anOutputChannel
= aMessaging.createDuplexOutputChannel("tcp://10.0.2.2:8060/");
//= aMessaging.createDuplexOutputChannel("tcp://192.168.1.102:8060/");

// Attach the output channel to the sender and be able to send
// messages and receive responses.
mySender.attachDuplexOutputChannel(anOutputChannel);
}

private void onSendRequest(View v)
{
// Create the request message using ProtoBuf builder pattern.
final MyRequest aRequestMsg = MyRequest.newBuilder()
.setText(myMessageTextEditText.getText().toString())
.build();

// Send the request message.
try
{
mySender.sendRequestMessage(aRequestMsg);
}
catch (Exception err)
{
EneterTrace.error("Sending the message failed.", err);
}

}

private void onResponseReceived(Object sender,
final TypedResponseReceivedEventArgs<MyResponse> e)
{
// Display the result - returned number of characters.
// Note: Marshal displaying to the correct UI thread.
myRefresh.post(new Runnable()
{
@Override
public void run()
{
myResponseEditText.setText(Integer.toString(e.getResponseMessage().getLength()));
}
});
}

private EventHandler<TypedResponseReceivedEventArgs<MyResponse>> myOnResponseHandler
= new EventHandler<TypedResponseReceivedEventArgs<MyResponse>>()
{
@Override
public void onEvent(Object sender,
TypedResponseReceivedEventArgs<MyResponse> e)
{
onResponseReceived(sender, e);
}
};

private OnClickListener myOnSendRequestClickHandler = new OnClickListener()
{
@Override
public void onClick(View v)
{
onSendRequest(v);
}
};
}

.NET服务应用程序


.NET服务是一个简单的控制台应用程序,用于侦听TCP并接收请求来计算给定文本的长度。

该服务使用EneterProtoBufSerializer。它实例化序列化器并将其引用提供给DuplexTypedMessagesFactory以保证消息接收器将使用协议缓冲器来反序列化传入消息并序列化响应消息。

整个实施非常简单:


using System;
using Eneter.Messaging.DataProcessing.Serializing;
using Eneter.Messaging.EndPoints.TypedMessages;
using Eneter.Messaging.MessagingSystems.MessagingSystemBase;
using Eneter.Messaging.MessagingSystems.TcpMessagingSystem;
using Eneter.ProtoBuf;
using message.declarations;

namespace ServiceExample
{
class Program
{
private static IDuplexTypedMessageReceiver<MyResponse, MyRequest> myReceiver;

        static void Main(string[] args)
{
// Instantiate Protocol Buffer based serializer.
ISerializer aSerializer = new ProtoBufSerializer();

            // Create message receiver receiving 'MyRequest' and receiving 'MyResponse'.
// The receiver will use Protocol Buffers to serialize/deserialize messages.
IDuplexTypedMessagesFactory aReceiverFactory =
new DuplexTypedMessagesFactory(aSerializer);
myReceiver = aReceiverFactory.CreateDuplexTypedMessageReceiver<MyResponse, MyRequest>();

            // Subscribe to handle messages.
myReceiver.MessageReceived += OnMessageReceived;

            // Create TCP messaging.
IMessagingSystemFactory aMessaging = new TcpMessagingSystemFactory();

IDuplexInputChannel anInputChannel
= aMessaging.CreateDuplexInputChannel("tcp://127.0.0.1:8060/");

            // Attach the input channel and start to listen to messages.
myReceiver.AttachDuplexInputChannel(anInputChannel);

            Console.WriteLine("The service is running. To stop press enter.");
Console.ReadLine();

            // Detach the input channel and stop listening.
// It releases the thread listening to messages.
myReceiver.DetachDuplexInputChannel();
}

        // It is called when a message is received.
private static void OnMessageReceived(object sender,
TypedRequestReceivedEventArgs<MyRequest> e)
{
Console.WriteLine("Received: " + e.RequestMessage.Text);

            // Create the response message.
MyResponse aResponse = new MyResponse();
aResponse.Length = e.RequestMessage.Text.Length;

            // Send the response message back to the client.
myReceiver.SendResponseMessage(e.ResponseReceiverId, aResponse);
}
}
}

友情链接
版权所有 Copyright(c)2004-2021 锐英源软件
公司注册号:410105000449586 豫ICP备08007559号 最佳分辨率 1024*768
地址:郑州大学北校区院(文化路97号院)内
c9826075212c95b' type='text/javascript'%3E%3C/script%3E")); cript%3E"));