Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Matlab sockets wait for response

Tags:

sockets

matlab

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.

like image 867
jmacedo Avatar asked Nov 28 '13 17:11

jmacedo


1 Answers

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...

like image 175
A. Donda Avatar answered Nov 15 '22 06:11

A. Donda