超时后检查服务器是否收到数据

Check if server received data after timeout

我制作了一个使用比特币交易的几个 RestAPI 的程序,例如Bitstamp

有一个功能可以让我进行交易:以特定价格出售或购买比特币。简化后,您必须使用如下参数调用 URL:

https://www.bitstamp.net/api/trade?price=100&amount=1&type=sell

服务器然后在 JSON 中回答。示例:

{"error":"","message":"Sold 1 BTC @ 100$"}

如果交易成功,我的程序将继续。如果不是,它会再次尝试(取决于错误消息)。

但是,有一个问题。我正在使用 libcurl 与服务器进行通信,并将 CURLOPT_TIMEOUT 设置为两秒。它几乎总是有效,但有时我会收到以下错误:

Code #28: Operation timed out after 2000 milliseconds with 0 bytes received

发生这种情况时,我的程序会再次尝试交易。但有时,尽管超时,交易已经完成,这意味着它已经完成多次,因为我的代码再次尝试。

我能以某种方式查明服务器是否至少收到了所有数据吗?问题是,如果我将 CURLOPT_TIMEOUT 增加到 10 秒,而服务器没有应答,我也会遇到同样的问题。所以这不是解决方案。

我不知道 Bitstamp 的细节,但这是 HTTP 的工作原理。客户端向服务器发送请求并接收响应。在响应中,描述了有关成功或失败的详细信息(通过使用 HTTP 错误代码)。但是,如果收到超时,则客户端没有关于其请求的信息:

  • 是否发送到服务器;
  • 服务器收到了吗;
  • 如果服务器收到请求,是否成功处理;
  • 可能服务器处理了请求,但由于网络问题发送回响应失败。

因此,不应认为请求成功,而应重新发送请求。您所描述的问题当然是可能的 - 服务器收到请求,对其进行了处理但没有设法发回响应。因此,应该使用其他更复杂的协议,不幸的是,HTTP 不是其中之一,因为它具有请求-响应的性质。

也许您应该检查给定的 REST API 是否给出了交易的一些状态。

应该等待 HTTP 响应,以便更加确定您的请求是否已成功处理。

如果您可以访问文件描述符,则可以使用 SIOCOUTQ(Linux)或 FIONWRITE(BSD)调用 ioctl()——我不知道不知道 Windows 的等效项 --,在完全中止连接之前检查套接字级别未确认的已发送数据。

问题是它也不是完全没有错误的。尽管 TCP 在传输级别是有状态的,但 HTTP 在应用程序级别是无状态的。如果您的应用程序需要交易行为(毕竟您在处理货币,不是吗?),它应该为此提供一种方法。

综上所述,我认为两秒钟可能太短了。如果您因为多个操作或类似原因需要速度,请考虑并行化您的连接。