Ì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 以来的秒数并保持故障安全和便携,您需要注意三件事:
- 以可移植的方式获取自 Epoch 以来的秒数。
- 选择一个足够大的整数类型。
- 将此“大”值转换为网络字节顺序。
一种可能的方法是:
#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()
不会失败。