Implementacja modelu Comet

0

Witam,

mam ambicję na stworzenie aplikacji - gry internetowej. Zwykła prosta planszówka, gra się w nią w dwie osoby. Niby działa, ale na takiej zasadzie że skrypt odpytuje server co kilka sekund czy nic się nie zmieniło - jeżeli tak: server wysyła informacje o ruchach itp.

Chciałbym zrobić to na takiej zasadzie że do gry dociera coś wtedy kiedy faktycznie coś się zmienia, żeby nie było niepotrzebnego ruchu w sieci. Znalazłem informację o czymś takim jak Comet. Jako że pierwsze słyszę - poczytałem teorię, ściągnąłem jakieś proste demo z :
http://jsjoy.com/blog/197/simple-php-comet-example
oraz
http://www.zeitoun.net/articles/comet_and_php/start
wgrałem na server ftp, włączam - nic się nie dzieje. Strona się wczytuje (długo, pewnie przez to że plik php ma nieskończoną pętlę), nagle przestaje się wczytywać. Jest jeden napis, który się nie zmienia. Nie tak to powinno działać :/

Podpatrzyłem kod pod Chrome Developer Tools, nie wiem co się mogło stać. Sprawdzałem nazwy plików i czy nie ma jakichś literówek.
W chrome dev tools zmieniłem styl tej iframe tak żeby była widoczna, nie miała ujemnych left i top, i żeby miała wymiary na 600x400. Okazało się po jakimś czasie że jest tam : scr.jpg

I już nie wiem co mogę zrobić, żeby zobaczyć czy to faktycznie działa tak jak chcę i w ogóle mieć jakąś basic implementację żeby przepisać kod odpowiedzialny za wymienianie informacji o ruchach w grze.

0

Nie masz czasem włączonego jakiegoś gzipowania albo buforowania wyścia? Pokaż/wrzuć plik backend.php, spróbuję odpalić go u siebie i zobaczymy co z tego wyniknie.
A inny pomysł - próbowałeś ze skryptem po stronie serwera, który sprawdzałby (w pętli) czy nie nastąpił ruch drugiego gracza, ale z limitem czasowym? tzn nie chodzący w nieskończonej pętli, tylko takiej która po 20 sekundach się skończy (jeśli natrafi na ruch drugiego gracza oczywiście powinien kończyć się z odpowiednią informacją od razu). A po stronie klienckiej sprawdzanie i ponawianie wywołania co np. 20 sekund? wtedy po pierwsze miałbyś informację o ruchu niemal natychmiast (a nie dopiero po kilku sekundach jak w Twoim pierwszym rozwiązaniu), po drugie Twój skrypt byłby odporny na wszelkie timeouty (bo zazwyczaj PHP ma 30 sekund na wykonanie skryptu), a po trzecie nie byłoby dużo zbędnego ruchu- request co 20 sekund to tylko trzy na minutę, więc IMO - good enough :)

0

Plik "backend.php" jest żywcem skopiowany z ze stron które podałem w linkach. W każdym z tych linków jest inne rozwiązanie, ale oba nie działają u mnie :/

Co do Twojej propozycji, opisał byś ją dokładniej? :) Nie do końca rozumiem, a chciałbym się jej przyjrzeć.

1

Mam nadzieję że nie zepsuję Ci zabawy wrzucając po prostu kod który realizuje to założenie... łatwiej ubrać to w PHP i JS niż w słowa :P

backend.php

<?php
header("Cache-Control: no-cache, must-revalidate");
header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
$startTime = time();
$maxLoopTime = 20;
$lastMinute = date('i'); 
while(time()-$startTime < $maxLoopTime) {
	sleep(1);//żeby nie robić 100% loada na serwerze
	if ($lastMinute != date('i')) {//zmieniła się minuta na serwerze
		echo date('Y-m-d h:i:s');
		die();
	}
}
die();

i index.php:


<html>
<head>
	<script src="http://code.jquery.com/jquery-1.11.0.min.js"></script>
	<meta charset="utf-8">
</head>
<body>
<p>Dokładnie co minutę pokaże się alert z bieżącym czasem serwera</p>
<script type="text/javascript">
	function doResuest() {
		$.ajax(
		{
			url: 'backend.php',
			success: function(response) {
				if (response.length > 2) {
					alert(response);
					doResuest();
				} else {
					doResuest();
				}
			}
		}
		);
	}
	$(function() {
		doResuest();
	});
	
</script>
</body>
</html>

JSowa funkcja doRequest sprawdza czy odpowiedź od serwera zawiera treść, i jeśli tak - obsługuje zdarzenie (w moim przypadku po prostu alertem).

0

Rozumiem że można byłoby też to zapisać tak: ??

function doResuest() {
        $.ajax(
        {
            url: 'backend.php',
            success: function(response) {
                if (response.length > 2) {
                    alert(response);
                }
                doResuest();
            }
        }
        );
    }
0

A właściwie to po co jest to die(); w pętli i poza nią?

0

Poza - zupełnie niepotrzebnie, bo skrypt i tak by się tam skończył. Zapomniałem po prostu skasować ;)
a w pętli po to żeby zaraz po wystąpieniu zdarzenia (czyli zmianie daty) działanie skryptu się zakończyło i klient odebrał informację. Spróbuj sobie to odpalić bez die w pętli, zobaczysz (podejrzyj np. firebugiem) że wtedy każdy request będzie wisiał na 'pending' przez 20 sekund nawet jeśli zdarzenie na serwerze wystąpi wcześniej.

1 użytkowników online, w tym zalogowanych: 0, gości: 1