Jblew.pl - Notatnik młodego programisty. Elektronika, webmastering, programowanie.

Przenosiny

Serwer feynman




Bezpieczne bindowanie do portów < 1024 w javie

W linuksach, żeby otworzyć gniazdo nasłuchujące na porcie od 0 do 1024, trzeba mieć prawa roota. Teoretycznie można uruchomić serwer z prawami roota, ale czy to bezpiecznie? Są aż dwa sposoby rozwiązania tego problemu, umożliwiające nasłuchiwanie na porcie 80, bez praw roota i bez rekompilacji jądra. Zobacz więcej »




[Ubuntu 10.10] Brak pluginu javy w firefoxie i google chrome

W nowym ubuntu przykrą niespodzianką jest brak pluginu javy. Nie ma go też w domyślnych repozytoriach. Na szczęście można go zainstalować. Najpierw należy wejść do Synaptica, w Ustawienia > Repozytoria, a tam Inne Oprogramowanie i zaznaczyć „Partnerzy Canonical”. Następnie trzeba kliknąć „odśwież” w głównym oknie Synaptica i zainstalować „sun-java6-plugin”. Potem wystarczy tylko zrestartować przeglądarkę, i po sprawie. :)




[Ubuntu] Nie da się wączyć bluetooth

Miałem dzisiaj taki problem, że nie mogłem ponownie włączyć bluetooth na moim laptopie. Cały czas pokazywał mi się przycisk włącz bluetooth. Najwyraźniej jest to jakiś błąd w nowej wersji (11.04), bo wcześniej nie miałem takiego problemu. Na szczęście, żeby to naprawić wystarczy wpisać w terminalu sudo /etc/init.d/bluetooth restart, i po sprawie. :)




java.lang.IllegalStateException: Cannot find the system Java compiler. Check that your class path includes tools.jar

Tak się zdarzyło, że do progów używam jednak dynamicznej kompilacji, gdyż skrypty w javax.script.* zbyt wolno chodziły na serwerze. Dynamiczny kompilator wymaga jednak „tools.jar” do poprawnej pracy. Jeśli uruchamia się program z wykorzystaniem jre (zamiast jdk) możemy dostać taki wyjątek, jak w temacie.

Rozwiązanie jest proste. Wystarczy zainstalować jdk: apt-get install openjdk-6-jdk. I gotowe.




Jak zwiększyć zużycie ramu w Javie

We wszystkich podręcznikach o programowaniu przytacza się zasadę, że kodu nie wolno optymalizować. I nawet nie próbuj programisto, bo popsujesz! Nie jestem zwolennikiem takiego myślenia, bowiem czasem zdarza się, że napiszemy bardzo nieoptymalny kod i warto go zoptymalizować (oczywiście, cudzego kodu optymalizować nie wypada ;P).

Dlaczego to piszę? Jak we wszystkich poprzednich postach, znowu muszę wspomnieć o mudzie… Podczas pisania zauważyłem, że gdy użytkownik wyda jakąkolwiek komendę, zużycie ramu zwiększa się nawet o 50kb! Na szczęście szybko znalazłem przyczynę. Okazało się, że, jak zwykle winny jest programista, a nie kto inny. Otóż gdy użytkownik wpisywał komendę tworzona była nowa klasa Command, która tą komendę przetwarzała. I tu był błąd! Przy każdym tworzeniu tej klasy kompilator musiał zarezerwować pamięć. Szybko zorientowałem się, o co chodzi i poprawiłem kod tak, że klasa Command jest tworzona, gdy użytkownik wejdzie do gry, a potem jest wywoływana tylko jej metoda. Wspaniały profiler netbeansa pokazał wyraźnie różnicę w zużyciu pamięci.










Skrypty w javie…

Jak już wcześniej pisałem już od pewnego czasu piszemy muda w czystej javie. Mamy już sporo funkcji i obsługę wieli mudowych problemów, w związku z czym nadszedł czas na rozpoczęcie tworzenia obsługi MOB-ów, czyli postaci sterowanych przez komputer. Każdy mob ma swój program, nazywany mobprogiem. Cały problem polega na tym, żeby móc edytować program moba bez ponownej kompilacji całego programu. Dość długo szukałem optymalnego rozwiązania. Zastanawiałem się m.in. nad dynamicznym kompilowaniem kodu, nad językiem lua…

Ale najlepsze okazało się dedykowane API dla skryptów – javax.script.

Jest bardzo proste w obsłudze. Poniżej przedstawiamprzykład i opis:


package scriptingtest;

import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;

public class Main {
public static void main(String[] args) throws ScriptException {
ScriptEngineManager factory = new ScriptEngineManager();
ScriptEngine engine = factory.getEngineByName("JavaScript");

Proba p = new Proba(); //zawiera tylko pole int i

engine.put("p", p);
p.i = 7;
System.out.println(p.i);

engine.eval(""
+ "importPackage(java.lang);"
+ "importClass(Packages.scriptingtest.Proba);"
+ ""
+ "p.i = 2;");

System.out.println(p.i);
}
}

