[Ajax lub ASP] Odświeżenie strony bez wysyłania do serwera

0

Cześć, już mówię o co chodzi. Tworzę serwis w technologii ASP .NET

I teraz mam problem, bo nie wiem ani jaką technologią się posłużyć, ani jak rozwiązać jedną kwestię.

Otóż załóżmy, że mamy iluś klientów oglądających stronę i serwer.
Klient A wpisuje jakiś komentarz(do konta klienta B) i wciska przycisk "WYŚLIJ" tym samym wysyłając odpowiednie dane do serwera. Następnie serwer ma dać znać wszystkim przeglądającym klientom, że zawartość się zmieniła i pokazać nowy komentarz - bez przeładowania strony.

Widziałem takie cuda na niektórych serwisach, ale nie mam pojęcia jak za to się zabrać. Wiecie?

0

Posłuż się obiektem AJAX i wysyłaj żądanie co kilka sekund do serwera, przy czym walisz do niego: check.php?page=50&lastid=30
Gdzie 50 to numer strony którą przeglądasz, a lastid to ID ostatniego komentarza. Jeśli serwer odpowie "noop" to nic nie robisz, jak odpowie inaczej to zwiększasz ID o jeden w wstawiasz w innerHTML tabelki nowy TR i TD, gdzie leci komentarz.

0
Demonical Monk napisał(a)

Posłuż się obiektem AJAX i wysyłaj żądanie co kilka sekund do serwera,

A inaczej? Bo w taki sposób mając pecha przy 100 użytkownikach mogę zabić serwer.
Poza tym nie ukrywam, że z pewnych względów to musi się wszystko dziać w czasie rzeczywistym, a więc żądanie musiałbym wysyłać najpóźniej co sekundę.

0

Nie wiem jak to jest z tym twoim ASP, ale też się obawiam że to server-side, więc g... zdziałasz. AJAX albo nic. Ew. zrobić plik HTML i cache'ować jakoś w nim konkretne wartości żeby nie zamęczyć serwera. Przykładowo folderek last_comments/ z ostatnią setką komentów. Wtedy AJAX wysyła request do: last_comments/50/30.html, jeśli nie ma to powinien wywalić się błąd 404 (onError), a jeśli jest ok, to w pliku powinna być treść komenta (onSuccess). Jakby przeglądarka umożliwiała stałe połączenie TCP... W każdym razie ja chciałbym napisać sobie komponent ActiveX to takiej działalności i bawić się nim pisząc grę via WWW. Ludzie... jakie to możliwości daje! W każdym razie ty raczej nie będziesz kazał instalować wszystkim jakiś podejrzanych obiektów, żeby mieli ten feature.

0

Ja bym napisał skrypt czekający z odpowiedzią, aż nie pojawi się nowy komentarz i wtedy dopiero wysyłający informacje o komentarzu ( zdarzeniu ).

0

Tylko, że trzeba coś pchać (jakiś noop, ale nie stwarzać zdarzenia domready) bo niektóre przeglądarki to usiedzieć nie potrafią. Przykładowo można przywalić z dziesięć \0 (null) co jakąś minutę i ustawić time limit dla PHP na 0. Tylko że wtedy serwer z kolei może się zesrać na max. ilości równoległych połączeń keep-alive ;)

0

Jest sposób na to, ale nie jest prosty do wykonania.

Klient od razu wysyła zapytanie AJAX do serwera. Serwer ( w tejże metodzie) odpala wątek, który śpi (z ustawionym Timeout na 30 sekund) i nasłuchuje czy jest nowy komentarz. Jeśli przyjdzie - wątek się kończy, a sewer zwraca nowy komentarz. Klient od razu ładuje nowe zapytanie AJAX, które znowu odpala wątek. Nowe zapytanie leci też w przypadku Timeout'a.

W ten sposób każdy nowy komentarz pojawi się natychmiastowo! u wszystkich oglądających.

0

Deti, możesz bardziej szczegółowo albo dać jakieś linki lub zagadnienia?

0
@set_time_limit(0);
$lastid = $_GET['lastid']; //Ostatni ID komentarza, jaki mamy.
$id = $_GET['news_id']; //ID sprawdzanego newsa

function sprawdz() {
global $lastid;
global $id;
$query = mysql_query('SELECT * FROM komentarze WHERE news_id = ' . $id . ' AND comment_id > ' . $lastid . ' ORDER by time DESC');
  while ($row = @mysql_fetch_array($query)) {
     echo('<tr>'.$row['tresc'].'</tr>');
  }
  if (@mysql_num_rows($query) > 0) {
     exit();
  }
}

