10

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);

2 つの問題があります。

  • time_t はサイズ固定ではありません
  • time_t は、符号付きまたは符号なしの整数データ型の typedef にすることができます

(ほぼ) 任意のアーキテクチャ間で安全に送信できるように、その 2 つの問題を処理するにはどうすればよいですか?

前もって感謝します。

編集:同じ3つの回答を見た後、ここで回答する方が良いと思います. 申し訳ありませんが、以前にそれを明確にしませんでした。文字列として送信しても問題ありませんが、「純粋な」バイトで送信することを好みます。私が理解している限りでは、ホスト システムの time_t データ型の署名とサイズを (再度) 心に留めておく必要がありますね。(感謝と申し訳ありません)

4

4 に答える 4

16

まず、C 標準の意味が非常に曖昧であるという問題に対処するかどうかを決定する必要があると思いますtime_t(必ずしも秒単位で表されるとは限らず、順序や比較などの意味のある数値プロパティさえありません)。これは、すべての既存および歴史的な実装の動作に反します。ここtime_tで、秒単位です。C と POSIX の両方でもtime_t、浮動小数点型にすることができます。私の知る限り、これを利用する実装はありません。POSIX では、 のはなどtime_tで使用されているように整数でなければならないため、かなり有害です。struct timespec

time_tが常にエポックからの整数秒数であると仮定して満足している場合、つまりがシステム間の交換に意味がある場合は、それらをフォーマットするだけです。最も安全な方法は、意味のある値を格納するのに十分な大きさで、すべてのシステムで同じサイズの整数型に単純にキャストすることint64_tです。int64_t次に、エンディアンの違いの影響を受けない方法でシリアル化するために使用する通常の手段を使用します。

一方、「絶対に」移植可能にしたい場合は、time_t「エポック」の独自の値(標準の値または独自のエポックの選択)を計算し、使用difftimeして「からの秒数」を表す double に変換する必要があります。エポック」を使用してフォーマットしdoublesnprintf(buf, sizeof buf, "%.0f", diff). ポータブル C でエポックの値を計算するtime_tことは、実際には非常に難しいことに注意してください。これは、ほとんどの標準関数がローカル時間で動作するのに対し、世界時が必要だからです。gmtimemktime、および関数を使用してそれを理解するためにできるトリックがありますがlocaltime、それは自明ではありません...

于 2012-12-19T17:00:25.033 に答える
4

strftimeと組み合わせてによって作成されたテキスト表現を送信できますgmtime。表現はバイナリ表現より少し大きくなりますが、巨大ではありません。たとえば、フォーマット文字列"%Y%j%H%M%S"は、ある時点の 13 バイト表現を生成します (NUL 文字を除く)。

EDIT:使用する私の以前のアドバイスを忘れてくださいctime。これは使用localtimeするため、クライアントとサーバーが同じタイムゾーンにある場合にのみ機能します。どうやら、asctime安全ではないので、を使用してstrftimeください。

于 2012-12-19T16:57:41.887 に答える
3

固定桁数のテキスト形式で送信できます。そうすれば、符号、サイズの非互換性、さらにはバイト オーダーについて心配する必要はありません。

于 2012-12-19T16:58:28.650 に答える