I've set up a C++ server/client environment, and am trying to send a time_t value from the server to the client (an useful thing in any server). But I'm coming accross a headache: time_t seems to not be under any size specifications. I'm wondering what is the safest (more portable) way to send time_t over the network.
This is a little example:
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);
I have two problems:
How can I handle that two issues so that I can send it safely between (almost) any architecture?
Thanks in advance.
EDIT: After seeing the same three answers, I find it better to response here. I'm sorry I did not clarify that before. I prefer sending it in 'pure' bytes, although sending it as a string is not a problem. As far as I understand, I would need to keep in mind (again) the signedness and the size of time_t data type in the host system, isn't it? (thanks and sorry)
First, I think you need to decide if you want to deal with the issue that the C standard leaves the meaning of time_t
overly vague (it's not necessarily represented in seconds and doesn't even have any meaningful numerical properties like order/comparison). This is contrary to the behavior of every existing and historical implementation, where time_t
is in seconds. Both C and POSIX also allow time_t
to be a floating point type; as far as I know, no implementations make use of this, and on POSIX it would be rather harmful since the value of time_t
has to be an integer the way it's used in struct timespec
, etc.
If you decide you're happy assuming time_t
is always an integral number of seconds since the epoch, i.e. the values are meaningful for interchange between systems, then it's just a matter of formatting them. The safest thing to do would be to simply cast to a integer type that's large enough to store any meaningful value and that's the same size on all systems: that would be int64_t
. Then use whatever normal means you use for serializing int64_t
in a way that's immune to endian differences.
If on the other hand you want to be "absolutely" portable, you should compute your own time_t
value for "the epoch" (either the standard one or your own choice of epoch), then use difftime
to convert to a double representing "seconds since the epoch", and format the double
with snprintf(buf, sizeof buf, "%.0f", diff)
. Note that computing a time_t
value for the epoch in portable C is actually quite difficult because most of the standard functions work in local time, whereas you need universal time. There are tricks you can do with the gmtime
, mktime
, and localtime
functions to figure it out, but it's nontrivial...
You could send a textual representation produced by strftime
in combination with gmtime
. The representation would be a bit larger than a binary representation, but not huge. E.g., the format string "%Y%j%H%M%S"
produces a 13-byte representation of a moment in time (excluding a NUL character).
EDIT: forget about my previous advice to use ctime
; that uses localtime
and would therefore only work if client and server are in the same timezone. And apparently, asctime
is unsafe, so use strftime
.
You could send it in textual form, with a fixed number of digits. Then you don't have to worry about signs, size incompatibilities, or even byte order.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With