for($i=0; $i<9999; $i++) { //Sprawdzamy w pętli
  $i = 1; //Pętla nigdy się nie skończy...
  sprawdz(); //... chyba że funkcja zwróci exit(), jeśli znajdzie jakieś komentarze.
}

Zainspirowałeś mnie Deti. Zastosuję to w mojej grze AJAX i będę miał rekordowy czas synchronizacji na arenie silników Open-Source.

0

Nie lepiej

@set_time_limit(0);
$lastid = $_GET['lastid']; //Ostatni ID komentarza, jaki mamy.
$id = $_GET['news_id']; //ID sprawdzanego newsa

function sprawdz() {
global $lastid;
global $id;
$query = mysql_query('SELECT * FROM komentarze WHERE news_id = ' . $id . ' AND comment_id > ' . $lastid . ' ORDER by time DESC');
  while ($row = @mysql_fetch_array($query)) {
     echo('<tr>'.$row['tresc'].'</tr>');
  }
  if (@mysql_num_rows($query) > 0) {
     exit();
  }
}

while(true) { //nieskończona pętla
  sprawdz(); //... chyba że funkcja zwróci exit(), jeśli znajdzie jakieś komentarze.
  sleep(5); // pięć sekund czasu zwolnione dla innych procesów
}

// EDIT poprawiony trochę kod, ale i tak do optymalizacji.

0

taak, i w ten sposób zasracie serwery http i bazy danych. nie dość, że kilkadziesiąt i więcej naraz przetwarzanych requestów wydoi całą pamięć z serwera, to pętla while bez żadnego sleepa w środku zużyje 100% procesora (co prawda samo zapytanie będzie działać jako sleep, ale wtedy baza danych będzie kontynuować obciążanie procesora), a ciągłe zapytania do bazy danych zamordują także i ją; a jeśli baza danych stoi na osobnym serwerze, to jeszcze i przytkacie nieco sieć (aczkolwiek w dobie gigabitowych sieci lan to chyba będzie najmniejszy problem).
imho pomysł ciekawy, ale tylko do bardzo specyficznych zastosowań i tylko po solidnej optymalizacji.

0

taak, i w ten sposób zasracie serwery http i bazy danych. nie dość, że kilkadziesiąt i więcej naraz przetwarzanych requestów wydoi całą pamięć z serwera, to pętla while bez żadnego sleepa w środku zużyje 100% procesora (co prawda samo zapytanie będzie działać jako sleep, ale wtedy baza danych będzie kontynuować obciążanie procesora), a ciągłe zapytania do bazy danych zamordują także i ją; a jeśli baza danych stoi na osobnym serwerze, to jeszcze i przytkacie nieco sieć (aczkolwiek w dobie gigabitowych sieci lan to chyba będzie najmniejszy problem).
imho pomysł ciekawy, ale tylko do bardzo specyficznych zastosowań i tylko po solidnej optymalizacji.

Muszę sprostować.

Bynajmniej nie miałem na myśli ciągłego zapytywania bazy danych w wątku. Wątek czeka grzecznie, ale praktycznie nie robi nic - do momentu, aż dostanie notyfikację. Notyfikacja musi być obsługiwana przez warstwę biznesową (nie wiem jak to zrobić w php - nie znam tego języka), widziałem świetnie działające implementacje w .NET.

To właśnie warstwa pośrednia (czyli praktycznie kod serwisu) jest odpowiedzialny za wysłanie notyfikacji : dodano komentarz pod obrazkiem numer xxxx" (pseudo). Zainteresowane wątki sprawdzą sobie, czy interesuje ich obrazek xxxx, wtedy kończą wątek i nowy komentarz wraca do klienta. Ten znowu odpala zapytanie....

Tak więc wątek nie robi praktycznie nic, do momentu notyfikacji lub timeoutu (żadnego ciągłego czytania w bazie lub co jakiś interval!). Notyfikację można zrealizować przez wewnętrzny event w serwisie wysyłany w razie potrzeby. W naszym przykładzie - będzie to moment dodania nowego komentarza - dodajemy event, które notyfikuje zainteresowane komponenty, że dodano nowy komentarz (wraz z informacją kto, gdzie, co).

Dodatkowo, każdą notyfikację należy opatrzyć w unikalny numer, inkrementowany za każdym razem. W ten sposób wątki będą mogły ustalić dolny zakres notyfikacji, jakie chcą otrzymywać. Dzięki temu, nie stracimy żadnej notyfikacji w czasie, gdy klient wykonał "przerwanie".

