c/c ++ - 通过套接字发送time_t的最安全的方法

shu*_*ero 10 c c++ time network-programming

我已经设置了一个C++服务器/客户端环境,并尝试从服务器向客户端发送time_t值(在任何服务器中都很有用).但是我很头疼:time_t似乎没有任何尺寸规格.我想知道什么是通过网络发送time_t最安全(更便携)的方式.

这是一个小例子:

time_t T = time(NULL);
unsigned char * P = (unsigned char *)&T;
// ... Convert it to network byte order, etc.

// Here, 's' would be the socket, and 'S'
// the size of the data that is going to
// be sent
send(s, P, S, 0);
Run Code Online (Sandbox Code Playgroud)

我有两个问题:

  • time_t不是大小固定的
  • time_t可以是有符号或无符号整数数据类型的typedef

我如何处理这两个问题,以便我可以在(几乎)任何架构之间安全地发送它?

提前致谢.

编辑:看到相同的三个答案后,我觉得最好回答这里.对不起,我之前没有说清楚.我更喜欢用'纯'字节发送它,虽然将它作为字符串发送不是问题.据我了解,我需要(再次)记住主机系统中time_t数据类型的签名和大小,不是吗?(谢谢,对不起)

R..*_*R.. 15

首先,我认为您需要决定是否要处理C标准留下time_t过于模糊的含义的问题(它不一定用秒表示,甚至没有任何有意义的数字属性,如顺序/比较).这与每个现有和历史实施的行为相反,time_t在几秒钟内.C和POSIX都允许time_t成为浮点类型; 据我所知,没有实现充分利用这一点,并在POSIX这将是相当有害的,因为价值time_t必须是一个整数,它的使用的方式struct timespec,等等.

如果你认为你很高兴假设time_t自纪元以来总是一个整数秒,即这些对于系统之间的交换是有意义的,那么它只是格式化它们的问题.最安全的做法是简单地转换为一个足够大的整数类型来存储任何有意义的值,并且在所有系统上都是相同的大小:那就是int64_t.然后使用任何正常的方法int64_t,以一种不受endian差异影响的方式进行序列化.

另一方面,如果你想要"绝对"可移植,你应该time_t为"纪元"(标准的或你自己选择的纪元)计算你自己的价值,然后difftime用来转换成一个代表"自从时代",并格式化doublesnprintf(buf, sizeof buf, "%.0f", diff).请注意,time_t在便携式C 中计算纪元的值实际上非常困难,因为大多数标准函数在本地时间工作,而您需要通用时间.有技巧,你可以用做gmtime,mktimelocaltime功能弄明白,但它是平凡的...

  • 使用 32 位整数会很愚蠢;与在 1970 年代和 80 年代使用 2 位字符串大致相同的愚蠢程度。这是 2012 年。你有 64 位整数,它们对于宇宙的生命周期来说足够大。使用它们。 (2认同)

Fre*_*Foo 4

strftime您可以发送由与 结合生成的文本表示gmtime。该表示形式会比二进制表示形式稍大一些,但也不会很大。例如,格式字符串"%Y%j%H%M%S"生成一个时间点的 13 字节表示(不包括 NUL 字符)。

编辑:忘记我之前的使用建议ctime;它使用localtime并因此仅在客户端和服务器位于同一时区时才有效。显然,asctime这是不安全的,所以使用strftime.