Learn R Programming

R.matlab (version 1.1.0)

. About the Matlab server: . About the Matlab server

Description

This section gives addition details on the Matlab server. At the end, the MatlabServer.m script and the InputStreamByteWrapper.java code is shown.

Arguments

Starting the Matlab server on Windows

Note that you "cannot prevent Matlab from creating a window when starting on Windows systems, but you can force the window to be hidden, by using " the option -minimize. See http://www.mathworks.com/support/solutions/data/1-16B8X.html for more information.

MatlabServer.m script

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % MatlabServer % % This scripts starts a minimalistic Matlab "server". % % Troubleshooting: If not working out of the box, add this will to the % Matlab path. Make sure InputStreamByteWrapper.class is in the same % directory as this file! % % Requirements: % This requires Matlab with Java support, i.e. Matlab v6 or higher. % % Author: Henrik Bengtsson, 2002-2005 % % References: % [1] http://www.mathworks.com/access/helpdesk/help/techdoc/ % matlab_external/ch_jav34.shtml#49439 % [2] http://staff.science.uva.nl/~horus/dox/horus2.0/user/ % html/n_installUnix.html %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % addpath R/R_LIBS/linux/library/R.matlab/misc/ % Detect major Matlab version isVersion7 = eval('length(regexp(version, ''^7'')) ~= 0', '0'); if (~isVersion7) disp('Matlab v6.x detected.'); % Default save option saveOption = ''; % In Matlab v6 only the static Java CLASSPATH is supported. It is % specified by a 'classpath.txt' file. The default one can be found % by which('classpath.txt'). If a 'classpath.txt' exists in the % current(!) directory (that Matlab is started from), it *replaces* % the global one. Thus, it is not possible to add additional paths; % the global ones has to be copied to the local 'classpath.txt' file. % % To do the above automatically from R, does not seem to be an option. else disp('Matlab v7.x or higher detected.'); % Matlab v7 saves compressed files, which is not recognized by % R.matlab's readMat(); force saving in old format. saveOption = '-V6'; disp('Saving with option -V6.'); % In Matlab v7 both static and dynamic Java CLASSPATH:s exist. % Using dynamic ones, it is possible to add the file % InputStreamByteWrapper.class to CLASSPATH, given it is % in the same directory as this script. javaaddpath({fileparts(which('MatlabServer'))}); disp('Added InputStreamByteWrapper to dynamic Java CLASSPATH.'); end % Importing Java classes import java.io.*; import java.net.*; % If a server object exists from a previous run, close it. if (exist('server')) close(server); clear server; end % If an input stream exists from a previous run, close it. if (exist('is')) close(is); clear is; end % If an output stream exists from a previous run, close it. if (exist('os')) close(os); clear os; end fprintf(1, '----------------------\n'); fprintf(1, 'Matlab server started!\n'); fprintf(1, '----------------------\n'); % Try to open a server socket on port 9999 % Note that we can't choose a port less than 1023 if we are not % privileged users (root) port = 9999; server = ServerSocket(port); fprintf(1, 'Server socket created.\n'); % Create a socket object from the ServerSocket to listen and accept % connections. % Open input and output streams % Wait for the client to connect clientSocket = accept(server); fprintf(1, 'Connected to client.\n'); % ...client connected. is = DataInputStream(getInputStream(clientSocket)); %is = BufferedReader(InputStreamReader(is0)); os = DataOutputStream(getOutputStream(clientSocket)); % Commands commands = {'eval', 'send', 'receive', 'send-remote', 'receive-remote', 'echo'}; % As long as we receive data, echo that data back to the client. state = 0; while (state >= 0), if (state == 0) cmd = readByte(is); fprintf(1, 'Received cmd: %d\n', cmd); if (cmd < -1 | cmd > length(commands)) fprintf(1, 'Unknown command code: %d\n', cmd); else state = cmd; end %------------------- % 'eval' %------------------- elseif (state == strmatch('eval', commands, 'exact')) bfr = char(readUTF(is)); fprintf(1, '"eval" string: "%s"\n', bfr); try eval(bfr);, writeByte(os, 0); fprintf(1, 'Sent byte: %d\n', 0); flush(os); catch, fprintf(1, 'EvaluationException: %s\n', lasterr); writeByte(os, -1); fprintf(1, 'Sent byte: %d\n', -1); writeUTF(os, lasterr); fprintf(1, 'Sent UTF: %s\n', lasterr); flush(os); end flush(os); state = 0; %------------------- % 'send' %------------------- elseif (state == strmatch('send', commands, 'exact')) tmpname = sprintf('%s.mat', tempname); expr = sprintf('save %s %s', tmpname, saveOption); ok = 1; for k=1:length(variables), variable = variables{k}; if (exist(variable) ~= 1) lasterr = sprintf('Variable ''%s'' not found.', variable); ok = 0; break; end; expr = sprintf('%s %s', expr, variable); end; if (~ok) writeInt(os, -1); writeUTF(os, lasterr); else disp(expr); eval(expr); writeUTF(os, tmpname); end answer = readByte(is); fprintf('answer=%d\n', answer); state = 0; %------------------- % 'send-remote' %------------------- elseif (state == strmatch('send-remote', commands, 'exact')) tmpname = sprintf('%s.mat', tempname); expr = sprintf('save %s %s', tmpname, saveOption); ok = 1; for k=1:length(variables), variable = variables{k}; if (exist(variable) ~= 1) lasterr = sprintf('Variable ''%s'' not found.', variable); ok = 0; break; end; expr = sprintf('%s %s', expr, variable); end; if (~ok) writeInt(os, -1); writeUTF(os, lasterr); else disp(expr); eval(expr); file = File(tmpname); maxLength = length(file); clear file; writeInt(os, maxLength); fprintf(1, 'Send int: %d (maxLength)\n', maxLength); fid = fopen(tmpname, 'r'); count = 1; while (count ~= 0) [bfr, count] = fread(fid, 65536, 'int8'); if (count > 0) write(os, bfr); % fprintf(1, 'Wrote %d byte(s).\n', length(bfr)); end; end; fclose(fid); % fprintf(1, 'Wrote!\n'); fprintf(1, 'Send buffer: %d bytes.\n', maxLength); delete(tmpname); clear bfr, count, maxLength, fid, tmpname; end flush(os); answer = readByte(is); fprintf('answer=%d\n', answer); state = 0; %------------------- % 'receive-remote' %------------------- elseif (state == strmatch('receive-remote', commands, 'exact')) len = readInt(is); fprintf(1, 'Will read MAT file structure of length: %d bytes.\n', len); reader = InputStreamByteWrapper(4096); bfr = []; count = 1; while (len > 0 & count > 0) count = reader.read(is, min(4096, len)); if (count > 0) bfr = [bfr; reader.bfr(1:count)]; len = len - count; end; end; clear reader count len; tmpfile = sprintf('%s.mat', tempname); % tmpfile = 'tmp2.mat'; % disp(bfr'); % disp(tmpfile); fh = fopen(tmpfile, 'wb'); fwrite(fh, bfr, 'int8'); fclose(fh); clear fh, bfr; load(tmpfile); delete(tmpfile); clear tmpfile; writeByte(os, 0); state = 0; %------------------- % 'receive' %------------------- elseif (state == strmatch('receive', commands, 'exact')) filename = char(readUTF(is)); fprintf(1, 'Will read MAT file: "%s"\n', filename); load(filename); clear filename; writeByte(os, 0); state = 0; end end fprintf(1, '-----------------------\n'); fprintf(1, 'Matlab server shutdown!\n'); fprintf(1, '-----------------------\n'); writeByte(os, 0); close(os); close(is); close(server); %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % HISTORY: % 2005-03-08 % o BUG FIX: substring() is not recognized by Matlab v7. Using regexp() % which works in Matlab 6.5 and 7. Workaround eval('try', 'catch'). % Thanks Patrick Drechsler, University of Wuerzburg for the bug report. % 2005-02-24 % o Now the dynamic Java classpath is set for Matlab v7 or higher. This % will simplify life for Matlab v7 users. % 2005-02-22 % o Added javaaddpath() to include InputStreamByteWrapper.class. % Thanks Yichun Wei forfeedback and great suggestions. % 2005-02-11 % o If Matlab v7 or higher is detected, all MAT structures are saved with % option '-V6' so readMat() in R.matlab can read them. % 2002-09-02 [or maybe a little bit earlier] % o Created. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