0

Zróbcie ludzie zserializowaną bazę, w której będzie lastID komentarza dla każdego newsa/artu i zmieniajcie ją tylko wtedy jak ktoś doda komentarz. Na początku oferowałem też te pliki HTML, w każdym razie dla każdego można znaleźć coś fajnego i nie róbmy z tego tragedii obsługiwanej przez Perla, .Net i PHP jednocześnie...
W bazie zserializowanej pojawiło się nowe lastID komenta? Nie posiadasz go? Serwer więc wysyła Ci to, czego potrzebujesz w formie:

nick---komentarz---data---id

I tak kończy Ci się limit połączeń Keep Alive, a twój serwer pada na ryj, identycznie jak we wszystkich poprzednich przypadkach. ;)

0

Przepraszam za swoją zuchwałość, ale gdzie ja pisałem coś o PHP? :)
Nie interesuje mnie w ogóle PHP, tylko ASP .NET(C#) i, jak już ktoś raczył powiedzieć AJAX.
Ale jak na razie wiem tyle samo, ile przed napisaniem tego wątku :)

// toć odpowiedź padła .. ze szczegółami [???] - deti
// i jaka różnica, PHP czy ASP, przecież metoda identyczna, a rozważania w ogóle czysto teoretyczne - Ł

0

No właśnie ;) Tyle że sobie inaczej zakodujesz rozwiązanie w ASP. Jakoś magicznie z serwerem się nie można połączyć i myślę że serwer-side nie różni się tak bardzo, kiedy tworzy się strony w języku koncernu M$.

0

Nie ma więcej odpowiedzi na dzień dzisiejszy .. postanowiłem więc zabrać się za to, co wcześniej opisywałem.

Potrzebuje chętnych, którzy chcieliby współpracować i napisać.. część kliencką - czyli klasę w Javascripcie :-) (którego nienawidzę...)

Może znajdą się tacy? ... kod C# już mam prawie gotowy (wersja uboga, ale działa...)

0

Ich liebe shaisse!

Czyli jednak zdecydowałeś się zasrać cały serwer HTTPD durnymi pytaniami? Mógłbym coś naskrobać łatwego bo silnik gry 2D w PHP, HTML, AJAX robie równolegle (wytnie się z tamtąd)

0

Myślę, że zacznę od aplikacji - czat (oczywiście na samym JS + mój "framework"). Powinno śmigać, serwer zdaje się być niewzruszony. Wystawie kod za kilka dni.

0

Więc dobrze. Jak nabazgrasz kod klienta ja zrobię na razie prościutką klasę (tylko odbieranie wiadomości i deserializacja).

Właśnie... JSON lepiej się deserializuje niż różne prowizorki. Mógłbyś info wysyłane do klienta serializować w taki właśnie sposób?

0

Tak, operuje na JSON'nie.

Napisałem klasę dla klienta, jednak coś nie do końca działa :-/

Założenia zgodnie z tym co napisałem - oczekiwanie na timeout.

  1. Pierwszy request - klient otrzymuje ID i liczbę "lookup"
  2. Drugi request wysyła (już ze swoimi danymi). Czeka grzecznie na odpowiedź (tzw. "Timeout" jako pakiet.. nie prawdziwy timeout)
  3. Timeout przychodzi, wysyła natychmiast drugi request
  4. Czeka, i znowu timeout (zgodnie z założeniami!)... jednak nie widzi już odpowiedzi serwera .. nie wiem, czy ja coś źle zrobiłem czy co?..
  • sprawdziłem serwer, tam wszystko działa, odpowiedź idzie do klienta - coś zatem musi być nie tak z moim Javascriptem :-/

Oto kod klasy (jeszcze w fazie eksperymentalnej..)
http://paste.bradleygill.com/index.php?paste_id=9506

.. A tu link do mojej strony z opisem (plus pełny kod serwera do zassania): http://tinyurl.com/q7wbok

0

Dla zainteresowanych: wystawiłem testową stronę : http://aspspider.info/DetoX/sync.aspx

Na razie działa tylko dla Firefox!

Polecam sprawdzenie w kilku otwartych okienkach firefoxa.

Przydałyby się jakieś testy manualne :-)

0

Ja robie od nowa swoją wersję, potem zrobimy kompromis między rozwiązaniami.

0

Trochę wolno chodzi ale to wina serwera który ma na ps auxie koło 30 otwartych połączeń w jednej sekundzie z różnych skryptów.

http://nockruka.gram.pl/aurora/
Komenda /nick dostępna

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