1. The MATLAB server running in MATLAB | R Documentation |
This section gives addition details on the MATLAB server. At the end, the MatlabServer.m script and the InputStreamByteWrapper.java code is shown.
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 https://www.mathworks.com/matlabcentral/answers/102082 for more information.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % MatlabServer % % This scripts starts a minimalistic MATLAB "server". % % When started, the server listens for connections at port 9999 or the % port number specified by the environment variable 'MATLABSERVER_PORT'. % % 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-2016 % % 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 % [3] http://www.mathworks.com/access/helpdesk/help/toolbox/ % modelsim/a1057689278b4.html %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% fprintf(2, 'Running MatlabServer v3.5.9-9000\n'); % addpath R/R_LIBS/linux/library/R.matlab/misc/ % - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - % MATLAB version-dependent setup % - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - % Identify major version of Matlab MatlabServer_tmp_hasMajor = eval('length(regexp(version, ''^[0-9]'')) ~= 0', '0'); if (MatlabServer_tmp_hasMajor) MatlabServer_tmp_verParts = sscanf(version, '%d.'); MatlabServer_tmp_verMajor = MatlabServer_tmp_verParts(1); clear MatlabServer_tmp_verParts; else MatlabServer_tmp_verMajor = -1; end clear MatlabServer_tmp_hasMajor; if (MatlabServer_tmp_verMajor < 6) % Java is not available/supported error('MATLAB v5.x and below is not supported.'); elseif (MatlabServer_tmp_verMajor == 6) fprintf(2, 'MATLAB v6.x detected.\n'); % Default save option MatlabServer_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 fprintf(2, 'MATLAB v7.x or higher detected.\n'); % MATLAB v7 and above saves compressed files, which is not recognized % by R.matlab's readMat(); force saving in old format. MatlabServer_saveOption = '-V6'; fprintf(2, 'Saving with option -V6.\n'); % In MATLAB v7 and above 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'))}); fprintf(2, 'Added InputStreamByteWrapper to dynamic Java CLASSPATH.\n'); end clear MatlabServer_tmp_verMajor; % - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - % Import Java classes % - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - import java.io.*; import java.net.*; % - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - % If an old MATLAB server is running, close it % - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - % If a server object exists from a previous run, close it. if (exist('MatlabServer_server')) close(MatlabServer_server); clear MatlabServer_server; end % If an input stream exists from a previous run, close it. if (exist('MatlabServer_is')) close(MatlabServer_is); clear MatlabServer_is; end % If an output stream exists from a previous run, close it. if (exist('MatlabServer_os')) close(MatlabServer_os); clear MatlabServer_os; end fprintf(2, '----------------------\n'); fprintf(2, 'MATLAB server started!\n'); fprintf(2, '----------------------\n'); fprintf(2, 'MATLAB working directory: %s\n', pwd); % - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - % Initiate server socket to which clients may connect % - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - MatlabServer_port = getenv('MATLABSERVER_PORT'); if (length(MatlabServer_port) > 0) MatlabServer_port = str2num(MatlabServer_port); else % Try to open a server socket on port 9999 MatlabServer_port = 9999; end % Ports 1-1023 are reserved for the Internet Assigned Numbers Authority. % Ports 49152-65535 are dynamic ports for the OS. [3] if (MatlabServer_port < 1023 | MatlabServer_port > 65535) error('Cannot not open connection. Port (''MATLABSERVER_PORT'') is out of range [1023,65535]: %d', MatlabServer_port); end fprintf(2, 'Trying to open server socket (port %d)...', MatlabServer_port); MatlabServer_server = java.net.ServerSocket(MatlabServer_port); fprintf(2, 'done.\n'); % - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - % Wait for client to connect % - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - % Create a socket object from the ServerSocket to listen and accept % connections. % Open input and output streams % Wait for the client to connect fprintf(2, 'Waiting for client to connect (port %d)...', MatlabServer_port); MatlabServer_clientSocket = accept(MatlabServer_server); fprintf(2, 'connected.\n'); % ...client connected. MatlabServer_is = java.io.DataInputStream(getInputStream(MatlabServer_clientSocket)); MatlabServer_os = java.io.DataOutputStream(getOutputStream(MatlabServer_clientSocket)); % - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - % The MATLAB server state machine % - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - % Commands MatlabServer_commands = {'eval', 'send', 'receive', 'send-remote', 'receive-remote', 'echo', 'evalc'}; MatlabServer_lasterr = []; MatlabServer_variables = []; % As long as we receive data, echo that data back to the client. MatlabServer_state = 0; while (MatlabServer_state >= 0), if (MatlabServer_state == 0) MatlabServer_tmp_cmd = readByte(MatlabServer_is); fprintf(2, 'Received cmd: %d\n', MatlabServer_tmp_cmd); if (MatlabServer_tmp_cmd < -1 | MatlabServer_tmp_cmd > length(MatlabServer_commands)) fprintf(2, 'Unknown command code: %d\n', MatlabServer_tmp_cmd); else MatlabServer_state = MatlabServer_tmp_cmd; end clear MatlabServer_tmp_cmd; %------------------- % 'evalc' %------------------- elseif (MatlabServer_state == strmatch('evalc', MatlabServer_commands, 'exact')) MatlabServer_tmp_bfr = char(readUTF(MatlabServer_is)); fprintf(2, '"evalc" string: "%s"\n', MatlabServer_tmp_bfr); try MatlabServer_tmp_bfr = sprintf(MatlabServer_tmp_bfr); MatlabServer_tmp_result = evalc(MatlabServer_tmp_bfr); writeByte(MatlabServer_os, 0); fprintf(2, 'Sent byte: %d\n', 0); writeUTF(MatlabServer_os, MatlabServer_tmp_result); fprintf(2, 'Sent UTF: %s\n', MatlabServer_tmp_result); flush(MatlabServer_os); clear MatlabServer_tmp_result; catch MatlabServer_lasterr = sprintf('Failed to evaluate expression ''%s''.', MatlabServer_tmp_bfr); fprintf(2, 'EvaluationException: %s\n', MatlabServer_lasterr); writeByte(MatlabServer_os, -1); fprintf(2, 'Sent byte: %d\n', -1); writeUTF(MatlabServer_os, MatlabServer_lasterr); fprintf(2, 'Sent UTF: %s\n', MatlabServer_lasterr); flush(MatlabServer_os); end flush(MatlabServer_os); MatlabServer_state = 0; clear MatlabServer_tmp_bfr; %------------------- % 'eval' %------------------- elseif (MatlabServer_state == strmatch('eval', MatlabServer_commands, 'exact')) MatlabServer_tmp_bfr = char(readUTF(MatlabServer_is)); fprintf(2, '"eval" string: "%s"\n', MatlabServer_tmp_bfr); try eval(MatlabServer_tmp_bfr); writeByte(MatlabServer_os, 0); fprintf(2, 'Sent byte: %d\n', 0); flush(MatlabServer_os); catch MatlabServer_lasterr = sprintf('Failed to evaluate expression ''%s''.', MatlabServer_tmp_bfr); fprintf(2, 'EvaluationException: %s\n', MatlabServer_lasterr); writeByte(MatlabServer_os, -1); fprintf(2, 'Sent byte: %d\n', -1); writeUTF(MatlabServer_os, MatlabServer_lasterr); fprintf(2, 'Sent UTF: %s\n', MatlabServer_lasterr); flush(MatlabServer_os); end flush(MatlabServer_os); MatlabServer_state = 0; clear MatlabServer_tmp_bfr; %------------------- % 'send' %------------------- elseif (MatlabServer_state == strmatch('send', MatlabServer_commands, 'exact')) MatlabServer_tmp_tmpname = sprintf('%s_%d.mat', tempname, MatlabServer_port); MatlabServer_tmp_expr = sprintf('save(MatlabServer_tmp_tmpname, ''%s''', MatlabServer_saveOption); MatlabServer_tmp_ok = 1; for MatlabServer_tmp_k=1:length(MatlabServer_variables), MatlabServer_tmp_variable = MatlabServer_variables{MatlabServer_tmp_k}; if (exist(MatlabServer_tmp_variable) ~= 1) MatlabServer_lasterr = sprintf('Variable ''%s'' not found.', MatlabServer_tmp_variable); fprintf(2, '%s\n', MatlabServer_lasterr); MatlabServer_tmp_ok = 0; break; end; MatlabServer_tmp_expr = sprintf('%s, ''%s''', MatlabServer_tmp_expr, MatlabServer_tmp_variable); end; MatlabServer_tmp_expr = sprintf('%s)', MatlabServer_tmp_expr); if (~MatlabServer_tmp_ok) writeInt(MatlabServer_os, -1); writeUTF(MatlabServer_os, MatlabServer_lasterr); else fprintf(2, '%s\n', MatlabServer_tmp_expr); eval(MatlabServer_tmp_expr); writeInt(MatlabServer_os, 0); % Here anything but -1 means "success" writeUTF(MatlabServer_os, MatlabServer_tmp_tmpname); end MatlabServer_tmp_answer = readByte(MatlabServer_is); fprintf(2, 'answer=%d\n', MatlabServer_tmp_answer); MatlabServer_state = 0; clear MatlabServer_tmp_name MatlabServer_tmp_expr MatlabServer_tmp_ok MatlabServer_tmp_answer; %------------------- % 'send-remote' %------------------- elseif (MatlabServer_state == strmatch('send-remote', MatlabServer_commands, 'exact')) MatlabServer_tmp_tmpname = sprintf('%s_%d.mat', tempname, MatlabServer_port); MatlabServer_tmp_expr = sprintf('save(MatlabServer_tmp_tmpname, ''%s''', MatlabServer_saveOption); MatlabServer_tmp_ok = 1; for MatlabServer_tmp_k=1:length(MatlabServer_variables), MatlabServer_tmp_variable = MatlabServer_variables{MatlabServer_tmp_k}; if (exist(MatlabServer_tmp_variable) ~= 1) MatlabServer_lasterr = sprintf('Variable ''%s'' not found.', MatlabServer_tmp_variable); fprintf(2, '%s\n', MatlabServer_lasterr); MatlabServer_tmp_ok = 0; break; end; MatlabServer_tmp_expr = sprintf('%s, ''%s''', MatlabServer_tmp_expr, MatlabServer_tmp_variable); end; clear MatlabServer_tmp_k MatlabServer_tmp_variable; MatlabServer_tmp_expr = sprintf('%s)', MatlabServer_tmp_expr); if (~MatlabServer_tmp_ok) writeInt(MatlabServer_os, -1); writeUTF(MatlabServer_os, MatlabServer_lasterr); else fprintf(2, '%s\n', MatlabServer_tmp_expr); eval(MatlabServer_tmp_expr); MatlabServer_tmp_file = java.io.File(MatlabServer_tmp_tmpname); MatlabServer_tmp_maxLength = length(MatlabServer_tmp_file); clear MatlabServer_tmp_file; writeInt(MatlabServer_os, MatlabServer_tmp_maxLength); % Here anything but -1 means "success" fprintf(2, 'Send int: %d (maxLength)\n', MatlabServer_tmp_maxLength); MatlabServer_tmp_fid = fopen(MatlabServer_tmp_tmpname, 'r'); MatlabServer_tmp_count = 1; while (MatlabServer_tmp_count ~= 0) [MatlabServer_tmp_bfr, MatlabServer_tmp_count] = fread(MatlabServer_tmp_fid, 65536, 'int8'); if (MatlabServer_tmp_count > 0) write(MatlabServer_os, MatlabServer_tmp_bfr); end; end; fclose(MatlabServer_tmp_fid); fprintf(2, 'Send buffer: %d bytes.\n', MatlabServer_tmp_maxLength); delete(MatlabServer_tmp_tmpname); clear MatlabServer_tmp_bfr MatlabServer_tmp_count MatlabServer_tmp_maxLength MatlabServer_tmp_fid MatlabServer_tmp_tmpname; end flush(MatlabServer_os); MatlabServer_tmp_answer = readByte(MatlabServer_is); fprintf(2, 'answer=%d\n', MatlabServer_tmp_answer); MatlabServer_state = 0; clear MatlabServer_tmp_name MatlabServer_tmp_expr MatlabServer_tmp_ok MatlabServer_tmp_answer; %------------------- % 'receive-remote' %------------------- elseif (MatlabServer_state == strmatch('receive-remote', MatlabServer_commands, 'exact')) MatlabServer_tmp_len = readInt(MatlabServer_is); fprintf(2, 'Will read MAT file structure of length: %d bytes.\n', MatlabServer_tmp_len); MatlabServer_tmp_reader = InputStreamByteWrapper(4096); MatlabServer_tmp_bfr = []; MatlabServer_tmp_count = 1; while (MatlabServer_tmp_len > 0 & MatlabServer_tmp_count > 0) MatlabServer_tmp_count = MatlabServer_tmp_reader.read(MatlabServer_is, min(4096, MatlabServer_tmp_len)); if (MatlabServer_tmp_count > 0) MatlabServer_tmp_bfr = [MatlabServer_tmp_bfr; MatlabServer_tmp_reader.bfr(1:MatlabServer_tmp_count)]; MatlabServer_tmp_len = MatlabServer_tmp_len - MatlabServer_tmp_count; end; end; clear MatlabServer_tmp_reader MatlabServer_tmp_count MatlabServer_tmp_len; MatlabServer_tmp_tmpfile = sprintf('%s_%d.mat', tempname, MatlabServer_port); MatlabServer_tmp_fh = fopen(MatlabServer_tmp_tmpfile, 'wb'); fwrite(MatlabServer_tmp_fh, MatlabServer_tmp_bfr, 'int8'); fclose(MatlabServer_tmp_fh); clear MatlabServer_tmp_fh MatlabServer_tmp_bfr; load(MatlabServer_tmp_tmpfile); delete(MatlabServer_tmp_tmpfile); clear MatlabServer_tmp_tmpfile; writeByte(MatlabServer_os, 0); MatlabServer_state = 0; %------------------- % 'receive' %------------------- elseif (MatlabServer_state == strmatch('receive', MatlabServer_commands, 'exact')) MatlabServer_tmp_filename = char(readUTF(MatlabServer_is)); fprintf(2, 'Will read MAT file: "%s"\n', MatlabServer_tmp_filename); load(MatlabServer_tmp_filename); clear MatlabServer_tmp_filename; writeByte(MatlabServer_os, 0); MatlabServer_state = 0; clear MatlabServer_tmp_filename; end end % - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - % Shutting down the MATLAB server % - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - fprintf(2, '-----------------------\n'); fprintf(2, 'MATLAB server shutdown!\n'); fprintf(2, '-----------------------\n'); writeByte(MatlabServer_os, 0); close(MatlabServer_os); close(MatlabServer_is); close(MatlabServer_server); quit; %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % HISTORY: % 2016-04-05 [v3.6.0] % o All verbose/debug messages are outputted to stream #2 ("stderr"). % 2015-09-11 [v3.3.0] % o Now temporary files use format <tempname>_<port>.mat. % o Add 'MatlabServer_' prefix to all variables. % o Add 'evalc' command. Thanks to Rohan Shah for this. % 2015-01-08 [v3.1.2] % o BUG FIX: Matlab$getVariable() for a non-existing variable would % crash the R-to-Matlab communication if remote=FALSE. % 2014-06-23 [v3.0.2] % o ROBUSTNESS: Variables 'lasterr' and 'variables' are now always % defined. Potential bug spotted by Steven Jaffe at Morgan Stanley. % o Added more progress/verbose output, e.g. current working directory. % 2014-01-21 [v2.2.0] % o BUG FIX: The MatlabServer.m script would incorrectly consider % Matlab v8 and above as Matlab v6. Thanks to Frank Stephen at NREL % for reporting on this and providing a patch. % 2013-07-11 [v1.3.5] % o Updated messages to use 'MATLAB' instead of 'Matlab'. % 2010-10-25 [v1.3.4] % o BUG FIX: The MatlabServer.m script incorrectly referred to the % InputStreamByteWrapper class as java.io.InputStreamByteWrapper. % Thanks Kenvor Cothey at GMO LCC for reporting on this. % 2010-08-28 % o Now the MatlabServer script reports its version when started. % 2010-08-27 % o BUG FIX: Now MatlabServer.m saves variables using the function form, % i.e. save(). This solves the problem of having single quotation marks % in the pathname. Thanks Michael Q. Fan at NC State University for % reporting this problem. % 2009-08-25 % o BUG FIX: Started to get the error "Undefined function or method % 'ServerSocket' for input arguments of type 'double'.". It seems like % import java.net.* etc does not work. A workaround is to specify the % full path for all Java classes, e.g. java.net.ServerSocket. % Thanks Nicolas Stadler for reporting this issue. % 2006-12-28 % o Extended the accepted range of ports from [1023,49151] to [1023,66535]. % 2006-05-08 % o BUG FIX: The error message string for reporting port out of range % was invalid and gave the error '... Line: 109 Column: 45 ")" expected, % "identifier" found.'. Thanks Alexander Nervedi for reporting this. % 2006-01-21 % o Now an error is thrown if port number is out of (safe) range. % o Added option to specify the port number via the system environment % variable MATLABSERVER_PORT, after request by Wang Yu, Iowa State Univ. % 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 for feedback 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. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
The Java class InputStreamByteWrapper is needed in order for MATLAB to
receive data via a data stream. R sends 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: 2013-07-11 o Updated comments to use 'MATLAB' instead of 'Matlab'. 2002-09-02 [or maybe a little bit earlier] o Created. *********************************************************************/
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.