我有一个书面的C++服务器应用程序,我希望能够控制从Matlab。到目前为止,我已经在套接字通信中使用了mex函数,但是我想放弃mex函数,直接在m文件中使用内联Java。这将是一个更精简的解决方案。
我的基于C++的独立应用程序需要一条具有以下数据的消息,如下所示。。。
协议的这一部分是固定的,不能更改:
协议的这一部分是我设计的,可以修改:
正如您所看到的,我目前正在将所有内容压缩到一个uint8数组中(一个巨大的传说)。这是因为java“写”函数需要一个字节数组,而Matlab uint8数组是我在Mathworks站点将数据传递给Java方法上使用下表时发现的兼容数据类型。
我不是Java程序员,但今天下午我成功地获得了一些非常简单的通信代码并运行。有人能帮我把这做得更好吗?
import java.net.Socket
import java.io.*
mySocket = Socket('localhost', 12345);
output_stream = mySocket.getOutputStream;
d_output_stream = DataOutputStream(output_stream);
data = zeros(12,1,'uint8');
%Magic key: use this combination of uint8s to make
% a uint32 value of = 445566 -> massive code-smell
data(1) = 126;
data(2) = 204;
data(3) = 6;
%Size of message block:
%total number of bytes in following message including header
%This is another uint32 i.e. (data(5:8))
data(5) = 4;
%header B: a group of 4 uint8s
data(9) = 1;
data(10) = 2;
data(11) = 3;
data(12) = 4;
%Main block of floats
%????
d_output_stream.write(data,0,numel(data));
pause(0.2);
mySocket.close;我已经尝试过发送一个java对象,该对象由我想发送的数据的不同部分组成,但我不确定它们是如何在内存中排序的。在C/C++中,很容易在一个连续的内存块中附加不同的数据类型,然后发送它。在Java中,有什么简单的方法可以让我做到这一点吗?我最终也想做双向沟通,但现在可以等了.感谢您的阅读。
发布于 2012-01-25 23:42:01
这里至少有两个不同的问题。一个是如何构造这样一个协议的Matlab代码。另一种方法是如何在您的有线协议中表示可能复杂的数据。
至于组织Matlab代码,您可以使用一个类以更结构化的方式组织消息,并使用typecast将数字转换为字节。也许是这样的。这假设您的客户机和服务器具有相同的原生类型表示,并忽略网络字节排序(htonl/ntohl)。
classdef learnvst_message
%//LEARNVST_MESSAGE Message for learnvst's example problem
%
% Examples:
% msg = learnvst_message;
% msg.payload = { 'Hello world', 1:100 }
% msg.payloadType = uint8([ 5 12 0 0 ]); % guessing on this
properties
magicNumber = uint32(445566);
payloadType = zeros(4, 1, 'uint8'); %// header B
payload = {};
end
methods
function out = convertPayload(obj)
%//CONVERTPAYLOAD Converts payload to a single array of bytes
byteChunks = cellfun(@convertPayloadElement, obj.payload, 'UniformOutput',false);
out = cat(2, byteChunks{:});
end
function out = marshall(obj)
payloadBytes = convertPayload(obj);
messageSize = uint32(4 + numel(payloadBytes)); %// ex first 8 bytes
out.headerBytes = [
typecast(obj.magicNumber, 'uint8') ...
obj.payloadType ...
typecast(messageSize, 'uint8')];
out.payloadBytes = payloadBytes;
end
function sendTo(obj, host, port)
m = marshall(obj);
mySocket = Socket(host, port);
d_output = mySocket.getOutputStream();
d_output.write(m.headerBytes, 0, numel(m.headerBytes));
d_output.write(m.messageBytes, 0, numel(m.messageBytes));
mySocket.close();
end
end
end
function out = convertPayloadElement(x)
if isnumeric(x)
out = typecast(x, 'uint8');
elseif ischar(x)
% Assumes receiver likes 16-bit Unicode chars
out = typecast(uint16(x), 'uint8');
else
% ... fill in other types here ...
% or define a payload_element class that marshalls itself and call
% it polymorphically
error('Unsupported payload element type: %s', class(x));
end
end我认为,它的可读性更强,代码气味也更少一些。作为调用者,您可以以更结构化的形式处理数据,并在类的编组方法中封装到有线协议字节的转换。"convertPayload“就是”将一个由许多不同数据类型组成的通用内存块拼接在一起“。在Matlab中,uint8数组是将不同数据类型的表示附加到内存块中的一种方法。它基本上是unsigned char []的包装器,具有自动重新分配的功能。typecast(...,'uint8')相当于在C/C++中对char *进行重新解释。看看他们两个人的帮助。
但这带来了更多的问题。服务器如何知道每个有效负载的组件有多长,如果是多维的,它们的形状是什么,以及它们各自的类型是什么?或者,如果它们是复杂的数据类型,它们可以嵌套吗?您可能需要在每个有效负载元素中嵌入小的头。上面的代码假定4字节的有效载荷类型头完全描述了有效载荷内容。
听起来,您要寻找的可能是一种基于异构数组的数据的自描述格式。有一些现有的格式,包括NetCDF、HDF5和Matlab自己的MAT文件。Matlab已经内置了对它们的支持,或者您可以为它们引入第三方Java库。
就速度而言,每次通过Matlab/Java边界传递数据时,您都必须付费。大型原始数组的转换成本相对较低,因此在将大部分消息传递给Java之前,您可能希望将大部分消息打包到一个字节数组中,而不是进行大量单独的write()调用。这将取决于您的数据有多大和多复杂。有关一些Matlab操作(包括Java调用)的成本,请参见MATLAB是慢的还是我做错了什么?。(完全披露:这是一个自动插头。)
https://stackoverflow.com/questions/9007673
复制相似问题