3

所以我在 linux 上用 C 语言编写了一个时间服务器-客户端应用程序,它应该将当前的 unix 时间戳发送到客户端。

它一切正常,但我被告知 time_t 可能并不总是相同的大小和字节顺序。我如何确保我发送的时间客户总是能理解?

到目前为止,我只是做

time_t now = htonl(time(0));

并发送。

我在 google 和 stackoverflow 上进行了搜索,但似乎其他人只是发送了 ctime() 或 strftime() 生成的时间字符串。

提前致谢!

4

1 回答 1

3

Ìn 一般发送二进制数据很容易出错,因为发送方和接收方对其解释方式不同。

time_t特别是它甚至不清楚会涉及多少位,它可能是 32 或 64 甚至更复杂的东西,time_t甚至可以实现为struct.

在您使用的特殊情况下htonl(),假定为 32 位,因为htonl()它采用 32 位值。

因此,故障安全解决方案确实是发送系统时间的文本表示。

以编程方式,这可能如下所示:

char st[64] = "";

{
  struct * tm = gmtime(time(NULL));
  if (NULL == tm)
  {
    fprintf(stderr, "gmtime() failed\n");
  }
  {
    if(0 == strftime(st, sizeof(st), "%s", tm)) /* Prints the text representaiotn of the seconds since Epoch into st. */
    {
      fprintf(stderr, "strftime() failed\n");
    }
  }
}

要反转此操作,您可以使用strptime()

char st[64] = "123456789123";
time_t t;
memset(&t, 0, sizeof(t));
{
  struct tm = {0};
  char p = strptime(t, "%s", &tm);
  if (NULL == p || p != (t + strlen(t)))
  {
    fprintf(stderr, "strptime() failed\n");
  }
  else
  {
    t = mktime(&tm);
  }
}

使用strptime()and的好处strftime()是您可以轻松地更改传输中的日期/时间的格式,只需修改调用这两个函数时指定的格式即可。

更改"%s""%Y-%m-%d %H:%M:%S"会转移时间"2014-05-20 13:14:15"


但是,如果您真的想以二进制格式发送 Epoch 以来的秒数并保持故障安全和便携,您需要注意三件事:

  1. 以可移植的方式获取自 Epoch 以来的秒数。
  2. 选择一个足够大的整数类型。
  3. 将此“大”值转换为网络字节顺序。

一种可能的方法是:

#include <time.h>
#include <inttypes.h> /* For uint64_t, as 64bit should do to represent the seconds since Epoch for the next few years. */

...

time_t t_epochbegin;
memset(&t_epochbegin, 0, sizeof(t_epochbegin);
uint64_t t_host = (uint64_t) difftime(time(NULL), t_epochbegin); /* Get the seconds since Epoch without relying on time_t being an integer. */
uint64_t t_network = htonll(t_host); /* Convert to network byte order. */

关于如何实现非标准,htonll()请参阅此问题的各种答案:Big Endian and Little Endian support for byte ordering


上面示例中的所有代码都假定运行代码的系统提供了一个计时器,并且尽管调用time()不会失败。

于 2014-06-26T16:40:48.130 回答