Code covered by the BSD License  

Highlights from
TCP/IP Communications in Matlab

4.94118

4.9 | 17 ratings Rate this file 122 Downloads (last 30 days) File Size: 12.8 KB File ID: #24524

TCP/IP Communications in Matlab

by

 

22 Jun 2009 (Updated )

Sends/receives TCP packets using Matlab's Java interface. Now handles matrices and cell arrays, etc.

| Watch this File

File Information
Description

Transmission Control Protocol (TCP/IP) communications are used to send data from one computer to another over a network or from one application to another within a single computer.

The jtcp.m program uses Matlab's ability to call Java code to enable it to send and/or receive TCP packets. One Matlab session can communicate with another Matlab session (on the same machine or over the network) or it can communicate with a completely different program (again, on the same machine or over the network).

This latest version of jtcp.m uses Java's serialization functionality to write and read strings, matrices, cell arrays and primitives (that is, just about any Matlab variable type other than structures).

Serialization will cause errors if jtcp.m is talking to a program or piece of hardware that does not itself implement serialization. In this case, set the 'serialize' argument to false when requesting or accepting a connection. This will limit read and write operations to variables of type "int8", which most socket applications will be able to handle.

Update, 2013-04-19 (thanks to Qi Wang for pointing this out): java.lang.OutOfMemoryError occurs after a volume of data approximating the Java heap space size has been sent. This appears to be a bug in Java itself (see http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6525563). Workaround is to call
  jTcpObj.outputStream.reset;
every once in a while from whatever program you are calling the jtcp "WRITE" command from.

Acknowledgements

Tcp/Ip Socket Communications In Matlab and Tcp/Ip Socket Communications In Matlab Using Java Classes inspired this file.

Required Products MATLAB
MATLAB release MATLAB 7.8 (R2009a)
Tags for This File   Please login to tag files.
Please login to add a comment or rating.
Comments and Ratings (58)
11 Apr 2014 Kevin Bartlett

@Carsten--The OptionalDataException appears to be associated exclusively with serializable objects. I don't know why this is happening, but you could presumably get around this problem by setting 'serialize' to false and converting the payload data to int8 (see last example in jtcp.m header). Would this be an option for you?

10 Apr 2014 Carsten

Hi Kevin,
i have a problem using the jTPC read function.

I get an 'java.io.OptionalDataException' if i try to use the read function in a timer function that works in a GUI.

If the timers period is >0.3 seconds it works without problems but i want a faster update.
The code that should be updated under 0.3 seconds is:

try
while true
mssgs = jtcp('read',jTcpObj);
mssg = mssgs(1); %mssgs is a cell array

if(~isempty(mssgs))
set(handles.timestamp_txt,'string',char(mssg));
end
end
catch me
disp(me);
end

Hope you can help me, thank you

24 May 2013 Kevin Bartlett

@Geoffry Akien--I'm not able to duplicate your 2nd error (the one with jtcp_version01), so I'm not sure what to say about that. Your 1st error is really mysterious: a failed jtcp_request_connection() on my machine results in a "connect timed out" error, but the message you get says "Read timed out". I don't know the inner workings of Java well enough to understand why it should be attempting a read operation when you are requesting a connection, so I'm afraid I'm not going to be able to offer you any help here.

23 May 2013 Geoffrey Akien

