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.
Thanks, it is very easy to use and very useful.
ReplyDeleteonly 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.
it doesn't work by me. maybe i have to deactivate my and other Firewall?
DeleteAhhh yes, I assumed that would be obvious, for the purposes of the example (with 2 instances of Matlab running) only localhost will work.
ReplyDeleteI'll update the example.
Thanks
Hi Rodney
ReplyDeleteI 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:
ReplyDeleteWhen 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.
ReplyDeleteHi Rodney
ReplyDeletewould 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.
ReplyDeleteA 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.
ReplyDeleteI'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.
ReplyDelete1) 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.
ReplyDeletewhat 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.
ReplyDeleteFrom 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
ReplyDeletethe connection done now
the reason of failure :
Firewall server ports was blocked
and because I not run two command simultaneously.
thank you very much
hi
Deletehow did you solve that?
Hey Rodney,
ReplyDeleteI 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).
ReplyDeleteThere 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
thanks rodney ,i tried your example and it's not working , i wanna know if i should have the same version of matlab in each instance ??
ReplyDeleteand thank you another time
The versions of MATLAB should not be important so long as both are compatible with the inline Java calling (ie Release 14 onwards).
ReplyDeleteok thank you rod ,for the moment it works but can i send images or another thing over this example ??
ReplyDeleteand how ?? should i convert the image on "doublearray" or somthing like that ??
thanks a lot rod
your comments mentioned that the input and output from the client and server respectively are buffered.
ReplyDeleteI was reading
http://java.sun.com/docs/books/tutorial/essential/io/buffers.html
and I'm not very experience with java.
How does the link above differ with yours?
Thanks
hi,
ReplyDeletei having an issue where the 1st byte of what im sending is getting sent in it's own packet first then the next packet has the rest of the bytes.
How do I solve this issue?
thanks
for the moment it works but can i send images or another thing over this example ??Theoretically yes. Although it is not designed for this. If you had a double array:
ReplyDeletetmp = rand(1, 100);
% store the data in the array as a series of chars
tmp_byte = typecast(tmp, 'int8');
% on server:
server(char(tmp_byte), 3000, 10);
% on client
data_char = client('localhost', 3000);
% convert back form bytes to doubles. Note you may need to convert from char to int8 first with 'int8(data_char)'
data_double = typecast(data_char, 'double')
i having an issue where the 1st byte of what im sending is getting sent in it's own packet first then the next packet has the rest of the bytes.I can suggest maybe modifying the client.m file to keep reading until the desired number of bytes has been read.
One of these days i'll upload an improved method for reading in large amounts of data (unfortunately will need to resort to a Java .class file!)
thanks rod
ReplyDeletebut i got problem with the length of the image ,this exemple dont support sending more than 8000 byte
Hi Rodney
ReplyDeleteFirst of all I really want to thank you for this example: it's simple but very very useful!
I've just a question for you: is there a way to make the server running in another thread, leaving the user free to type commands in the Matlab Command Window? I mean..a background server :)!
Thank you for the help
Gianluca
This comment has been removed by the author.
ReplyDeleteHi Gianluca,
ReplyDeleteUnfortunately MATLAB is inherently single threaded. That is why in my example I state "Open a second instance of MATLAB" to run the client.
Some people have explored using Java Threading within MATLAB (http://www.osmanoglu.org/index.php/computing/4-computing/1-matlabjavamultitreading). This might give you some ideas (You may have to rewrite client/server in Java for this to work).
Hi Rodney,
ReplyDeletethank you for your answer. I also found the link in your answer, but I saw that they use Java thread separately from Matlab; what I'm trying to do is to make a "Matlab" server (maybe written using Java too) that permit to users, once it's started, to continue their work in Matlab. The problem is that the communication between Java and Matlab, using JMI, it's deprecated by Mathworks and no more supported, unlike the communication between Matlab and Java!
So I hoped that there would be a way to use Java within a M-File to make that file (i.e., that function) multithread, but I think that's not possible..so I have just few choices:
- use JMI hoping that it will work for at least the next two or three release;
- use Matlab Engine and so use C/C++ instead of Java: the communication Matlab-C/C++ is suppported both ways.
I don't know if I explained it well..I tried to summarize the problem at my best :)!
Thanks again
Gianluca
Hi Rodney
ReplyDeleteHow can I make connection between server and client in two different network
I try to do it but it failure
Is it possible to read out the structure of the stream which was send?
ReplyDeleteAre there any commands in matlab?
And how can I put it into the example?
Thanx for your Help und for your work
Hello I use you scripts in a GUI , and I want to know how could I make the server script to always listen for a connection. I tried a loop , I have a pushbutton and whe I press it it goes in a loop and waits for a connection but it blocks the matlab I can't do anything else , I also have a simulink model that I modifie some parameters in it whit the data that I receive from a connection but it blocks to , is there any way I can make the script to sleep for a time but only the GUI to sleep not Matlab, I've tried pause but it puts to sleep the GUI and the simulation . What should I do ?
ReplyDeleteI found this to be quite helpful, thank you!
ReplyDeleteMathlab also has its own tcp/ip functions:
ReplyDeletehttp://www.mathworks.com.au/help/toolbox/instrument/f16-54297.html
Hi, i want to send data via ethernet from matlab to my FPGA board and i have a question. Can i change this code to omit this part where we are connecting to the server and only send data without specyfing IP adres host etc. ?
ReplyDelete@Anonymous on Jan 14 2013:
ReplyDeleteUsing TCP/IP? No, you must specify a host and port for a client to connect to.
You MAY be able to do this with UDP, but I'll leave that to you to investigate.
@Rodney Thomson thanks for your reply.
ReplyDeleteNo, i dont need TCP/IP. On pc and on my fpga board there is no server, and shouldnt be. I have ethernet controler on board and i wonder if it works if i modify your matlab code to send only data via ethernet straight to board without setting IP etc.
@Anonymous:
ReplyDeleteSo you kind of want to use the Ethernet as a signal line for sending data to your FPGA? But without using TCP/IP or UDP/IP?
That MIGHT be possible but you would have to get access to the ethernet at a low level (ie driver level), so as good as impossible.
Sounds like your really just want a serial connection!
Either that or just use TCP/IP.
Hi.. As simple as the working of the client program, Can it not send data to the server?
ReplyDeleteI could not find a solution, and hoped it would be a piece of cake for you.
Is it possible to send message to server, before waiting for a message.
Tried to add d_output_stream from server code, and its not working.
Suggestions please
Thank you
@lakshman it is possible to modify the client to send days back to the server. Check back in the next few days and I'll try and upload an example.
ReplyDeleteYou have the right approach with the data output stream!
Hi Rodney Thomson,
ReplyDeleteThank you for very helpful codes
I have strange problem when running code as follow:
>> server(message, '3000', 10)
Try 1 waiting for client to connect to this host on port : 51
Try 48 waiting for client to connect to this host on port : 48
Try 48 waiting for client to connect to this host on port : Try 2 waiting for client to connect to this host on port : 51
Try 48 waiting for client to connect to this host on port : 48
Try 48 waiting for client to connect to this host on port : Try 3 waiting for client to connect to this host on port : 51
Try 48 waiting for client to connect to this host on port : 48
Try 48 waiting for client to connect to this host on port : Try 4 waiting for client to connect to this host on port : 51
Try 48 waiting for client to connect to this host on port : 48
Try 48 waiting for client to connect to this host on port : Try 5 waiting for client to connect to this host on port : 51
Try 48 waiting for client to connect to this host on port : 48
Try 48 waiting for client to connect to this host on port : Try 6 waiting for client to connect to this host on port : 51
Try 48 waiting for client to connect to this host on port : 48
Try 48 waiting for client to connect to this host on port : Try 7 waiting for client to connect to this host on port : 51
I dont know why this happens???
So, would you give me any solutions for this,
Thank you!
Port should be a number not a strong. Try:
ReplyDelete>> server(message, 3000, 10)
Hello Rodney,
ReplyDeleteI read one of your comments: "IE it looks like you have bi-directional comms. You could setup one machine as server and another as client, then use the Java DataOutputStream/DataInputStream objects on both the client and server to both read and write data without re-establishing a connection each time"
I try to modify your codes to make a server and a client connect all the time, and send/receive data bi-direction. But it seems connect only one time. So, would you tell me how can I make server/client to send and receive data all the time. Thank you!
Hi Rodney,
ReplyDeleteI use your example code to communicate two instances of Matlab and it works perfect. I have a question, I need to work in a remote machine as if I were in the local machine, Is it possible to open a session in the remote machine as if I were in the session of the local machine with this type of communication?
thanks in advance
@Anonymous (please put a name to the comments so I can address them!)
ReplyDeleteYou could in theory run remote commands using the eval() function and by sending commands. Maintaining a workspace of variables is more difficult, but again it is possible.
What I would recommend you look at is using the MATLAB Mobile functionality as this can either run MATLAB 'in the cloud' or it can connect to a running instance of MATLAB on one of your lan/internet connected computers.
http://www.mathworks.com.au/mobile/
I have tried to use your example, but when i try to connect to server , bring me back a error
ReplyDelete>> server(message, 3000, 10) [enter]
??? Error: File: server.m Line: 9 Column: 17
Unexpected MATLAB operator.
The line 9 is the code "if (nargin <>"
I'm using matlab 7.11.0 R2010b.
Tks for your support!
Carlos,
ReplyDeleteI'm not sure if is a typo where you have written the error message, but line 9 should be:
if (nargin < 3)
and not
if (nargin <>
Please check that the contents are correct. Otherwise try downloading the file again from the Mathworks File Exchange
Hi Rodney,
ReplyDeleteI'm more familiar with C++ than I am with Java. If I wanted to do this with an existing socket library written in C++, would I have to use MEX?
Thanks,
Allen
Hi Rodney,
ReplyDeleteThis is really great and an awesome piece of work. I tweaked the code a bit so that it can wait for the availability of the entire input stream buffer so that it can read the whole content correctly. I tested this with upto 4096 bytes and it worked well. Did not get time to test for more bytes though... Here is the tweak. This can be implemented on both server and client to complete the loopback...
%================================================
% reading data from Server
%================================================
% read data from the socket - wait a short time first
pause(0.5);
bytes_available = 0;
while bytes_available == 0
fprintf(1, 'Waiting for bytesavailable from server\n');
bytes_available = input_stream.available;
pause(1)
end
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);
Thanks,
Amit
Help!!!! something is wrong in here =(
ReplyDeleteif (nargin <>
number_of_retries = 20; % set to -1 for infinite
end
Right you are Itzel. Easy fixed, the line should be:
ReplyDeleteif (nargin < 3)
I blame Blogger's horrible support for formatted code at the time. It had a habit of destroying my formatting.
Hello sir,
ReplyDeleteHow do we create GUI interface for this server and multiple clients communication.
I am trying to build one, can you help me?