Ich habe eine C ++ - Server / Client-Umgebung eingerichtet und versuche, einen time_t-Wert vom Server an den Client zu senden (eine nützliche Sache auf jedem Server). Aber ich bekomme Kopfschmerzen: time_t scheint unter keinen Größenangaben zu stehen. Ich frage mich, was ist die sicherste (portabler) Art und Weise zu senden time_t über das Netzwerk.
Dies ist ein kleines Beispiel:
%Vor%Ich habe zwei Probleme:
Wie kann ich diese zwei Probleme behandeln, damit ich sie sicher zwischen (fast) jeder Architektur senden kann?
Vielen Dank im Voraus.
EDIT: Nachdem ich die gleichen drei Antworten gesehen habe, finde ich es besser, hier zu antworten. Es tut mir leid, dass ich das vorher nicht geklärt habe. Ich bevorzuge es in 'reinen' Bytes zu senden, obwohl das Senden als String kein Problem ist. Soweit ich weiß, muss ich (wieder) die Signedness und die Größe des Datentyps time_t im Host-System berücksichtigen, oder? (Danke und Entschuldigung)
Erstens, ich denke, Sie müssen entscheiden, ob Sie sich mit dem Problem befassen wollen, dass der C-Standard die Bedeutung von time_t
zu vage lässt (es ist nicht unbedingt in Sekunden dargestellt und hat auch keine aussagekräftigen numerischen Eigenschaften wie Bestellung / Vergleich). Dies widerspricht dem Verhalten von jeder vorhandenen und historischen Implementierung, wobei time_t
in Sekunden angegeben ist. Sowohl C als auch POSIX erlauben auch, dass time_t
ein Fließkommatyp ist; Soweit ich weiß, machen das keine Implementierungen aus, und auf POSIX wäre das ziemlich schädlich, da der Wert von time_t
eine Ganzzahl sein muss, wie sie in struct timespec
verwendet wird .
Wenn Sie sich entscheiden, dass Sie zufrieden sind, wenn time_t
immer eine ganzzahlige Anzahl von Sekunden seit der Epoche ist, dh die Werte für den Austausch zwischen Systemen bedeutsam sind, dann müssen Sie sie nur formatieren . Am sichersten wäre es, einen Integer-Typ zu erzeugen, der groß genug ist, um einen sinnvollen Wert zu speichern, und der auf allen Systemen die gleiche Größe hat: das wäre int64_t
. Verwenden Sie dann die normalen Mittel, die Sie zum Serialisieren von int64_t
auf eine Art verwenden, die gegen Endian-Unterschiede immun ist.
Wenn Sie andererseits "absolut" portabel sein möchten, sollten Sie Ihren eigenen time_t
-Wert für "die Epoche" (entweder den Standard oder Ihre eigene Epoche) berechnen und dann difftime
verwenden konvertiert in ein Double, das "Sekunden seit der Epoche" darstellt, und formatiere double
mit snprintf(buf, sizeof buf, "%.0f", diff)
. Beachten Sie, dass die Berechnung eines time_t
-Werts für die Epoche in Portable C ziemlich schwierig ist, da die meisten Standardfunktionen in lokaler Zeit arbeiten, während Sie universelle Zeit benötigen. Es gibt Tricks, die Sie mit den Funktionen gmtime
, mktime
und localtime
ausführen können, um es herauszufinden, aber es ist nicht trivial ...
Sie können es in Textform mit einer festen Anzahl von Ziffern senden. Dann müssen Sie sich nicht um Zeichen, Größeninkompatibilitäten oder sogar die Byte-Reihenfolge kümmern.
Sie könnten eine Textdarstellung senden, die von strftime
in Kombination mit gmtime
erstellt wurde. Die Darstellung wäre etwas größer als eine Binärdarstellung, aber nicht groß. Z. B. erzeugt die Formatzeichenkette "%Y%j%H%M%S"
eine 13-Byte-Darstellung eines Zeitpunkts (ausschließlich eines NUL-Zeichens).
BEARBEITEN : Vergessen Sie meinen vorherigen Hinweis, ctime
zu verwenden; das verwendet localtime
und würde daher nur funktionieren, wenn sich Client und Server in derselben Zeitzone befinden. Und anscheinend ist asctime
unsicher, also benutze strftime
.
Ich habe gerade ein ähnliches Problem, und ich denke, es wäre nett, einige Anweisungen zu haben, wie man das durchmacht. Beachten Sie, dass diese Lösung hier POSIX.1-2001 kompatibel sein sollte (auf Ubuntu 14.04, man tzset
und man localtime
gibt solche Informationen, und ich habe wirklich keine anderen Quellen verwendet).
Verwenden Sie localtime
, um die aus Ihrem Aufruf erhaltenen Daten in time
in ein struct tm
zu konvertieren (siehe time.h
):
Beachten Sie, dass localtime
die Variable deklariert als (siehe auch time.h
)
Da alle Typen jetzt bekannt sind, können Sie Ihr eigenes Konvertierungstool schreiben, um dieses Datennetzwerk portabel zu machen. Dinge zu beachten:
int
und long
haben (verwenden Sie sizeof
, natürlich) struct tm
durchführen (verwenden Sie htonl
oder htons
- für 64-Bit-Typen müssen Sie Ihre eigenen schreiben) und senden Sie diese Information an den Client (wie Sie wollen). timezone
(siehe oben). Der Kunde muss dann
struct tm
(wenn Zeitzonen beteiligt sind, schreiben Sie die empfangenen Zeitzonendaten in ein long
) long
und berechne die Zeitzonendifferenz (berechne die Differenz des empfangenen timezone
-Datums und was du bekommst, indem du tzset
lokal aufrufst ...), passen Sie dann die in Schritt 2 erstellte Variable struct tm
an. struct tm
an die lokale Zeitzone des Kunden angepasst haben, verwenden Sie mktime
, um Daten in ein time_t
zurück zu konvertieren.
Tags und Links c c++ network-programming time