InputStreamByteWrapper.(class|java) script

The Java class InputStreamByteWrapper is needed in order for Matlab to receive data via a data stream. Rsends data via a data stream if, and only if, the connection was setup for "remote" communication, that is, with argument remote=TRUE). import java.io.*; /********************************************************************* % Compile from within Matlab with: % !javac InputStreamByteWrapper.java % Matlab example that reads a file using Java code and writes it % back to a temporary file using Matlab code. Finally the contents % of the new file is displayed. reader = InputStreamByteWrapper; % Default buffer size is 4096 bytes. in = java.io.FileInputStream('InputStreamByteWrapper.java'); bfr = []; len = 1; while (len > 0) len = reader.read(in, 16); % Read 16 bytes at the time (offset=0). if (len > 0) bfr = [bfr; reader.bfr(1:len)]; % Add bytes to my Matlab buffer. end end close(in); clear in, reader; disp(bfr'); tmpfile = tempname; fh = fopen(tmpfile, 'wb'); fwrite(fh, bfr, 'char'); fclose(fh); type(tmpfile); *********************************************************************/ public class InputStreamByteWrapper { public static byte[] bfr = null; public InputStreamByteWrapper(int capasity) { bfr = new byte[capasity]; } public InputStreamByteWrapper() { this(4096); } public int read(InputStream in, int offset, int length) throws IOException { return in.read(bfr, offset, length); } public int read(InputStream in, int length) throws IOException { return read(in, 0, length); } public int read(InputStream in) throws IOException { return in.read(bfr); } } /********************************************************************* HISTORY: 2002-09-02 [or maybe a little bit earlier] o Created. *********************************************************************/