【问题标题】:Matlab sockets wait for responseMatlab 套接字等待响应
【发布时间】:2015-05-01 20:16:34
【问题描述】:

我正在尝试在 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');

我做错了什么?看起来服务器没有等待客户端发送任何东西来尝试读取数据,所以没有数据要读取(它等待客户端连接的想法)。


编辑1: 好的,我现在正在发送字符,所以我们确定 t.BytesAvaiable = 元素数。

我已经能够通过以下方式成功同步接收(这是服务器代码,客户端代码相同但我现在发送字符并在与服务器建立连接后暂停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 毫秒(较低的数字接缝有风险)已失效。

【问题讨论】:

  • 如果客户端未启动,t.BytesAvailable 为零,您正在读取零字节。这是不可能的,只有t.BytesAvailable>0
  • @DanielR 我编辑了我的问题,因为链接错误。现在是对的。关于你的回答,我不明白你的意思。 fopen 等待客户端连接,所以应该没有问题...从一开始就必须处于活动状态的是服务器...
  • @joxnas,我不认为 BytesAvailable 仅在尝试读取后才设置,因为我只需等待即可使其工作。我不知道为什么它在读取一个字节后效果更好的另一个原因。我同意,实现看起来很糟糕。一种可能的解决方法:使用 Matlab 附带的 java。已经有一段时间了,但我使用 java.ui 中的 ServerSocket 和 Socket 在 java 中实现一个简单的 Web 服务器没有问题。
  • 我的意思是java.io,不是java.ui,但两者都是错误的:它是java.net.Socket,它可以从Matlab中实例化。
  • @A.Donda 看看我上次的编辑。我认为它现在已经解决了,但是如果你的口袋里有 matlab 中服务器套接字的 java 实例化实现,我很乐意保存它并研究它以备将来使用:)

标签: matlab sockets


【解决方案1】:

你是对的,服务器似乎并没有在等待客户端,即使默认的通信模式是同步的。您可以自己实现等待,例如通过插入

while t.BytesAvailable == 0
    pause(1)
end

在阅读之前。

但是,我发现还有更多问题——MathWorks 网站上的代码如此糟糕,这很奇怪——即,t.BytesAvailable 给出了一些字节,而fread 需要一些值,并且因为一个双精度值需要 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 服务器客户端通信相当脆弱,需要很多变通办法……

【讨论】:

    猜你喜欢
    • 2020-08-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-10-23
    • 1970-01-01
    相关资源
    最近更新 更多