Using the ability to call Java directly from within MATLAB, I'm going to provide a short example of a client/server written solely in MATLAB and usable from Release 14 onwards (possibly even earlier).
The example is available on the Mathworks File Exchange: Simple TCP/IP Socket Comms Example
I'm working on a little TCP/IP comms library at the moment using these techniques. It will provide a nice layer of abstraction and allow you to use Sockets as you would in other programming languages (as well as one can in a single thread). Keep an eye out for it on the File Exchange.
Interpreted Java?
Amazingly we can execute Java code, even from within the Command Window without the need to compile. For example, the traditional example:
>> import java.lang.*
>> System.out.println('Hello World')
Hello World
To
perform socket communications, we utilise the Java Socket and Input/OutputStream classes to
pass data around via TCP/IP sockets.On the server side we use (unsurprisingly) a ServerSocket, which once a client has been accepted, provides a Socket around which we wrap a DataOutputStream to which we can write data.
On the client side we use a Socket to connect to the specified host and port which provides us an InputStream which we wrap in a DataInputStream to read data from.
The code for the example server and client is outlined below.
client.m
% CLIENT connect to a server and read a message
%
% Usage - message = client(host, port, number_of_retries)
function message = client(host, port, number_of_retries)
import java.net.Socket
import java.io.*
if (nargin <>
number_of_retries = 20; % set to -1 for infinite
end
retry = 0;
input_socket = [];
message = [];
while true
retry = retry + 1;
if ((number_of_retries > 0) && (retry > number_of_retries))
fprintf(1, 'Too many retries\n');
break;
end
try
fprintf(1, 'Retry %d connecting to %s:%d\n', ...
retry, host, port);
% throws if unable to connect
input_socket = Socket(host, port);
% get a buffered data input stream from the socket
input_stream = input_socket.getInputStream;
d_input_stream = DataInputStream(input_stream);
fprintf(1, 'Connected to server\n');
% read data from the socket - wait a short time first
pause(0.5);
bytes_available = input_stream.available;
fprintf(1, 'Reading %d bytes\n', bytes_available);
message = zeros(1, bytes_available, 'uint8');
for i = 1:bytes_available
message(i) = d_input_stream.readByte;
end
message = char(message);
% cleanup
input_socket.close;
break;
catch
if ~isempty(input_socket)
input_socket.close;
end
% pause before retrying
pause(1);
end
end
end
server.m% SERVER Write a message over the specified port
%
% Usage - server(message, output_port, number_of_retries)
function server(message, output_port, number_of_retries)
import java.net.ServerSocket
import java.io.*
if (nargin <>
number_of_retries = 20; % set to -1 for infinite
end
retry = 0;
server_socket = [];
output_socket = [];
while true
retry = retry + 1;
try
if ((number_of_retries > 0) && (retry > number_of_retries))
fprintf(1, 'Too many retries\n');
break;
end
fprintf(1, ['Try %d waiting for client to connect to this ' ...
'host on port : %d\n'], retry, output_port);
% wait for 1 second for client to connect server socket
server_socket = ServerSocket(output_port);
server_socket.setSoTimeout(1000);
output_socket = server_socket.accept;
fprintf(1, 'Client connected\n');
output_stream = output_socket.getOutputStream;
d_output_stream = DataOutputStream(output_stream);
% output the data over the DataOutputStream
% Convert to stream of bytes
fprintf(1, 'Writing %d bytes\n', length(message))
d_output_stream.writeBytes(char(message));
d_output_stream.flush;
% clean up
server_socket.close;
output_socket.close;
break;
catch
if ~isempty(server_socket)
server_socket.close
end
if ~isempty(output_socket)
output_socket.close
end
% pause before retrying
pause(1);
end
end
end
Opening up two instances of
Matlab:% Instance 1
>> message = char(mod(1:1000, 255)+1);
>> server(message, 3000, 10)
Try 1 waiting for client to connect to this host on port : 3000
Try 2 waiting for client to connect to this host on port : 3000
Try 3 waiting for client to connect to this host on port : 3000
Try 4 waiting for client to connect to this host on port : 3000
Client connected
Writing 1000 bytes
% Instance 2 (simultaneously)
% NOTE: If the 'server' was runnning on a non local machine, substitute its IP address
% or host name here:
% data = client('10.61.1.200', 2666); % To connect to server at IP 10.61.1.200:2666
>> data = client('localhost', 3000)
Retry 1 connecting to localhost:3000
Retry 2 connecting to localhost:3000
Connected to server
Reading 1000 bytes
data =
!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~
!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~
!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~
!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~
This code can be expanded to
read/write arbitrary data types, and SHOULD be expanded to properly deal with
errors (ie not getting all of the buffer on receive end), but it serves as a
simple example of how to get communication between MATLAB and other applications
/ instances of MATLAB.
14 comments:
Thanks, it is very easy to use and very useful.
only one suggestion, in the example, although it is almost obvious, clarify you can put
an specific IP (client('190.0.0.162',3000)) to connect to other PC instead of client('localhost',3000)
Thanks again.
Ahhh yes, I assumed that would be obvious, for the purposes of the example (with 2 instances of Matlab running) only localhost will work.
I'll update the example.
Thanks
Hi Rodney
I have Matlab 7.5.0
I tried your example in two instances of matlab, but it is not working.
here what I get in server side.
>> message = char(mod(1:1000, 255)+1);
>> server(message, 3000, 10)
Try 1 waiting for client to connect to this host on port : 3000
Try 2 waiting for client to connect to this host on port : 3000
Try 3 waiting for client to connect to this host on port : 3000
Try 4 waiting for client to connect to this host on port : 3000
Try 5 waiting for client to connect to this host on port : 3000
Try 6 waiting for client to connect to this host on port : 3000
Try 7 waiting for client to connect to this host on port : 3000
Try 8 waiting for client to connect to this host on port : 3000
Try 9 waiting for client to connect to this host on port : 3000
Try 10 waiting for client to connect to this host on port : 3000
Too many retries
and in client side I get also :
>> data = client('localhost', 3000)
Retry 1 connecting to localhost:3000
Retry 2 connecting to localhost:3000
Retry 3 connecting to localhost:3000
Retry 4 connecting to localhost:3000
Retry 5 connecting to localhost:3000
Retry 6 connecting to localhost:3000
Retry 7 connecting to localhost:3000
Retry 8 connecting to localhost:3000
Retry 9 connecting to localhost:3000
Retry 10 connecting to localhost:3000
Too many retries
data =
[]
P.S : I run the two command simultanously.
Do you have any suggestion ? Thanks
Ok, firstly the obvious question:
When you say you are running them simultaneously, does that also mean you are running the 2 instances on the same machine? If not, then the client will need to connect to the server machine (ie client('192.168.1.2', 3000))
Other than that I would suggest checking any firewall services on your machine and make sure they are not blocking the incoming connections.
Alternatively, you could test just the server alone by using telnet to connect. Start the MATLAB server method. Run telnet (Start->run(cmd), then type telnet localhost 3000) and verify you see the message appear.
Any other dramas email me at rodney.thomson @ gmail.com
most helpful, thank you.
Hi Rodney
would you mind see where the problem ,please ?
I have Matlab 7.5.0
I tryied examples using 2 machine
and I put
ie client('62.215.158.219', 3000))
result :
server
>> message = char(mod(1:1000, 255)+1);
>> server(message, 3000, 10)
Try 1 waiting for client to connect to this host on port : 3000
Try 2 waiting for client to connect to this host on port : 3000
Try 3 waiting for client to connect to this host on port : 3000
Try 4 waiting for client to connect to this host on port : 3000
Try 5 waiting for client to connect to this host on port : 3000
Try 6 waiting for client to connect to this host on port : 3000
Try 7 waiting for client to connect to this host on port : 3000
Try 8 waiting for client to connect to this host on port : 3000
Try 9 waiting for client to connect to this host on port : 3000
Try 10 waiting for client to connect to this host on port : 3000
Too many retries
client
>> data = client('62.215.158.219', 3000)
Retry 1 connecting to localhost:3000
Retry 2 connecting to localhost:3000
Retry 3 connecting to localhost:3000
Retry 4 connecting to localhost:3000
Retry 5 connecting to localhost:3000
Retry 6 connecting to localhost:3000
Retry 7 connecting to localhost:3000
Retry 8 connecting to localhost:3000
Retry 9 connecting to localhost:3000
Retry 10 connecting to localhost:3000
Too many retries
data =
[]
thanks
I can't see anything obvious as to why it would not be working in your scenario.
A few things to check:
- Firewall, ensure server ports are not being blocked
- General connectivity, can you ping '62.215.158.219' from your client machine from within a Command Window (or terminal)
Note that MATLAB has a manual proxy setup (if the machine you are attempting ot access is external to your network). It can be configured in File->Preferences->Web
Hope that helps!
I'm not familiar with java and have been trying the Instrument Control Toolbox instead.
I'm trying to create my own client SW to send data to a rapid prototyping machine.
I can connect to the machine using both toolbox and your java method but i haven't been able to send the data that i've recorded in Wireshark.
I have a few questions"
1.Can your client script be modified to send messages? If so is it the same command as in the server script?
2.is there a way to control the flags in the protocol? eg. ACK, SYN , Push?
Thanks
Firstly, these files are just a simple EXAMPLE of TCP/IP socket comms in MATLAB. They are not always the best solution for every application. But they are a good starting point.
1) Yes, the Java Socket interface (http://java.sun.com/j2se/1.4.2/docs/api/java/net/Socket.html) allows you to obtain an OutputStream (getOutputStream) from which you could apply the same techniques as in server.m to send data.
2) As for manually manipulating the TCP/IP flags in the Java Sockets... errr pass! That a bit lower down then my current experience allows. Maybe try Google for those!
Good Luck!
Rod
thanks for your reply.
what i was getting to about the TCPIP flags was that I can't get what the status of the packets are via the flags. eg. whether i received an ACK from the server so i can send the next packet.
I can't find any documentations for the matlab instrument control and have already read through the JAVA tcpip tutorial and didn't find anything that would help me with this.
Would you happen to know anything about this?
Thanks
I've never personally dealt with the SYN/ACK stuff personally. I've always been sitting high and dry in the session layer with a nice TCP/IP Socket that hides all of that behavior.
From initial glance, the default behavior of a Java Socket for writing is that it will be a blocking write, so if the Socket is unable to immediately send the data, it will wait as required.
Sorry I'm not too much help with this!
Hi Rodney
the connection done now
the reason of failure :
Firewall server ports was blocked
and because I not run two command simultaneously.
thank you very much
Hey Rodney,
I find this link very useful for matlab users. I myself am using your code for communication between two matlab processes. I am trying to send a small file (around 600KB) from server end to the client end.
Server flashes a message that it has sent all the data to the client but client script prints: "Reading 72 bytes"
Can you suggest why client is not able to read all the data?
Thanking You,
Mayank
In client.m, it only attempts to read the data available on the underlying data stream (Socket in this case).
There are a couple of ways you could attempt to ensure you read the entire contents of your file:
1) sleep longer - Waiting until all of the data is sent and hopefully flushed
2) Put a loop in client.m and keep attempting to read until the desired number of bytes has been read.
Note: the specific example in client.m was really designed as a proof of concept and performs poorly with even relatively short messages. I'll post an update shortly which uses a compiled Java class to read data in a more efficient manner (but then becomes slightly more annoying having to cart a .class file around!)
Rod
Post a Comment