Frage zum Unterschied dieser beiden Codeschippsel...

Hallo,
ich bin neu in der Arduino-Welt und hätte eine Verständnisfrage zu folgenden Codeschnippseln:

         //diese Variante funktioniert nicht im IE, dafür aber in Firefox, Chrome, Safari...
          client.println("HTTP/1.1 401 Authorization Required");  
          client.println("Content-Type: text/html");  
          client.println("WWW-Authenticate: Basic realm=\"Test\"");
          client.println();
          client.println("<HTML><HEAD><TITLE>Error</TITLE></HEAD><BODY><H1>401 Unauthorized.</H1></BODY></HTML>");


          //diese Variante funktioniert mit allen Browsern...
          //client.write("HTTP/1.1 401 Authorization Required\r\nContent-Type: text/html\r\nWWW-Authenticate: Basic realm=\"Test\"\r\n\r\n");
          //client.write("<HTML><HEAD><TITLE>Error</TITLE></HEAD><BODY><H1>401 Unauthorized.</H1></BODY></HTML>\r\n\r\n");

Was ist der Unterschied zwischen den beiden Schreibweisen?

Ich hänge als Anhang mal den kompletten Sketch an.

Vielen Dank für Eure Hilfe.
MfG paulinchen

passwort.ino (3.2 KB)

Die bewirken das gleiche.
Beim zeiten werden Zeilenumbrüche durch \n erzeugt.
Beim ersten wird das ausführlich ausgeschrieben.

Addi

Der Unterschied liegt darin, dass die write()-Methode den ihr übergebenen Byte-Array nach Möglichkeit in einem Paket ausgibt. Die println()-Methode ist aber so implementiert, dass für jedes Byte die write()-Methode einzeln aufgerufen wird. Somit wird pro TCP/IP-Paket nur ein Byte effektiver Daten übertragen. In Deinem Beispiel fast 200 Pakete übertragen werden. Was natürlich höchst ineffizient ist. Die print() bzw. println()-Methoden sind zwar sehr angenehm zu benutzen, aber nicht wirklich für schlaue Anwendungen zu empfehlen. Man kann jetzt vortrefflich darüber streiten, ob die Print-Klasse oder die write()-Methode der Ethernet-Klasse unschön implementiert ist.

Nach den gültigen Standards müsste ein Browser die Daten aus den verschiedenen Paketen problemlos zusammensetzen können, aber der IE hat die Bezeichnung Browser ja auch nicht wirklich verdient :slight_smile:

Hallo pylon,
vielen Dank für Deine Antwort.

Das bedeutet, daß man bei der Implementierung eines Webservers generell nur client.write() nutzen sollte, oder?

MfG paulinchen

paulinchen:
Was ist der Unterschied zwischen den beiden Schreibweisen?

Das "println" hängt nur ein Linefeed Steuerzeichen "\n" an den String dran.

Das ist zwar legal, um die Zeilen im HTTP-Header zu trennen und auch und die Zeilen in der HTTP-Message zu trennen, aber es ist gemäss HTTP-Standard nicht legal, um die Header-Response von Body der Message zu trennen.

Siehe HTTP-Normung beim W3C:
http://www.w3.org/Protocols/rfc2616/rfc2616-sec6.html

Header und Body werden mit zweimal hintereinander CRLF ("\r\n") voneinander getrennt, wenn es HTTP-standardkonform sein soll.

Deine erste Version sendet das Steuerzeichen CR ("\r") aber überhaupt nicht, weil println das nicht als Zeilenende-Zeichen mitsendet.

Der wesentliche Unterschied auf den es ankommt ist das "\r\n\r\n" am Ende der Zeile:

... WWW-Authenticate: Basic realm="Test"\r\n\r\n");

Das ist der standardkonforme Trenner zwischen HTTP-Header und HTTP-Message.

So ganz generell würde ich dem nicht zustimmen, aber wenn Du Wert darauf legst, dass das sich nicht an Standards haltende Ding von Microsoft auch zugreifen können soll, wirst Du wahrscheinlich nicht darum herum kommen.

Die Print-Klasse hat aber durchaus auch ihre Vorzüge. z.B. kannst Du dort einfach das F()-Macro verwenden und sparst dadurch viel RAM ein. Das mit vernünftigem write()-Aufruf abzubilden macht Kompromisse nötig.

@jurs: println() hängt ein "\r\n" an das Argument an (und nicht nur ein "\n"), aber es ruft eben die write()-Methode byte-weise auf.

Ja, momentan nutze ich client.println(F("textstring"));

Aber mit Hilfe der Flash-library könnte ich ja Flash-strings definieren und diese dann mit client.write() nutzen...

Ich werde dann wohl mal mein Programm umstellen...

Vielen Dank an alle.
MfG paulinchen

Aber mit Hilfe der Flash-library könnte ich ja Flash-strings definieren und diese dann mit client.write() nutzen...

Ich weiss nicht, welche Flash-Library Du meinst, aber so einfach dürfte das nicht werden. Wenn Du die Strings des F()-Macros meinst, die kannst Du nicht direkt per write() ausgeben.

Hallo,
ich definiere halt die Flash-strings im PROGMEM:

FLASH_STRING(FS_404_Header, "HTTP/1.1 404 Not Found\r\nContent-Type: text/html\r\n\r\n");

und im Programmablauf kopiere ich diese dann bei Bedarf ins RAM:

FS_404_Header.copy(my_flash_buf);

und sende sie an den client:

MyClient.write(my_flash_buf);

Funktioniert prima.
MfG paulinchen