I'm trying to run the following client and server socket example code in matlab: http://www.mathworks.com/help/instrument/using-tcpip-server-sockets.html
This is my code.
Server:
t=tcpip('0.0.0.0', 9994, 'NetworkRole', 'server');
fopen(t);
data=fread(t, t.BytesAvailable, 'double');
plot(data);
Client:
data=sin(1:64);
t=tcpip('localhost', 9994, 'NetworkRole', 'client');
fopen(t);
fwrite(t, data, 'double');
This is what happens: I run the server code-> The program waits for the connection from the client-> I run the client code ->In the server console I get:
Error using icinterface/fread (line 163)
SIZE must be greater than 0.
Error in socketTentativaMatlab (line 3)
data=fread(t, t.BytesAvailable, 'double');
What am I doing wrong? It looks like the server doesn't wait for the client to send anything to try to read the data, so there's no data to read (It waits for the client connection thought).
Edit1: Ok, I'm sending chars now, so we know for sure that t.BytesAvaiable = number of elements.
I have been able to successfully receive synchronously in the following way (this is server code, client code is the same but I send chars now and pause 1 second after establishing the connection with the server):
t=tcpip('0.0.0.0', 30000, 'NetworkRole', 'server');
fopen(t);
data=strcat(fread(t, 1, 'uint8')');
if get(t,'BytesAvailable') > 1
data=strcat(data,fread(t, t.BytesAvailable, 'uint8')');
end
data
This is because I suspected that bytesAvaiable is the number of bytes left to read after attempting to read at least once... this doesn't seem very logical, but it apparently is what happens. Since I have to read at least once to know how many bytes the message has...I choose to read 1 byte only the first time. I then read what's left, if there is something left...
I can make this work between matlab processes, but I can't do it between C++ and matlab. The C++ client successfully connects to the matlab server, and can send the data without problems or errors. However, on the matlab server side, I can't read it.
Something seems very wrong with all this matlab tcpip implementation!
Edit2: If I properly close all the sockets in both client and server (basically don't let the program exit with open sockets), the above code seams to work consistently. I went to console and typed "netstat" to see all the connections ...It turns out since I was leaving open sockets, some connections were in the FIN_WAIT_2 state, which apparently rendered the ports of those connections unusable. Eventually the connection times out definitely, but it takes a minute or more, so, it's really best practice to just make sure the sockets are always properly closed.
I don't understand thought what is the logic behind t.BytesAvaiable... it doesn't seam to make much sense the way it is. If I loop and wait for it to become greater then 0, it eventually happens, but this is not the way things are supposed to be with synchronous sockets. My code lets one do things synchronously, even though I don't understand why t.BytesAvaiable isn't properly set the first time.
Final server code:
t=tcpip('0.0.0.0', 30000, 'NetworkRole', 'server');
fopen(t);
data=strcat(fread(t, 1, 'uint8'));
if get(t,'BytesAvailable') > 1
data=strcat(data,fread(t, t.BytesAvailable, 'uint8')');
end
fclose(t);
Final client code:
Your typical socket client, implemented in any language, but you will have to make sure that between successive calls of send() method/function (or between calling connect() and send()), at least 100ms (lower number seam to be risky) are ellapsed.
You are right, the server doesn't appear to be waiting for the client, even though the default mode of communication is synchronous. You can implement the waiting yourself, for example by inserting
while t.BytesAvailable == 0
pause(1)
end
before the read.
However, I've found that there are more problems – it's weird that the code from the MathWorks site is so bad – namely, t.BytesAvailable
gives a number of bytes, while fread
expects a number of values, and since one double value needs 8 bytes it has to say
data=fread(t, floor(t.BytesAvailable / 8), 'double');
Moreover, if the client writes the data immediately after opening the connection, I've found that the server simply overlooks them. I was able to fix this by inserting a pause(1)
in the client code, like this
data=sin(1:64);
t=tcpip('localhost', 9994, 'NetworkRole', 'client');
fopen(t);
pause(1)
fwrite(t, data, 'double');
My impression is that Matlab's implementation of TCP/IP server client communication is quite fragile and needs a lot of workarounds...
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With