Niezalogowany [ logowanie ]
Subskrybuj kanał ATOM Kanał ATOM

Autor wpisu: cojack, dodany: 15.05.2010 01:51, tagi: apache

Ostatnimi czasy nie mam czasu by tu nawet zajrzeć, kobieta -> praca -> kobieta -> praca i tak w kółko macieju. Siedząc na ircu dużo osób wciąż się pyta jak skonfigurować apache i ustawić vhosty. Jedni polecają userdir mod, mi ten mod w ogóle nie podchodzi. Ja tam sobie będę trzymał dane tam gdzie mi pasuje, i wszystko inne też. Także w poniższym “artykule” pokażę Wam jak w nowym Apache2 wersja. 2.2.14 (teraz taka aktualna jest w ubuntu 10.04). Zakładam że macie już zainstalowanego apache, php, jedno z drugim ślicznie działa i jesteśmy prawie zadowoleni.

Konfiguracja /etc/hosts

Pierwej przed przystąpieniem do pracy i konfiguracji vhostów sprawdźmy sobie ustawienia naszego /etc/hosts, zakładamy że chcemy pracować tylko lokalnie i mieć vhosty dla swojej wygody pracując na lokalnej maszynie. Także edytujmy plik posiadając uprawnienia użytkownika root:

$ sudo su

następnie po wpisaniu hasła edytujemy plik:

$ nano /etc/hosts

I interesują nas pierwsze dwie linijki:

127.0.0.1       localhost.localdomain
127.0.1.1       nazwa-kompa

Tak powinień się nam przedstawiać nasz /etc/hosts, gdzie nazwa-kompa jest nazwą która wyświetli Wam się po wykonaniu polecenia:

$ echo $HOSTNAME

jeżeli tak mniej więcej wygląda Wasz plik hosts to ja proponuje takie rozwiązanie:

127.0.0.1       localhost.localdomain   nazwa-kompa
#127.0.1.1      nazwa-kompa

Jak widać 127.0.1.1 jest zaremowane więc nie jest brane pod uwagę. Czasami jest lepiej coś zaremować niż usuwać.

Na tym zakończymy na razie edycję pliku /etc/hosts

Konfiguracja vhosta

Przechodząc do edycji vhosta na samym początku chciałbym poinformować o pewnych zmianach wprowadzanych w ubuntu systematycznie, otóż mamy taki ciekawy program który się nazywa service i nie musimy latać do /etc/init.d/ by robić coś z aktualnie odpalonym deamonem. Czyli np taka komenda:

$ service apache2 restart

da nam to samo co:

Czytaj dalej tutaj (rozwija treść wpisu)
Czytaj dalej na blogu autora...

Autor wpisu: Michał Środek, dodany: 14.05.2010 21:40, tagi: php

Spróbujmy udoskonalić nasz serwer tak aby posiadał możliwości prostego chatu — wysyłanie wiadomości ogólnych do wszystkich użytkowników oraz prywatnych tylko do jednej osoby. Mój kod urósł prawie do 150 linijek przy czym nie uwzględnia on kilku rzeczy, o których wspomnę podczas pisania protokołu lub tworzenia klientów.(w końcu nie piszę MUD-a i telnet muszę zastąpić czymś innym).

Poprawiony kod wygląda tak:

<?php 
set_time_limit(0);
 
class GameClient
{
   public $id;
   private $socket;
 
   public function __construct(&$socket, $id)
   {
      $this->socket = $socket;
      $this->id = $id;
   }
 
   public function sendMessage($message)
   {
      socket_write($this->socket, $message."\n".chr(0));
      echo 'Wysylam wiadomosc do '.$this->id.': '.$message."\n";
   }
 
}
 
class GameServer
{
   private $master;
   private $address; 
   private $port; 
   private $maxClients;
   private $sockets = array();
   private $clients = array();
 
