[suse-programming] Sockets in verschiedenen Sprachen? Endekennung??
Hallo alle zusammen, ich schreibe gerade einen kl. Serveranwendung, der Server ist in perl, der Client in Java. Das klappt ganz gut! Nur womit wird der Socket Stream abgeschlossen? Beispiel: Der Client sendet einen String "hallo", in perl will diesen String auswerten. if ( $string eq 'hallo') print "$string"; Ich habe schon versucht, mit chomp das "\n" zu entfernen, reicht aber scheinbar nicht. Also mache ich noch ein "chop" hinterher, jetzt funktioniert das ganze. Aber was hängt denn da nun eigentlich für ein Steuerzeichen hinter? Ist das Sprachübergreifend gleich? (IMHO sollte es so sein...) Ciao Andre
* Andre Heine
Hallo alle zusammen,
ich schreibe gerade einen kl. Serveranwendung, der Server ist in perl, der Client in Java.
Das klappt ganz gut!
Nur womit wird der Socket Stream abgeschlossen?
Beispiel:
Der Client sendet einen String "hallo", in perl will diesen String auswerten.
if ( $string eq 'hallo') print "$string";
Ich habe schon versucht, mit chomp das "\n" zu entfernen, reicht aber scheinbar nicht. Also mache ich noch ein "chop" hinterher, jetzt funktioniert das ganze. Aber was hängt denn da nun eigentlich für ein Steuerzeichen hinter?
binäre 0 = \0
also
$string =~ s/\0+//g;
oder sowas ...
cu
--
echo '@a=(A..Z,a..z," ");$t="a"x16;{for($x=0,$|=$n=30; $n--;){for($l=$t;1
Hi Remo,
From: Remo Behn
* Andre Heine
[020617 14:23]: Nur womit wird der Socket Stream abgeschlossen? Ich habe schon versucht, mit chomp das "\n" zu entfernen, reicht aber scheinbar nicht. Also mache ich noch ein "chop" hinterher, jetzt funktioniert das ganze. Aber was hängt denn da nun eigentlich für ein Steuerzeichen hinter?
binäre 0 = \0
Hmm, das kann gut sein, muß aber immernoch chomp & chop benutzen. Ich werde mal Deinen Ansatz verfolgen, und das mit 'ner regex machen. IMHO ist das dann etwas sicherer :)) Thx Andre PS: Ist der Einzeiler von Dir? Der ist gut.... print just another perl hacker;q;s/^\w+_}/;;sub _{reverse split q=:+==>[caller${\1}]->[3]};;sub another::just{shift&&join q=>_,@_};package hacker;sub perl{}$0=~m() Leider nicht von mir ;((
Hallo Andre, "Andre Heine" wrote:
ich schreibe gerade einen kl. Serveranwendung, der Server ist in perl, der Client in Java.
Das klappt ganz gut!
Nur womit wird der Socket Stream abgeschlossen?
der ganze Strom wird durch das Schließen der (TCP-)Verbindung abgeschlossen, ohne daß dafür ein Steuerzeichen in den Strom selbst eingefügt wird. Aber das ist anscheinend nicht das, was Du meinst.
Der Client sendet einen String "hallo", in perl will diesen String auswerten.
if ( $string eq 'hallo') print "$string";
Ich habe schon versucht, mit chomp das "\n" zu entfernen, reicht aber scheinbar nicht.
Ich nehme dann mal an, daß Du in Java eine der Funktionen zum Schreiben einer ganzen Zeile mit automatischem Anhängen eines Zeilenumbruchs benutzt hast. Es könnte sein, daß dabei die Zeilen nicht nur mit einem Linefeed, sondern mit der Kombination Carriage-Return + Linefeed ("\r\n") abgeschlossen werden. Sie mal in der Dokumentation der entsprechenden Java-Klassen nach, da sollte was dazu drin stehen.
Also mache ich noch ein "chop" hinterher, jetzt funktioniert das ganze. Aber was hängt denn da nun eigentlich für ein Steuerzeichen hinter?
Falls obige Vermutung zutrifft, läßt das chomp natürlich noch ein "\r" am Ende des Strings übrig. Mit dem zusätzlichen chop wird dieses entfernt -- aber das Funktioniert mehr "zufällig" (eben weil's das letzte Zeichen ist), ist aber keine besonders saubere und robuste Lösung.
Ist das Sprachübergreifend gleich?
Nein, nicht unbedingt. Sprachen (bzw. zugehörige Bibliotheken) stellen mitunter Hilfsmittel zum Lesen oder Schreiben von Textzeilen zur Verfügung. Die genauen Eigenschaften dieser Hilfmittel sollte man jeweils in der Dokumentation nachlesen, denn da kann es durchaus feine Unterschiede geben -- nicht nur zwischen verschiedenen Sprachen, sondern vor allem auch bei der gleichen Sprache auf unterschiedlichen Plattformen. Beispiel: In Unix-artigen Systemen ist der übliche Zeilenumbruch in Textdateien ein einfaches "\n", unter MS-DOS bzw. Windows dagegen die Kombination "\r\n". Dementsprechend verhalten sich die C-Funktionen fread(), fwrite() etc. je nach Plattform unterschiedlich, wenn der Stream beim fopen() als Text- und nicht als Binärdatei geöffnet wurde: Unter Unix würde etwa beim Schreiben ein "\n" unverändert geschrieben, aber unter MS-DOS würde ein C-Stream "on the fly" ein "\r\n" daraus machen. Ich denke, in anderen Sprachen (z.B. Java) werden solche Mechanismen auch verfügbar sein. Der Programmierer wird so dabei unterstützt, die in der jeweiligen Umgebung üblichen Konventionen einzuhalten. Wenn nicht alle beteiligten Programme die gleichen Konventionen einhalten, gibt's natürlich ein Problem. Sowas passiert besonders gerne, wenn ein Datenaustausch (z.B. über's Netz) zwischen verschiedenen Plattformen stattfindet. Gängige Problemquellen sind z.B. unterschiedliche Byte-Order, verschiedene Zeichensätze oder eben unterschiedliche Repräsentation von Zeilenenden. Die Lösung besteht darin, für die Übertragung ein Protokoll zu definieren, daß die genaue Darstellung für den Datenaustausch festlegt. Man kann natürlich auch bewußt bestimmte Spielräume lassen und fordern, daß der Empfänger mit allen Varianten klarkommen muß. In Deinem Fall könntest Du z.B. sagen, daß der Empfänger verschiedene Darstellungen des Zeilenendes handhaben können muß. Für die Realisierung in perl gibt `perldoc -f chomp` Hinweise, wie sich daß Verhalten von chomp beeinflussen läßt. Du könntest auch einem String in der Variable $line mit $line =~ s/[\r\n]+$//; von allen Carriage-Returns und Linefeeds am Ende befreien, egal, in welcher Anzahl und Reihenfolge die da stehen. Soviel ist wohl meist nicht nötig, und $line =~ s/\r?\n$//; reicht, um am Zeilenende ein Linefeed und -- falls vorhanden -- ein vorangestelltes Carriage-Return zu entfernen. Die etwas sauberere Variante wäre es, für Deine Kommunikation genau festzulegen, wie ein ein Zeilenumbruch auszusehen hat (z.B. genau ein Linefeed), und dann in allen beteiligten Programmen sicherzustellen, daß (unabhängig von der jeweiligen Plattform) genau diese Darstellung auch verwendet wird. Übrigens verwenden etliche textbasierte Protokolle (z.B. auch HTTP, SMTP und NNTP) tatsächlich die Kombination von Carriage-Return und Linefeed als Zeilentrenner. Eilert -- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Eilert Brinkmann -- Universitaet Bremen -- FB 3, Informatik eilert@informatik.uni-bremen.de - eilert@tzi.org http://www.informatik.uni-bremen.de/~eilert/
Hallo Eilert, Am Donnerstag, 20. Juni 2002 21:07 schrieb Eilert Brinkmann:
Also mache ich noch ein "chop" hinterher, jetzt funktioniert das ganze. Aber was hängt denn da nun eigentlich für ein Steuerzeichen hinter?
Falls obige Vermutung zutrifft, läßt das chomp natürlich noch ein "\r" am Ende des Strings übrig. Mit dem zusätzlichen chop wird dieses entfernt -- aber das Funktioniert mehr "zufällig" (eben weil's das letzte Zeichen ist), ist aber keine besonders saubere und robuste Lösung.
Nach "\r" habe ich natürlich noch nicht gesucht, "\0" ist es nicht. So ganz bin ich auf java.sun.com noch nicht fündig geworden, scheinbar wird aber kein "\n" angehängt, das hab' ich Dusel selbst in Java angefügt. Das komische an der Lösung von mir ist, daß ich in Java " \n"(mit einem Leerzeichen vor!) anhänge und mit chomp & chop wieder entferne. Lasse ich " \n" weg funktioniert es trotzdem nicht korrekt. Zum testen lasse ich das erstmal so, werde morgen mal die Klassen posten, vielleicht fällt noch etwas auf.
Ist das Sprachübergreifend gleich?
Nein, nicht unbedingt. Sprachen (bzw. zugehörige Bibliotheken) stellen mitunter Hilfsmittel zum Lesen oder Schreiben von Textzeilen zur Verfügung. Die genauen Eigenschaften dieser Hilfmittel sollte man jeweils in der Dokumentation nachlesen, denn da kann es durchaus feine Unterschiede geben -- nicht nur zwischen verschiedenen Sprachen, sondern vor allem auch bei der gleichen Sprache auf unterschiedlichen Plattformen.
Ja, Windows Client, Server Linux... Da könnte auch noch etwas verschieden sein, aber die Doku zu Win9x ist ja so bescheiden :))
auch verfügbar sein. Der Programmierer wird so dabei unterstützt, die in der jeweiligen Umgebung üblichen Konventionen einzuhalten.
Jo, das muß jedenfall noch was _besser_ machen. Ist ja später für die Produktion.
festlegt. Man kann natürlich auch bewußt bestimmte Spielräume lassen und fordern, daß der Empfänger mit allen Varianten klarkommen muß.
Nee, das beibt mir zum Glück erspart...
In Deinem Fall könntest Du z.B. sagen, daß der Empfänger verschiedene Darstellungen des Zeilenendes handhaben können muß. Für die Realisierung in perl gibt `perldoc -f chomp` Hinweise, wie sich daß Verhalten von chomp beeinflussen läßt. Du könntest auch einem String in der Variable $line mit
$line =~ s/[\r\n]+$//;
von allen Carriage-Returns und Linefeeds am Ende befreien, egal, in welcher Anzahl und Reihenfolge die da stehen. Soviel ist wohl meist nicht nötig, und
$line =~ s/\r?\n$//;
reicht, um am Zeilenende ein Linefeed und -- falls vorhanden -- ein vorangestelltes Carriage-Return zu entfernen.
Ich denke, ich werde chomp & chop sein lassen und das ganze mit regex machen, so werde ich auch sehen was da nun dran hängt.
Die etwas sauberere Variante wäre es, für Deine Kommunikation genau festzulegen, wie ein ein Zeilenumbruch auszusehen hat (z.B. genau ein Linefeed), und dann in allen beteiligten Programmen sicherzustellen, daß (unabhängig von der jeweiligen Plattform) genau diese Darstellung auch verwendet wird.
Ja, das werde ich so machen, leider hatte ich nicht soviel Zeit auf der Arbeit das sauber zu machen. Zu meinem Leidwesen ist das meinem Chef egal, sein Motto: ---> Hauptsache funktioniert <--- Ich kann das jedenfalls nicht meinem Gewissen vereinbaren.
Übrigens verwenden etliche textbasierte Protokolle (z.B. auch HTTP, SMTP und NNTP) tatsächlich die Kombination von Carriage-Return und Linefeed als Zeilentrenner.
Am liebsten würde ich das binär machen, oder sogar verschlüsseln. Wegen der Sicherheit, wird meinem Chef aber zulange dauern ;(( Mal was anderes, ich habe auf meinem Linux ein Paket "libnet". Gibt es dazu ein Gegenstück für C++, oder kann ich libnet ruhig nehmen. Den Server würde ich gerne für zuhause in C++ machen :)) Dank' nochmal... CIao Andre
participants (3)
-
Andre Heine
-
Eilert Brinkmann
-
Remo Behn