c-时间服务器时间类型问题
作者:互联网
因此,我在linux上用C编写了一些时间服务器-客户端应用程序,该应用程序应该将当前的unix时间戳发送给客户端.
一切正常,但是我被告知time_t的大小和字节顺序可能并不总是相同.如何确定我发送给客户的时间总是可以理解的?
截至目前,我只是做
time_t now = htonl(time(0));
并发送.
我在google和stackoverflow上搜索,但似乎其他所有人都只是发送ctime()或strftime()生成的时间字符串.
提前致谢!
解决方法:
由于发送方和接收方采用不同的解释方式,一般发送二进制数据容易出错.
特别是对于time_t,甚至还不清楚会涉及多少位,它可能是32位或64位,甚至更复杂,因为time_t甚至可能实现为结构.
在使用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()和strftime()的好处是,您只需更改调用这两个函数时指定的格式,就可以轻松更改传输中日期/时间的格式.
将“%s”更改为“%Y-%m-%d%H:%M:%S”会转移时间,例如“ 2014-05-20 13:14:15”.
但是,如果您真的想以二进制格式发送自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()的调用不会失败.
标签:time-t,sockets,networking,c-3,linux 来源: https://codeday.me/bug/20191121/2052798.html