I want to use port 502 (I can't change this), but your code formally does not allow the user of ports <1025. I have a device which works just fine using tcpip in the instrument toolbox, but I was hoping to get rid of the dependency by using your code.

Naively changing this limit and using 2012bx64 on W7E I get the following:

>> j = jtcp('REQUEST', '10.10.10.4', 502)
Error using jtcp>jtcp_request_connection (line 293)
Java exception occurred:
java.net.SocketTimeoutException: Read timed out

at java.net.SocketInputStream.socketRead0(Native Method)

at java.net.SocketInputStream.read(Unknown Source)

at java.io.ObjectInputStream$PeekInputStream.read(Unknown Source)

at java.io.ObjectInputStream$PeekInputStream.readFully(Unknown
Source)

at
java.io.ObjectInputStream$BlockDataInputStream.readShort(Unknown
Source)

at java.io.ObjectInputStream.readStreamHeader(Unknown Source)

at java.io.ObjectInputStream.<init>(Unknown Source)

Error in jtcp (line 230)
jTcpObj = jtcp_request_connection(host,port,timeout,serialize);

...but using the same approach with jtcp_version01 seems to work initially:

>> j = jtcp_version01('REQUEST', '10.10.10.4', 502)

j =

socket: [1x1 java.net.Socket]
remoteHost: '10.10.10.4'
port: 502
inputStream: [1x1 java.net.SocketInputStream]
dataInputStream: [1x1 java.io.DataInputStream]
outputStream: [1x1 java.net.SocketOutputStream]
dataOutputStream: [0 java.io.DataOutputStream]

...but then sending something gives this error:

jtcp_version01('WRITE', j, int8(c))
Error using jtcp_version01>jtcp_write (line 384)
Java exception occurred:
java.net.SocketException: Software caused connection abort: socket
write error

at java.net.SocketOutputStream.socketWrite0(Native Method)

at java.net.SocketOutputStream.socketWrite(Unknown Source)

at java.net.SocketOutputStream.write(Unknown Source)

at java.io.DataOutputStream.write(Unknown Source)

Error in jtcp_version01 (line 258)
jtcp_write(jTcpObj,mssg);

...although closing the connection seems to work without complaint.

21 May 2013 Ian

Zack, Psychtoolbox already contains a TCP/IP UDP interface, which i use to control neurophysiology amplifiers (has a client / server mode and serialisation of variables etc). We also interface with an eyelink eye tracker, but that has its own network code. The problems you'll have to deal with is synchronisation, how will you ensure accurate timing between psychtoolbox and the eye tracker?

20 May 2013 Zack

Hi Kevin,

I am currently trying to link up a mac laptop that will be presenting a stimulus in MATLAB (psychtoolbox), to a PC that has eye tracking software (that can be controlled by MATLAB). Is there an easy way to achieve this using jtcp?

I greatly appreciate your help.

-zack

09 May 2013 Sally

Brilliant! Thanks Kevin!

09 May 2013 Kevin Bartlett

@Sally: You might use a try/catch block (if you're unfamiliar with these, type "doc try" on the command line).

09 May 2013 Sally

Thanks Kevin, so I tried that....but every time jtcp times out, it throws an error:
Error using jtcp>jtcp_accept_connection (line 327)
Java exception occurred:
java.net.SocketTimeoutException: Accept timed out

at java.net.PlainSocketImpl.socketAccept(Native Method)

at java.net.PlainSocketImpl.accept(Unknown Source)

at java.net.ServerSocket.implAccept(Unknown Source)

at java.net.ServerSocket.accept(Unknown Source)

Error in jtcp (line 232)
jTcpObj = jtcp_accept_connection(port,timeout,serialize);

So, if i could figure out a way to get it to timeout quietly and just get on with the rest of the code, that would work...

Suggestions?

08 May 2013 Kevin Bartlett

@Sally: It may be possible to do what you want to do, but I don't know how. The only workaround I can think of is to simulate a longer timeout by repeatedly calling jtcp with a short timeout in a loop. You could then interrupt the attempt the normal way you interrupt a loop, i.e., using Ctrl-C, deleting a control file, a GUI callback, etc.

08 May 2013 Sally

If you set the server to 'accept' a transmission with a long timeout, say 20 minutes, how do you abort the process? CTL+C doesn't seem to do anything. It just hangs until the process times out. I'd like to be able to abort sooner without having to shut down all of matlab and restarting.

04 May 2013 Kevin Wang

Any body tried this on Matlab 2011B and 2013A? I tried both today and got the following error message:

Error using jtcp>jtcp_request_connection (line 293)
Java exception occurred:
java.net.SocketTimeoutException: Read timed out
at java.net.SocketInputStream.socketRead0(Native Method)
at java.net.SocketInputStream.read(Unknown Source)
at java.io.ObjectInputStream$PeekInputStream.read(Unknown Source)
at java.io.ObjectInputStream$PeekInputStream.readFully(Unknown Source)
at java.io.ObjectInputStream$BlockDataInputStream.readShort(Unknown Source)
at java.io.ObjectInputStream.readStreamHeader(Unknown Source)
at java.io.ObjectInputStream.<init>(Unknown Source)
Error in jtcp (line 230)
jTcpObj = jtcp_request_connection(host,port,timeout,serialize);

19 Apr 2013 Kevin Bartlett

@Qi--As near as I can tell, this is a bug with Java itself. I've added a description of the bug and the workaround to the program description above.

Thanks again for pointing this out.

10 Apr 2013 Kevin Bartlett

@Qi--Thanks for the comment and especially for the test code. I'll see if I can replicate the error.

10 Apr 2013 Qi Wang

Hi Kevin,

Your great script is exactly what I was looking for. However after playing with it for sometime, I found a problem. I use it to transmit a lot of data between two matlab processes. After a certain among of data has been transmitted, there will be an error happened as follow:

Error using jtcp>jtcp_write (line 373)
Java exception occurred:
java.lang.OutOfMemoryError: Java heap space

Error in jtcp (line 234)
jtcp_write(jTcpObj,mssg);

How much data can be transmited before the error happen depends on the java heap size setting in matlab. It seems the data was never cleared in the matlab java heap memory.

here is the code I use for testing:
%%%%%%%%%%%%%%%%%%%%%%%%
jTCPObj = jtcp('ACCEPT', 3000,'TIMEOUT',30*60*1000);
cnt = 0;
while 1
cnt = cnt + 1;

data = [];
while isempty(data)
data = jtcp('READ', jTCPObj);
end
disp(['data packet: ' num2str(cnt) ' received']);
end

%%%%%%%%%%%%%%%%%%%%%%%%
jTCPObj = jtcp('REQUEST','localhost',3000,'TIMEOUT',2000);
cnt = 0;
while 1
cnt = cnt + 1;
disp(['data packet: ' num2str(cnt)]);
data = rand(1024*1024, 1);
jtcp('WRITE', jTCPObj, data);
end

I am not familiar with java. I don't know it is I made some mistake or there is a problem related to java in your functions?

02 Mar 2013 Michal  
28 Oct 2012 Rodrigo Fernandes  
03 Aug 2012 Roman Fedorenko

JTCPOBJ = jtcp('REQUEST','127.0.0.1',5050)
Java exception occurred:
java.io.StreamCorruptedException: invalid stream header: 003E02F6
at java.io.ObjectInputStream.readStreamHeader(Unknown Source)
at java.io.ObjectInputStream.<init>(Unknown Source)

Error in jtcp>jtcp_request_connection (line 293)
inputStream = java.io.ObjectInputStream(socketInputStream);

Error in jtcp (line 230)
jTcpObj = jtcp_request_connection(host,port,timeout,serialize);

27 Jul 2012 Sebastian Holmqvist

Wow, amazing script!

I was discouraged at first since my application didn't support serialization. But as soon as I grasped that it was on by default, everything came together.

Also, adding the DataReader class shaved off over 80 seconds from my script. Reading byte by byte apparently takes alot of time :)

However, adding dynamic java paths to matlab yields alot of output as all commands are then searched for in the dynamic paths. I would suggest changing

dynamicJavaClassPath = javaclasspath('-dynamic');

to

dynamicJavaClassPath = javaclasspath('-all');

in order to avoid adding dynamic paths in case a static one already exists, as it did for me (edited classpath.txt and restarted Matlab).

30 Apr 2012 none

excellent!

use this if you dont have tcpip.m in the ICT toolbox.

20 Jan 2012 Ueli Rutishauser  
05 Dec 2011 Alexander Kosenkov  
08 Nov 2011 Dean  
04 Oct 2011 Musharaf Ali

Excellent ,I works great and easy to use ,Bless you

12 Sep 2011 Mr Smart  
22 Aug 2011 Kevin Bartlett

Hi Nor, are you connecting two Matlab sessions together or trying to connect Matlab with some other software? Are you on Windows? Mac? Linux? What error message do you get when you fail to make a connection?

Probably the easiest way to play with jtcp.m is to get two Matlab sessions running on one computer (assuming your licence permits it). Assign one session the role of "client" and the other the role of "server and follow the example code in jtcp.m's help, with "client" lines being executed in the client session and the "server" lines being executed in the server session. EXECUTE THE LINES IN THE ORDER SHOWN IN THE HELP EXAMPLES. You can substitute a higher value than 2000 milliseconds for the timeout, if that makes things easier. I have used port 21566 in the examples; this port will have to be open in your firewall, or the firewall turned off.
Kevin.

22 Aug 2011 Nor Muzakkir

i cant connect at all. i've tried adding Rules in the firewall (even tried when turning off the firewall) but still i keep failing to make connection.

i really dont understand much on networking procedures, but if anyone could help point out the steps to make this works (especially establishing connection) it would be very helpful.

Thanks so much.

27 Jul 2011 Jesse Hopkins

Here's a link to CompressLib: http://www.mathworks.com/matlabcentral/fileexchange/25656-compression-routines

27 Jul 2011 Patrick Damiani

Hey Jesse, I looked up and down the file exchange for something called CompressLib. I tried searches for: convert, compress, structures, binary, tcp, bytes, variables, and the like. Is CompressLib still on the exchange?

27 Jul 2011 Patrick Damiani

Kevin, I was planning as much, but then I was going to ask if you knew if it was possible to... do exactly what Jesse has suggested. Thank you Jesse. I will check out CompressLib and see if the combination works for what I need.

27 Jul 2011 Jesse Hopkins

Patrick and Ian, take a look at CompressLib on the file exchange. Using this you can serialize almost any matlab structure to an array of bytes, and deserialize it back to a matlab structure on the other side. You can do classes as well, although that takes some work in the class definition itself.

26 Jul 2011 Kevin Bartlett

Hi Patrick. No, no plans to accommodate structures. You can easily pass any particular structure type by writing encode/decode functions to loop over the fields, passing each one to jtcp.m and re-assembling the structure on the other side. To make jtcp.m send and receive arbitrary structures, however, would require recursive programming to handle multiply-nested structures of all possible data types, and I didn't want to go that route.

26 Jul 2011 Patrick Damiani

Kevin,

I just downloaded your code, but I haven't had a chance to run it yet. I noticed in the description, you specifically say that it does not work on structures. Do you have plans to update this to send and receive structures?

28 Jun 2011 Ian

I'd love to be able to use this to send / receive class objects too. The way PNET does this is serialize an object to file (save it), then send the bytes, saved to file on the remote end and loaded back in. This is not efficient, but until TMW allows us to serialize objects properly, this works well enough.

22 Mar 2011 Alan

Thanks. Very nice.

19 Jan 2011 Kotya Karapetyan

I've found the problem: I was submitting int8('++addr'), but I should have submitted [int8('++addr') 13 10] to imitate CR.

19 Jan 2011 Kotya Karapetyan

Hello,

I am trying to use this tool to control a GPIB device over Ethernet using a Prologix' GPIB-Ethernet controller. Somehow I fail so far.

E.g., this controller can accept the command '++addr' and return the address of the device it is controlling. With a terminal program (I am using PuTTY), I type in '++addr' and get '5' in return. I am trying the code:

JTCPOBJ = jtcp('REQUEST', '131.220.157.23', 1234)
jtcp('WRITE',JTCPOBJ,int8('++addr'))
mssg = jtcp('READ', JTCPOBJ)

in the hope to see the response, but get a 1-by-0 matrix in response. Can you see what I am doing wrong? The IP address and the port are exactly the same as with the terminal.

13 Nov 2010 Elham Dolatabadi

Hello Kevin,

I tried to run the code and start a request from client to server but I got this error;
"??? Java exception occurred:
java.lang.IllegalArgumentException: timeout < 0

at java.net.PlainSocketImpl.setOption(Unknown Source)

at java.net.ServerSocket.setSoTimeout(Unknown Source)

Error in ==> jtcp>jtcp_accept_connection at 345
serverSocket.setSoTimeout(timeout);

Error in ==> jtcp at 256
jTcpObj = jtcp_accept_connection(port,timeout);"

What does that mean?

14 Oct 2010 Timothy

I'm looking at MATLAB (+ Add ons as requried) as part of my dissertaion to model SCADA vulnerabilities, when they use TCP/IP (UDP) etc. This has popped up in my searching. Anybody any ideas if this file is suitable?

24 Aug 2010 Tanyer Alan  
18 Nov 2009 Matthias Geier

@Kevin: Thanks for your response and for the adaptation of your code!
Just for the records: I was also running Matlab on Linux and I did have problems sending binary zeros.
I didn't try it on other operating systems.
I didn't try other strange characters either, just binary zeros and plain ASCII letters and punctuation.

17 Nov 2009 Kevin Bartlett

@Wei Ren: Thanks for the feedback. I don't think I misunderstood you. You were finding that when you sent 0xB4 (decimal 180), you were receiving -74; you found that Edwin's fix of using
mssg(i) = read( jTcpObj.dataInputStream );
instead of
mssg(i) = jTcpObj.dataInputStream.readByte;
solved this problem.

However my point is that I never experienced this same problem using readByte(), which is why I think there may be some platform-dependent issues here.

I think that switching from transmitting chars to transmitting int8 values, as I've done in the newest version, ought to avoid some of these issues.

Let me know how it works for you and if any of the same problems crop up again.

16 Nov 2009 Wei Ren

Kevin: I just wanted to make sure that you didn't misunderstood what i said last. 0xB4 is 180 in decimal. I was getting -74 until I corrected what Edwin pointed out.

16 Nov 2009 Kevin Bartlett

@Matthias and Rei Wen: I think we may be running into some platform-dependent stuff (I'm running Linux). I never had the problem in which 0xB4 becomes -74, and binary zeroes were coming through fine. I've rewritten jtcp.m to send messages in int8 format, rather than as strings. I'm hoping this will result in less variability in its behaviour. I also took Matthias' suggestion of using write() instead of writeBytes(). I'd appreciate you letting me know how this works for you.

In addition, I have incorporated Rodney Thomson's DataReader java class into the program (its use is optional). Again, let me know how this works for you.

15 Nov 2009 Matthias Geier

Hi Kevin and others.

I had a similar problem when I wanted to send strings which contained binary zeros (\0) as separators.
This didn't work with writeBytes() because the binary zero was interpreted as end-of-string.
Also, when I analyzed the IP traffic with wireshark, I saw that sometimes (strangely not always) an IP packet was sent for every single character of my message-string, which seemed quite inefficient to me.

So I changed line 351 from

jTcpObj.dataOutputStream.writeBytes(char(mssg));

to

jTcpObj.dataOutputStream.write(uint8(mssg), 0, length(mssg));

... where the second argument is an offset (which I chose to be 0).

This worked perfectly for me, I think it could also work for others, but of course I'm not sure about any side-effects or pitfalls ...

BTW, I didn't didn't care about receiving data, because I used another application for that.

Thanks for the this great m-file, it was very useful!

15 Nov 2009 Wei Ren

so using mssg(i) = read( jTcpObj.dataInputStream ) actually solved the problem of why 0xB4 was becoming -74. (Thanks Edwin)

So this is what i do sending hex data
mssg = sscanf(' 02 04 05 B4 01 01 04 02','%x');
jTcpObj.dataOutputStream.write(mssg);
jTcpObj.dataOutputStream.flush;

jTcpObj.dataOutputStream.writeBytes(mssg) works as well and both would work without using the flush class too.

on the receiving end
convert the mssg to hex using dec2hex(mssg)

13 Nov 2009 Kevin Bartlett

@Wei Ren: I saw Rodney's new DataReader class. I might try to incorporate it into jtcp to make it more efficient, but I haven't gotten around to it yet.

Regarding sending/receiving hex data: sorry, no clue. I'll keep playing with jtcp to see if it can be expanded to data types other than strings. If you figure anything out in the meantime, please let me know.

13 Nov 2009 Wei Ren

I forgot to note that even though it's sent correctly through wireshark, im still unable to read it correctly yet on matlab.
any ideas on how 0xB4 becomes -74?

13 Nov 2009 Wei Ren

so according to wireshark
mssg = sscanf(' 02 04 05 B4 01 01 04 02','%x');
using either
jTcpObj.dataOutputStream.writeBytes(char(mssg));
or
jTcpObj.dataOutputStream.write(mssg);
show as 02 04 05 B4 01 01 04 02 sent correctly. which is what I want.

also have you tried
data_reader = DataReader(d_input_stream);
message = data_reader.readBuffer(bytes_available);
Rodney had that new in his 2nd update of his syntax.
I tried adding that to your script but couldnt get it to work right.

09 Nov 2009 Wei Ren

The thing is that I need my server to communicate to an application that will need it in HEX. so :(

09 Nov 2009 Kevin Bartlett

Hexadecimal should be easy, since (as I understand it) Matlab stores hexadecimal numbers as strings anyway. If you have a decimal number to send, you can convert it to a string with sprintf or num2str. You can also switch back and forth from hex to decimal with hex2dec and dec2hex.

09 Nov 2009 Wei Ren

Hey thanks for the reply.
I'll try to see what matlab can do with changing the formats correctly how I need it. This is going to take some trial and error.

I wish it was more well documented.

09 Nov 2009 Kevin Bartlett

Edwin, changing line 396 to
"mssg(i) = read( jTcpObj.dataInputStream );"
might well be the right thing to do, but I can't say for sure that this won't cause more problems.

When I wrote jtcp.m, I limited it to handling strings because I don't really understand the internal workings of Sockets very well. Making it handle binary, hex, etc., seemed overly ambitious. I figured that for most applications the user could convert data to strings on one end and back to the original format (e.g., binary or hex) on the other.

I originally had a line testing to see if the user had entered a value of mssg that was not a string, but for some reason I commented it out. I have re-enabled this line, so now a non-string message will raise an error. Anybody who really wants to use jtcp.m to transmit binary or hex will have to re-comment out this test.

If there are any Sockets experts out there who want to take on the challenge of enhancing jtcp.m to handle other data types, I would encourage them to copy my code, build an improved version and post it to the File Exchange themselves, since this sort of thing is well outside my area of expertise.

Wei Ren, I hope this answers your question as well.

09 Nov 2009 Edwin Carter

Great little example.
The only problem I've found is that binary numbers >127 get mapped to zero on read. I found that replacing
mssg(i) = jTcpObj.dataInputStream.readByte;
with
mssg(i) = read( jTcpObj.dataInputStream );
(in jtcp_read(), line 396)
solves this issue, but I don't know if this is the right thing to do...

02 Nov 2009 Wei Ren

Can the output be anything else besides char? like hexidecimal for example?

23 Sep 2009 Derek Eggiman

Very nice example. However I've noticed your read function could be improved or perhaps cleaned up a little. Instead of the while loop for timeout you could do the following.

import java.net.Socket
import java.net.InetSocketAddress

%Set SocketAddress
sAddress = InetSocketAddress(Host,Port);

%Establish unconnected socket.
socket = Socket();

%connect
try
socket.connect(sAddress,timeout);
end

29 Jun 2009 Kevin Bartlett

Hi Jayson,

No, it wasn't your fault; I failed to close the server socket in the event of a timeout. I've posted an updated version that I hope fixes the problem, but it hasn't appeared online yet. Look for an "Updates" section to appear in the next day or so below this "Comments and Ratings" section and then download the new version.

Glad you're finding it useful! And thanks for your help!

Kevin.

29 Jun 2009 Jayson Brouchoud

Kevin,

This tool has been extremely useful for me. There is one problem I haven't gotten around yet. I'm regularily checking to see if other PCs have "logged on" so I'm doing a jtcp('accept') command triggered off a timer. The problem is that if the PC is not logging on, then I get a timeout as expected, but it hangs the port. I added a try/catch, but this kicks the jtcp routine back before it closes the port so I have the same problem. I'm sure it's my lack of how to use the tool properly, but if you have any suggestions, I would appreciate them.

Thanks,
Jayson

Updates
29 Jun 2009

Call to serverSocket.close added in try/catch statement in order to fix bug, spotted by Jayson Brouchoud, that caused port to hang after an "accept" timed out.

05 Oct 2009

Implemented suggestion from Derek Eggiman to replace while loop with built-in java socket timeout feature.

09 Nov 2009

Enabled call to error() if user inputs a value of mssg that is not a string.

16 Nov 2009

Switched to sending/receiving messages of "int8" format, rather than strings. Enabled optional use of Rodney Thomson's DataReader java class for more efficient reading of incoming data.

27 Jun 2011

Re-wrote Java code to permit reading and writing of cell arrays, matrices, strings, etc. (previous version limited to type "int8").

19 Jan 2012

Incorporates code from the earlier, int8-only version of jtcp.m to make data serialization optional. This allows jtcp.m to communicate with programs/hardware that do not themselves implement serialization.

03 Feb 2012

Removed reference to older version of jtcp.m (no longer included in zip file) from description.

26 Apr 2012

Now issues meaningful error message when an attempt is made to send non-int8 data with serialization set to false.

22 Apr 2013

Added workaround for outOfMemoryError to program description.

Contact us