Hallo,
Die bessere Lösung ist, ein Protokoll zu nutzen, bei dem der Server von sich aus neue Daten an den Client sendet, sobald welche vorliegen. Dazu braucht es aber auch eine clientseitig laufende Software, die auf diese Daten reagiert. Ein normaler Browser würde das nicht tun. Die Lösung könnte ein Java-Applet oder ein Flash-Objekt sein - oder eben ein spezielles Programm wie ein "richtiger" Chat-Client.
Hmm, eigentlich möchte ich weder Flash noch Java-Applets in meine Seite einbauen. Die Lösung von Manuel habe ich mal in einer Demo getestet, jedoch ist sie, wie du bereits sagtest, eher suboptimal.
Ich habe mir mal den HTTP-Chat der Seite www.freewar.de angeschaut, da ich diesen recht gut implementiert respektive umgesetzt finde und die Seite, genau wie meine, auf PHP und JavaScript zurückgreift. Leider verstehe ich den Source nicht so ganz, aber vielleicht könnt ihr ihn mir ja erklären :-)
Also der Aufbau des Framesets wird folgendermaßen bewerkstelligt:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Frameset//EN" "http://www.w3.org/TR/html4/frameset.dtd">
<html>
<head>
<title>Freewar.de - Welt 3</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<script>if(ProxSuccessStartCode) { document.location.href='frset.php?uclocal=1'; }</script></head>
<frameset rows="*" cols="*,280" framespacing="0" frameborder="no" border="0">
<frameset rows="*,200" cols="*" framespacing="0" frameborder="NO" border="0">
<frameset rows="75,*" cols="*" framespacing="0" frameborder="NO" border="0">
<frame src="banner.php" name="bannerFrame" scrolling="NO">
<frame src="main.php" name="mainFrame" scrolling="auto">
</frameset>
<frameset rows="*,0" cols="*" framespacing="0" frameborder="NO" border="0">
<frameset rows="*,35" cols="*" framespacing="0" frameborder="NO" border="0">
<frame src="chattext.php#bancor" name="chattextFrame" frameborder="no" scrolling="auto" noresize>
<frame src="chatform.php" name="chatformFrame" scrolling="NO" noresize>
</frameset>
<frameset rows="*,0" cols="*" framespacing="0" frameborder="NO" border="0">
<frame src="refresh.php" name="reloadChatFrame" scrolling="NO" noresize>
<frame src="chatupdate.php" name="chatupdateFrame" scrolling="NO" noresize>
</frameset>
</frameset>
</frameset>
<frameset rows="*,375" cols="*" framespacing="0" frameborder="NO" border="0">
<frame src="item.php" name="itemFrame" frameborder="no" scrolling="auto" noresize>
<frameset rows="*,50" cols="*" framespacing="0" frameborder="NO" border="0">
<frame src="map.php" name="mapFrame" scrolling="NO" noresize>
<frame src="menu.php" name="menuFrame" scrolling="NO" noresize>
</frameset>
</frameset>
</frameset>
<noframes><body>
Sie muessen einen Broswer verwenden der Frames unterstuetzt um FreeWar zu spielen.
</body></noframes>
</html>
Die für den Chat relevanten Frames sind offensichtlich chattextFrame, chatformFrame, reloadChatFrame und chatupdateFrame, wobei für das Update der Anzeige scheinbar die beiden letzteren verantwortlich sind.
Den Code dieser Seiten habe ich mir mal angeschaut (zumindest das, was der Server mir von den PHP-Files ausliefert):
Frame: reloadChatFrame (Datei refresh.php):
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>Unbenanntes Dokument</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
</head>
<body onLoad="init();">
[code lang=javascript]
<script language="JavaScript">
function getHTTPObject()
{
var xmlhttp;
try
{
xmlhttp = window.XMLHttpRequest ? new XMLHttpRequest() : new ActiveXObject("Microsoft.XMLHTTP");
}
catch (e)
{
alert('ActiveX Elemente wurden im Browser deaktiviert. Bitte aktiviere ActiveX in den Sicherheitseinstellungen deines Browsers. Folgendes muss z.B. im Internet Explorer aktiviert sein: Extras->Internetoptionen->Sicherheit->Stufe anpassen->ActiveX-Steuerelemente ausführen, die für Scripting sicher sind - aktivieren.');
}
return xmlhttp;
}
var httpReloadChat = getHTTPObject();
function init()
{
pollStatus();
}
function pollStatus()
{
if(httpReloadChat.readyState == 4 || httpReloadChat.readyState == 0)
{
var ran_unrounded=Math.random()*100000000;
var ran_number=Math.round(ran_unrounded);
httpReloadChat.open("GET",'rel_files/47963.htm?dynamicid='+ran_number, true);
httpReloadChat.onreadystatechange = handleChatReload;
httpReloadChat.send(null);
}
}
function handleChatReload()
{
if(httpReloadChat.readyState == 4)
{
window.setTimeout('pollStatus()', 1500);
if(httpReloadChat.responseText.length==1)
{
parent.chatupdateFrame.location.href = "chatupdate.php";
}
}
}
</script>
</body>
</html>
[/code]
Frame: chatupdateFrame (Datei chatupdate.php, beim Anschauen des Sources übrigens geladen per chatupdate.php?stoperror=1)
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>Unbenanntes Dokument</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
</head>
<body>
[code lang=javascript]
var IE = document.all ? 1:0;
parent.chattextFrame.add('', 0);
if (IE)
{
if(parent.mainFrame.formular.block_reload.value != 'true')
parent.mainFrame.location.href = 'main.php';
}
else
{
if(parent.frames.mainFrame.document.formular.block_reload.value != 'true')
parent.frames.mainFrame.location.href = 'main.php';
}
</script>
</body>
</html>
[/code]
Also so wie ich das sehe, ist die Datei chatupdate.php dafür zuständig, das eigentliche Chat-Fenster neu zu laden, sobald chatupdate.php selbst neu geladen wird (der Umweg über chatupdate.php zum Laden von main.php anstatt direkt main.php neu zu laden, scheint darin begründet, dass man zwischen Browsern unterscheiden kann und das Neuladen auch unterbinden kann). Dieser Source ist relativ einfach zu verstehen.
Mehr Probleme bereitet mir die Datei refresh.php:
Wenn ich es richtig verstehe, stellt bei Nicht-IE-Browsern die Variable httpReloadChat eine Referenz auf ein XMLHttpRequest-Objekt und bei IE-Browser eine auf ein ActiveXObject dar (implementiert in der Funktion getHTTPObject). Danach scheint das Prinzip in etwa das zu sein, was ich in meinem Eröffnungspost dieses Threads vorgeschlagen habe:
Alle 1,5 Sekunden (siehe Funktion handleChatReload: window.setTimeout('pollStatus()', 1500)) wird in der Funktion pollStatus httpReloadChat mit dem Inhalt der Datei rel_files/47963.htm befüllt (wobei der Name der zu lesenden Datei wahrscheinlich mit PHP immer wieder verändert wird). Der Sinn der generierten DynamicID entzieht sich mir leider, was das Verständnis des Codes erschwert. Jedenfalls enthält die Datei rel_files/47963.htm eine 1 als Inhalt, wenn man sie ohne jegliche Parameter mit dem Browser öffnet. Damit hätte der Inhalt von httpReloadChat die Länge 1, was die Abfrage im Event-Handler handleChatReload() (if(httpReloadChat.responseText.length==1)) wahr werden ließe- oder von was ist responseText abhängig? Mit httpReloadChat.send(null) wird wohl einfach ein Event für den Event-Handler gefeuert, oder?
Einige Dinge sind mir also noch unklar, wodurch mir eine Implementierung anhand des vorhandenen Source-Codes unmöglich ist. Könnt ihr meine Fragen beantworten (speziell den Sinn der DynamicID und ob ich den Code ansonsten richtig verstanden habe, oder etwas übersehen habe. Ließe sich der Chat so implementieren? Und ist responseText.length tatsächlich abhängig von der Länge des Inhalts der Datei rel_files/47863.htm?) ?
MfG
Fabian
PS:
[...] und der InternetExplorer sein cooles Reload-Klicken bringt ;-) ).
Was für ein Klicken? Habe zwar schon öfter gelesen, dass jemand das erwähnt hat, aber noch nie verstanden, was die Leute wirklich meinen bzw. woher das kommen soll.
Der InternetExplorer hat die nervige Eigenschaft (zumindest habe ich dies schon bei mehreren IE-Usern beobachtet), dass er bei einem Reload einer Seite (also immer dann, wenn die blaue ProgressBar erscheint) so ein “Maus-Klicken” ertönen lässt.