Matlab套接字等待响应

6
我正在尝试在Matlab中运行以下客户端和服务器套接字示例代码: http://www.mathworks.com/help/instrument/using-tcpip-server-sockets.html 这是我的代码。
服务器:
t=tcpip('0.0.0.0', 9994, 'NetworkRole', 'server');
fopen(t);
data=fread(t, t.BytesAvailable, 'double');
plot(data);

客户:
data=sin(1:64);
t=tcpip('localhost', 9994, 'NetworkRole', 'client');
fopen(t);
fwrite(t, data, 'double');

这是发生的事情:我运行服务器代码 -> 程序等待客户端连接 -> 我运行客户端代码 -> 在服务器控制台上,我得到:
Error using icinterface/fread (line 163)
SIZE must be greater than 0.

Error in socketTentativaMatlab (line 3)
data=fread(t, t.BytesAvailable, 'double');

我做错了什么?看起来服务器没有等待客户端发送任何内容就尝试读取数据,因此没有数据可读(它等待客户端连接)。现在我正在发送字符,所以我们确定 t.BytesAvailable = 元素数量。我已成功地以同步方式接收到以下方式的信息(这是服务器代码,客户端代码相同,但现在我发送字符并在与服务器建立连接后暂停1秒):
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

这是因为我怀疑bytesAvaiable是在尝试读取至少一次后剩余要读取的字节数...这似乎不太合理,但显然就是这样。由于我必须至少读取一次才能知道消息有多少字节...我选择第一次只读取1个字节。然后如果还有剩余的话,再读取剩下的部分...
我可以让这个在Matlab进程之间工作,但我无法在C++和Matlab之间做到这一点。C++客户端成功连接到Matlab服务器,并可以发送数据而没有问题或错误。然而,在Matlab服务器端,我无法读取它。
所有这些Matlab tcpip实现似乎都有很大问题!
编辑2: 如果我正确关闭客户端和服务器中的所有套接字(基本上不让程序退出时保持打开状态),上面的代码似乎可以始终正常工作。我去控制台并输入“netstat”以查看所有连接...结果由于我留下了打开的套接字,一些连接处于FIN_WAIT_2状态,这显然使得这些连接的端口无法使用。最终连接会超时,但需要一分钟或更长时间,因此,最好的做法是确保套接字始终正确关闭。
我不明白t.BytesAvaiable背后的逻辑...它似乎没有正确设置。如果我循环并等待它变得大于0,最终会发生这种情况,但这不是同步套接字的预期方式。我的代码允许以同步方式执行操作,即使我不理解为什么t.BytesAvaiable第一次没有正确设置。
最终服务器代码:
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);

最终客户端代码:
这是一个典型的套接字客户端,可以使用任何编程语言实现,但你必须确保在连续调用send()方法/函数(或在调用connect()和send()之间),至少要经过100毫秒的时间(较低的数字似乎存在风险)。

@DanielR 我修改了我的问题,因为链接是错误的。现在链接已经正确了。关于你的答案,我不明白你的意思。fopen 等待客户端连接,所以这方面应该没有问题... 服务器必须从一开始就处于活动状态... - jmacedo
1
@joxnas,我认为BytesAvailable不仅在尝试读取后才设置,因为我只是等待就让它工作了。可能有另一个原因导致读取一个字节后它的效果更好,我不知道。我同意,这个实现看起来相当糟糕。一个可能的解决方法:使用Matlab附带的java。虽然已经过了一段时间,但我没有问题使用java.ui中的ServerSocket和Socket实现了一个简单的Web服务器。 - A. Donda
1
我的意思是java.io,而不是java.ui,但两者都是错误的:它是java.net.Socket,并且可以从Matlab实例化。 - A. Donda
哦,我不记得了,但在Java中非常简单。在Matlab中,要开始使用:s = java.net.Socket()会给你一个Socket对象。 - A. Donda
端口方面有趣的观察。 - A. Donda
显示剩余2条评论
1个回答

8
您说的没错,服务器似乎并没有等待客户端,尽管默认的通信模式是同步的。您可以自己实现等待,例如通过插入代码:
while t.BytesAvailable == 0
    pause(1)
end

读取之前。

然而,我发现还有更多问题——从MathWorks网站下载的代码很糟糕——具体来说,t.BytesAvailable返回的是字节数,而fread需要值的数量,由于一个double值需要8个字节,因此它必须写成:

data=fread(t, floor(t.BytesAvailable / 8), 'double');

此外,如果客户端在打开连接后立即写入数据,我发现服务器会直接忽略这些数据。为了解决这个问题,我在客户端代码中插入了pause(1),像这样:

data=sin(1:64);
t=tcpip('localhost', 9994, 'NetworkRole', 'client');
fopen(t);
pause(1)
fwrite(t, data, 'double');

我的印象是Matlab的TCP/IP服务器客户端通信实现非常脆弱,需要大量的解决方法...


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接