   public function __construct($address = '127.0.0.123', $port=14117, $maxClients = 10)
   {
      $this->address = $address;
      $this->port = $port;
      $this->maxClients = $maxClients;
 
      $this->master = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
      socket_bind($this->master, $this->address, $this->port);
      socket_listen($this->master);
      $this->sockets[] = $this -> master;
 
      while(true)
      {
         $changedSockets = $this->sockets;
         socket_select($changedSockets,$write=null,$exceptions=null,null);
 
         foreach($changedSockets as $socket)
         {
            // zmiana gniazda głównego => nowe polaczenie
            if($socket == $this->master)
            {
               $socket = socket_accept($this->master); 
 
               $this->sockets[] = $socket;
               $id = array_search($socket, $this->sockets);
                $this->clients[] = new GameClient(&$this->sockets[$id], $id);
 
            }
            // zmiana gniazda jednego z klientów
            else
            {
               $input = socket_read($socket, 1024); 
               $input = trim($input," \t\n\r");
 
               if(strlen($input)==0 || $input=='exit')
               {
                  $output = 'Bye bye!'."\n".chr(0); 
 
                  // send data to socket 
                  socket_write($socket, $output);
 
                  $id = array_search($socket, $this->sockets);
                  unset($this->sockets[$id]);
                  unset($this->clients[$id-1]);
 
                  socket_close($socket);
               }
               else
               {
                  $command = (strpos($input,' ')!==false)
                      ? substr($input,0, strpos($input,' '))
                      : $input;
 
                  switch($command)
                  {
                     case 'hello':
                        $output = 'Hello!';
                        break;
                     case 'list':
                        // identyfikatory wszystkich gniazd
                        $all = array_keys($this->sockets);
                         // identyfikator uzytkownika
                        $id = array_search($socket, $this->sockets);
                        // usuniecie ID glownego gniazda oraz gniazda uzytkownika
                        $all = array_diff($all, Array(0, $id));
 
                        if(empty($all))
                           $output='Nie ma innych osob';
                        else
                           $output='ID innych osob to: '.implode(', ',$all);
                        break;
                     default:
                        if(is_numeric($command))
                        {
                           // identyfikator uzytkownika
                           $id = array_search($socket, $this->sockets);
                           // wyslanie wiadomosci do wszystkich
                           if($command=='0')
                           {
                              foreach($this->clients as $client)
                              {
                                 // nie wysylamy do siebie
                                 if($client->id!=$id)
                                    $client->sendMessage(substr($input,strpos($input,' ')+1));
                              }
                              $output = 'Do wszystkich';
                           }
                           // nie wysylamy do siebie, uzytkownik istnieje
                           elseif($command!=$id && isset($this->sockets[$command]))
                           {
                              // jeden mniejszy ponieważ $this->master znajduje sie
                              // w tablicy gniazd a nie jest klientem
                              $this->clients[$command-1]->sendMessage(substr($input,strpos($input,' ')+1));
                              $output = 'OK';
                           }
                           else
                              $output ='Bledny ID'; 
                        }
                        else
                           $output = 'Niezrozumiale polecenie: '.$input.''; 
                  }
                  socket_write($socket, $output."\n".chr(0));
               }
            }
         }
      }
   }
 
   public function __desctruct()
   {
      socket_close($this->master); 
   }
}
 
$gameServer = new GameServer();
?>

Czas na krótką analizę. Pierwsze co rzuca się w oczy to nowa klasa GameClient. Jest to klasa, z którą wiążę pewne plany. Obiekty tej klasy przechowują dwie rzeczy — gniazdo oraz jego identyfikator. Metoda sendMessage() służy do wysyłania wiadomości do użytkownika, który jest podpięty do tego gniazda.

W klasie GameServer pojawiły się dwa nowe pola prywatne, tablica sockets przechowująca wszystkie gniazda dostępne dla serwera oraz tablicę clients przechowującą obiekty klasy GameClient.

Ogólne założenia się nie zmieniły — wciąż istnieje pętla nieskończona jednak jej zawartość została zmodyfikowana.

$changedSockets = $this->sockets;
socket_select($changedSockets,$write=null,$exceptions=null,null);

Użyliśmy tutaj funkcji socket_select(). W parametrach podajemy referencje(dlatego pierwsza linijka jest konieczna) do tablic gniazd, a funkcja pozostawia w nich jedynie te elementy, w których zaszły pewne zdarzenia. Pierwszy parametr odpowiada czy czytanie, czyli wybrane zostaną jedynie te gniazda, które coś przesyłają do serwera. Drugi i trzeci parametr odpowiadają za pisanie oraz wyjątki lecz nas one nie interesują. Ostatni parametr dotyczy limitu czasu oczekiwania na wybranie poszczególnych gniazd. Null oznacza brat limitu czasowego.