Klasa Próba zawiera tylko pole public int i = 0; . Uruchamiając program zobaczymy, że skrypt zmieni wartość i z 7 na 2. To wszystko. Jak widać jest to bardzo proste i może być przydatne w dużych aplikacjach, szczególnie w grach.

Należy tylko pamiętać, że jeśli chcemy zaimportować jakąś klasę z wewnątrz jara, w którym uruchamiamy program, muśimy dodać na początku Packages.nazwapakietu.









Dlaczego debian na serwerze jest fajniejszy niż ubuntu?

Na ubuntu było >100mb…









Marines MUD – W pogoni za RAMem

Od dwóch tygodni piszemy z Progtrykiem MUD-a. MUD był jego pomysłem, ale postanowiłem przyłączyć się do projektu. MUD nazywa się Marines. Akcja toczy się w roku 2063, zaraz po III Wojnie Światowej. Ponieważ III Wojna Światowa rozciągała się niemiłosiernie długo, i istniała realna groźba zniszczenia przez ludzi naszej błękitnej planety, ktoś w jakiś sposób zniszczył wszystkie nowoczesne bronie i sprawił, że ludzie zapomnieli dla kogo walczą. W jednej chwili przestały istnieć państwa i hierarchia. Zapanował totalny chaos i anarchia. W grze, każdy walczy sam, przeciwko innym graczom. Na domiar złego, natura wybrała akurat ten moment, aby przemagnesować bieguny, w rezultacie czego, zmieniły się kontynenty i ziemia wygląda zupełnie inaczej. No, to tyle o historii. Potem ją dopracujemy i wrzucimy na stronę muda (marines.jblew.pl). Jeśli ktoś ma ochotę wypróbować muda, to zapraszam:
telnet 91.210.130.79 9000

Kod

No to teraz opowiem troche o kodzie. Gdyby ktoś chciał go obejrzeć, może to uczynić przez Subversion. Bieżąca wersja projektu znajduje się w folderze v2:
svn co svn://91.210.130.79/marines-mud marines-mud

Na samym początku postanowiliśmy, że podzielimy muda na program serwera i skrypt obsługujący użytkownika (oddzielny dla każdego usera). Po uruchomieniu serwer oczekiwał na nadchodzące połączenia. Gdy już jakieś zaakceptował, przenosił je do oddzielnego wątku i uruchamiłałał skrypt do obsługi użytkownika. Wątek odbierał dane do użytkownika, aby wysyłać je do skryptu i vice versa.

Pierwsza wersja muda była oparta na architekturze JAVA+PHP+MYSQL. OMG!? No właśnie… nie najszczęśliwsze połączenie. Problemem tej wersji była właściwie tylko java. Java jest fajna do programowania, bo prawie wszystko robi za programistę i zawiera mnóstwo bibliotek, które znacznie ułatwiają pracę. Zaraz, zaraz! Mnóstwo bibliotek = mnóstwo zużywanej pamięci! Największym problemem „javovej” wersji było horrendalne zużycie ramu. Na początek skrypt zabierał ok 70mb ramu, a potem zabierał kolejne 16mb na każdego użytkownika. Koszmar!

Zaraz potem próbowaliśmy szczęścia z pythonem zamiast javy. Jednak z pythonem był taki problem, że nijak nie mogliśmy zmusić biblioteki socketserver aby umożliwiła nam ponowne używanie portu.

Wreszcie postanowiliśmy w roli serwera użyć programu napisanego w c++. Nadal jednak mieliśmy problemy, tym bardzoej, że żaden z nas nie był doświadczonym programistą tego zacnego języka.

Ostatecznie zdecydowaliśmy się scalić skrypt z serwerem i tak powstała najnowsza wersja muda, w całości napisana w php. Sprawuje się bardzo dobrze, nie zużywa nadmiernie pamięci i ogólnie jestem z niej bardzo zadowolony. Dlatego opiszę ją dokładniej.

Wielowątkowość w php

Wiele lat myślałem że to niemożliwe. Cały czas zdawało mi się, że w php nie ma wielowątkowości. Kilka dni temu dowiedziałem się, że jednak jest! Ale tylko w systemach uniksowych. Jako, że jestem już szczęśliwym posiadaczem ubuntu, nie stanowi to żadnego problemu. Znalazłem też w sieci fajną klasę, która umożliwia czytelniejszą obsługę wątków w obiektowym stylu. Dzięki tej klasie obsługa wątków jest dziecinnie prosta. Autor zamieścił przykłady jej zastosowań.

Pierwsze uruchomienie

Jeśli ktoś chce uruchomić u siebie serwer, albo stworzyć innego muda na podstawie kodu, nie ma problemu. Proszę tylko o pozostawienie informacji o autorach (można dopisać swoje autorstwo).

