Implementacja modelu Comet

Implementacja modelu Comet
Riddle
Administrator
  • Rejestracja:prawie 15 lat
  • Ostatnio:około 17 godzin
  • Lokalizacja:Koszalin
  • Postów:10094
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.

  • scr.jpg (195 KB) - ściągnięć: 159
edytowany 3x, ostatnio: Riddle
K3
  • Rejestracja:ponad 11 lat
  • Ostatnio:około 11 lat
  • Postów:43
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 :)

Riddle
Administrator
  • Rejestracja:prawie 15 lat
  • Ostatnio:około 17 godzin
  • Lokalizacja:Koszalin
  • Postów:10094
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ć.

K3
  • Rejestracja:ponad 11 lat
  • Ostatnio:około 11 lat
  • Postów:43
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

Kopiuj
<?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:

Kopiuj

<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).

Riddle
Wielkie dzięki!!
MI
Jesli mialbym sie do czegos przyczepic to uzycie 'success' jest od ktorejs tam wersji jq deprecated i teraz uzywa sie 'done' na zasadzie method chainingu
K3
nie, nie jest :) z manuala jQuery odnośnie done: An alternative construct to the success callback option. Trzeba odróżnić callback "success" podawany w obiekcie z parametrami, od metody "success" obiektu jqXHR, zwracanego przez $.ajax(). Czyli moja konstrukcja nie jest deprecated, taka: $.ajax(options).success(function(){}) - jest. Ale sam to doczytałem dopiero teraz, bo mnie zastanowiłeś tym komentarzem.
Riddle
Administrator
  • Rejestracja:prawie 15 lat
  • Ostatnio:około 17 godzin
  • Lokalizacja:Koszalin
  • Postów:10094
0

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

Kopiuj
function doResuest() {
        $.ajax(
        {
            url: 'backend.php',
            success: function(response) {
                if (response.length > 2) {
                    alert(response);
                }
                doResuest();
            }
        }
        );
    }
K3
jasne, można :) chciałem wyraźniej pokazać że w obu przypadkach wywołujemy ponownie tę funkcję po prostu.
Riddle
Administrator
  • Rejestracja:prawie 15 lat
  • Ostatnio:około 17 godzin
  • Lokalizacja:Koszalin
  • Postów:10094
0

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

K3
  • Rejestracja:ponad 11 lat
  • Ostatnio:około 11 lat
  • Postów:43
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.

Riddle
ok, dzięki za wytłumaczenie :) tak właśnie myślałem że poza pętlą jest useless.

Zarejestruj się i dołącz do największej społeczności programistów w Polsce.

Otrzymaj wsparcie, dziel się wiedzą i rozwijaj swoje umiejętności z najlepszymi.