Następnie sprawdzamy każde z gniazd z tablicy $changedSockets. Jeśli gniazdo jest tym samym co gniazdo główne serwera oznacza to, że nowy użytkownik chce ustanowić połączenie. Robimy to tworząc nowe gniazdo i dopisując informacje o nim do tablic $this->sockets oraz $this->clients. W przypadku innych gniazd odczytywane są dane przesyłane do serwera.

$input = socket_read($socket, 1024); 
$input = trim($input," \t\n\r");

Używam funkcji trim() aby wyczyścić dane przychodzące do serwera z różnych niepotrzebnych białych znaków.

Pozostały kod to pseudo-protokół chatu. W przypadku przesłania komunikatu pustego lub wiadomości exit połączenie z użytkownikiem jest zrywane. Polecenie hello jest czysto demonstracyjne. W przypadku wpisania list pojawia się lista identyfikatorów innych użytkowników dostępnych aktualnie lub komunikat o ich braku. Wysyłanie komunikatów do innych użytkowników odbywa się w następujący sposób:

Czytaj dalej tutaj (rozwija treść wpisu)
Czytaj dalej na blogu autora...

Autor wpisu: Michał Środek, dodany: 14.05.2010 00:47, tagi: php

Pisząc grę internetową trzeba zastanowić się nad sposobem komunikacji między graczami oraz bazą danych. W przypadku aplikacji przeglądarkowych dużego wyboru nie ma. Praktycznie wszystkie gry wykorzystują technologię AJAX. Jak to działa w praktyce? Nie za dobrze. Spróbujmy stworzyć coś dużo bardziej wydajniejszego.

Sposób działania technologi AJAX

AJAX to rozwiązanie jednostronne. Klient prosi serwer o pewne informacje, a ten je wysyła użytkownikowi. Serwer nie posiada dokładnych informacji na temat ilości aktualnie połączonych użytkowników oraz nie może wysłać do żadnego z nich samodzielnie żadnej informacji(tj. może jedynie odpowiadać na ich zapytania).

Kocham robić te fajne obrazki i choć nie mają one niczego wspólnego z UML-em mam nadzieję, że jesteś w stanie je odczytywać

Przeanalizujmy przykład czatu internetowego w którym mamy trzech użytkowników(Client1, Client2, Client3). Pierwszy z nich chce wysłać informację do trzeciego. Wygląda to następująco:

  • (1) Client1 pyta serwer czy są jakieś wiadomości do niego. Serwer zwraca informację o ich braku.
  • (2) Client2 pyta serwer czy są jakieś wiadomości do niego. Serwer zwraca informację o ich braku.
  • (3) Client3 pyta serwer czy są jakieś wiadomości do niego. Serwer zwraca informację o ich braku.
  • (4) Client1 wysyła do serwera wiadomość przeznaczoną dla użytkownika Client3. Serwer zwraca informację o przyjęciu danych.
  • (4,5) Serwer zapisuje wiadomość do swojego bufora(w tym przykładzie bazy danych)
  • (5) Client2 pyta serwer czy są jakieś wiadomości do niego. Serwer zwraca informację o ich braku.
  • (6) Client3 pyta serwer czy są jakieś wiadomości do niego.
  • (6,5) Serwer odczytuje z bazy danych wiadomość oraz zwraca ją użytkownikowi.
  • (7) Client1 pyta serwer czy są jakieś wiadomości do niego. Serwer zwraca informację o ich braku.
  • (8) Client2 pyta serwer czy są jakieś wiadomości do niego. Serwer zwraca informację o ich braku.
  • (9) Client3 pyta serwer czy są jakieś wiadomości do niego. Serwer zwraca informację o ich braku.
  • (…)

Jak widać wykonywanych jest wiele niepotrzebnych zapytań. Każdy z klientów musi stale wysłać zapytanie do serwera co w przypadku małego czasu może powodować spore zużycie procesora serwera. W sytuacji, gdy czas będzie większy w grze pojawią się lagi. Jak ten problem rozwiązuje się w „normalnych“ grach internetowych? Używane są gniazda.

Jak działają gniazda

Szerokie linie oznaczają nasłuchiwanie serwera oraz klientów