Aby uruchomić muda należy najpierw utworzyć bazę danych phpmud, a następnie zaimportować tabele z pliku ./v2/other/sql/phpmud.sql. Kolejną sprawą jest ustawienie loginu i hasła do bazy danych, w plikach: ./v2/includes/mysql.php, ./v2/includes/globalMysql.php i ./v2/lib/class.mudUser.php. We wszystkich powinny znajdować się te same dane. Potem otwieramy trzy konsole, lub trzy okna screena, jak kto woli i w jednym uruchamiamy polecenie php tickers.php, w drugim php mobs.php, a w trzecim php phpMudServer.php. Jeśli wszystko będzie działało, w ostatnim oknie powinniśmy zobaczyć taki ekran:

   +----------------------------------+
   |   MudServer For PHP Muds v0.51   |
   +----------------------------------+
   |   Written by:                    |
   |        +JBLEW (www.jblew.pl)     |
   |        +PROGTRYK                 |
   +----------------------------------+

Setting server online...
Starting console reader...
Wpisz quit aby zakończyć program.
Starting SVNUpdater...
Listening on port 9000...
[0s od uruchomienia] Mysqli działa prawidłowo!
W wersji 418.

Jak to wszystko działa?

Skoro już uruchomiłeś muda, to opiszę teraz, jak on działa.
Pierwszy uruchomiony program – tickers.php jest mudowym odpowiednikiem crona. Tam wykonują się wszystkie periodyczne operacje, jak np. informowanie użytkowników o dniu/nocy, czy resetowanie obiektów w roomach.

Drugi program – mobs.php docelowo będzie obsługiwał moby, narazie jednak nie robi nic. Możesz go wyłączyć.

Najważniejszy jest trzeci skrypt – phpMudServer.php – to on obsługuje całego muda i co 30 sekund aktualizuje SVN.  Otwórz teraz w jakimś edytorze ten plik i zjedź aż do miejsca, gdzie znajduje się polecenie set_time_limit(0); Z pewnością wiesz, po co je tam umieściłem. Prawdziwa zabawa zaczyna się dopiero od linijki set_server_online(„1″);. Funkcja ta wpisuje „1″ do pliku data/online.dat, co jest dla skryptów znakiem, że serwer pracuje. Dalej uruchamiamy wątek consoleReader, który odczytuje kolejne linie z stdin i oczekuje aż wpiszemy quit. Wtedy wykona polecenie set_server_online(„0″);, dzięki czemu reszta wątków będzie wiedziała, że czas się wyłączyć. Dalej tworzymy nasłuchujące gniazdo, a potem w pętli oczekujemy połączenia, przy okazji co sekundę wysyłając bezsensowne polecenie do mysql-a, aby utrzymać połączenie. Gdy nowy użytkownik się połączy, serwer uruchamia wątek userThread. Przenieśmy się zatem do tej funkcji. Tworzy ona klasę MudUser i przekazuje jej gniazdo, oraz wątek. Następnie wywołuje metodę run, i od teraz użytkonik jest przenoszony do skryptu ./v2/lib/class.mudUser.php.

No. Na dzisiaj to wystarczy, jutro, albo pojutrze opiszę, co się dalej dzieje w tej klasie. Dziękuję za uwagę!







[PHP] Prosty sposób na odczytywanie danych XML

Jak zapewne zauważyliście dodałem na bloga skrypt wyświetlający wpisy z twittera między wpisami z bloga. Zanim jednak można będzie wyświetlić dane, trzeba je najpierw pobrać z serwera. Najłatwiejszym sposobem na pobranie wpisów twittera jest odczytanie kanału rss danego użytkownika.

Z każdego znacznika <item> (w kanale rss) potrzebujemy 3 znaczników: <title>, <pubDate> i <link>.

Niektórzy pewnie chcieliby pewnie wyciągnąć te dane używając wyrażeń regularnych. Do dzisiaj należałem do tych ludzi. Używanie bibliotek parsujących xml wydawało mi się skomplikowane i nieprzyjemne. Jednak w istocie tak nie jest. PHP posiada łatwą w użyciu bibliotekę DOMDocument. W naszym wypadku kod jest naprawdę krótki:

$objDOM = new DOMDocument();
    //pobieramy kanal rss i tworzymy liste zawierajaca elementy ITEM
$objDOM->load("http://adres.kanalu.rss/z/twittera"); 
$items = $objDOM->getElementsByTagName("item");

foreach( $items as $item ) {        
    //w petli wyciagamy wartosci z poszczegolnych znacznikow
    $title  = $item->getElementsByTagName("title")->item(0)->nodeValue;
    $pubDate = $item->getElementsByTagName("pubDate")->item(0)->nodeValue;
    $link = $item->getElementsByTagName("link")->item(0)->nodeValue;
}

Jak widzicie korzystanie z tej biblioteki to czysta przyjemność. ;) Wszystko można zrobić szybko i sprawnie. Kod łatwo jest zmodyfikować do swoich potrzeb.




Bannery

Create your own banner at mybannermaker.com!