检查套接字状态
使用套接字时,有必要检查其状态,因为分布式网络不像文件系统那样可靠。特别是,连接可能会因某种原因丢失。SocketIsConnected 函数允许你查明这一点。
bool SocketIsConnected(const int socket)
该函数会检查具有指定句柄(从 SocketCreate获得)的套接字是否已连接到其网络资源(在 Socket Connect中指定),并在成功时返回 true。
另一个函数 SocketIsReadable 让你知道与套接字关联的系统缓冲区中是否有任何可读取的数据。这意味着我们通过网络地址连接到的计算机已向我们发送(并可能继续发送)数据。
uint SocketIsReadable(const int socket)
该函数返回可以从套接字读取的字节数。如果出错,返回 0。
熟悉 Windows/Linux 套接字系统 API 的程序员知道,当套接字内部缓冲区中没有传入数据时,值 0 也可能是一种正常状态。然而,该函数在 MQL5 中的行为有所不同。当系统套接字缓冲区为空时,它会推测性地返回 1,将实际的数据可用性检查推迟到下一次调用某个读取函数时。特别是,这种返回虚拟 1 字节结果的情况,通常发生在首次对套接字调用该函数且接收内部缓冲区仍为空时。
执行此函数时可能会发生错误,这意味着通过 SocketConnect 建立的连接已断开(在 _LastError 中我们将得到代码 5273,ERR_NETSOCKET_IO_ERROR)。
SocketIsReadable 函数在设计用于使用 SocketRead进行“非阻塞”数据读取的程序中很有用。关键在于,当接收缓冲区中没有数据时,SocketRead 函数会等待数据到达,从而暂停程序的执行(暂停时间取决于指定的超时值)。
另一方面,阻塞读取在某种意义上更可靠,因为一旦新数据到达,你的程序就会“唤醒”,但是需要根据其他一些事件(通常是定时器或在循环中)定期使用 SocketIsReadable 检查数据是否存在。
在 TLS 安全模式下使用 SocketIsReadable 函数时应特别小心。该函数返回“原始”数据的量,在 TLS 模式下,这是一个加密块。如果“原始”数据尚未累积到解密块的大小,则后续调用读取函数 SocketTlsRead 将阻塞程序执行,等待缺失的片段。如果“原始”数据已包含准备好解密的块,则读取函数将返回比“原始”字节数少的已解密字节。因此,启用 TLS 时,建议始终将 SocketIsReadable 函数与 SocketTlsReadAvailable结合使用。否则,程序的行为将与预期不同。遗憾的是,MQL5 没有提供与 TLS 模式兼容且不强加所述约定的 SocketTlsIsReadable 函数。
类似的 SocketIsWritable 函数会检查给定套接字当前是否可写入。
bool SocketIsWritable(const int socket)
函数返回成功 (true) 或错误 (false) 的指示。在后一种情况下,通过 SocketConnect 建立的连接将被断开。
这是一个简单的脚本 SocketIsConnected.mq5,用于测试这些函数。在输入参数中,我们将提供输入地址和端口的机会。
input string Server = "www.mql5.com";
|
在 OnStart 处理程序中,我们创建一个套接字,连接到站点,并开始在循环中检查套接字的状态。在第二次迭代之后,我们强制关闭套接字,这应该会导致退出循环。
void OnStart()
|
以下条目显示在日志中。
Server=www.mql5.com / ok
|