Każdy z klientów musi ustanowić połączenie z serwerem. Serwer dla każdego z nich tworzy gniazdo za pomocą którego w dowolnym momencie może wysłać informację do jednego z użytkowników.

Wygląda to tak:

  • (0) Client1, Client2, Client3 nawiązują połączenie z serwerem(tworzone są gniazda)
  • (1) Client1 wysyła wiadomość do serwera (serwer zwraca komunikat o sukcesie)
  • (2) Serwer odnajduje gniazdo trzeciego użytkownika
  • (3) Serwer wysyła wiadomość do Client3

W odróżnieniu do technologi AJAX w tym przypadku nasz serwer napisany w php musi ciąglę nasłuchiwać, a więc proces tego skryptu musi być cały czas uruchomiony. W tym celu tworzy się pętlę nieskończoną, którą cięgle sprawdza stan gniazda serwera.

Czytaj dalej tutaj (rozwija treść wpisu)
Czytaj dalej na blogu autora...

Autor wpisu: Wojciech Sznapka, dodany: 13.05.2010 23:00, tagi: symfony, php

The sfWidgetFormSelect doesn't provide ability to render disabled options. It's rarely used feature of a HTML select element, but sometimes it could save your life :-) In fact, we can achieve this feature by creating our own widget, which inherits from sfWidgetFormSelect.

Autor wpisu: sokzzuka, dodany: 13.05.2010 14:21, tagi: php

Niejednokrotnie podczas pisania różnych skryptów, mam do czynienia z arytmetyką dat. Tak było również i tym razem, kiedy miałem zaimplementować funkcjonalność polegającą na ograniczeniu oddawania ponownego głosu w sądzie do 24 godzin.

Istnieje kilka rozwiązań tego problemu, pierwszym rozwiązaniem jest odejmowanie timestamp-ów. Nie jest to rozwiązanie zbyt wygodne, ponieważ trzeba ręcznie obliczać ilość sekund etc. Poza tym dochodzą problemy z strefami czasowymi. Może się zdarzyć sytuacja, że PHP ma ustawioną inną strefę czasową niż baza danych i wtedy wychodzą nam jakieś dziwne wyniki.

Jest łatwe rozwiązanie tego problemu, na które ostatnio natknąłem się właśnie przy okazji ww. zadania. Są to MySQL-owe funkcje date_add i date_sub. Przejdźmy więc do przykładów.

Obliczenie daty 5 godzin wcześniej od teraz:

SELECT date_sub(now(),interval 5 hour)

Obliczenie daty miesiąc wcześniej od teraz:

SELECT date_sub(now(),interval 1 month)

Generalnie reguła jest taka, że w drugim argumencie piszemy “interval <liczba> <jednostka>” gdzie liczba jest liczbą całkowitą, natomiast jednostka jest angielską nazwą jednostki daty(dzień, miesiąc, rok, sekunda…) w liczbie pojedynczej.

Autor wpisu: JoShiMa, dodany: 12.05.2010 01:45, tagi: php, sql

W poprzednich artykułach tej serii pokazałam jak wygląda konstrukcja drzewa typu nested set a także jak wczytać zawartość drzewa tego typu. W tym odcinku pokażę, że wystarczą niewielkie modyfikacje omówionych wcześniej zapytań, by bez trudu odczytać dowolnie wybraną gałąź naszej struktury. Dla przypomnienia Na początek przypomnę tabelę zawierająca strukturę drzewa, którą wykorzystywałam w poprzednich artykułach oraz [...]

Autor wpisu: batman, dodany: 11.05.2010 08:54, tagi: internet

Mike Beltzner, dyrektor odpowiedzialny w Mozilli za Firefoxa, przedstawił na swoim blogu wizję nowej wersji przeglądarki, oznaczonej numerem 4.

Celami jakie zostały postawione przed nowym wydaniem są:

  • szybkość
  • wsparcie dla nowych standardów
  • udzielenie użytkownikowi pełnych praw do zarządzania przeglądarką oraz danymi przez nią gromadzonymi

Prezentację założeń nowej przeglądarki można obejrzeć w wersji ogg. Na blogu Mike’a Beltznera jest również dostępna prezentacja w postaci SlideShare.

Wszystkie wpisy należą do ich twórców. PHP.pl nie ponosi odpowiedzialności za treść wpisów.