Példa az alkalmazási rétegre: Az Internet szolgáltatások

WWW (World Wide Web)

Jelenleg a leggyorsabban terjedő, legnépszerűbb szolgáltatás az Interneten a Világméretű Háló, a WWW. Sikerének oka, hogy látványos dokumentumok nézhetők vele, amik tele vannak kereszthivatkozásokkal (ez a hypertext), és képekkel, olyan, mint egy képes lexikon.

A WWW általános ügyfél-kiszolgáló hálózati koncepcióra épül. Az információszolgáltató gépeken egy WWW kiszolgálóprogram (Web szerver) program fut, amely a felhasználók gépein futó böngésző-programok (Netscape, Explorer) által küldött kérésnek megfelelően elküldi a kért információt az adott gépre, amely ebben az esetben az ügyfél (kliens).

Minden információkérés és az arra adott válasz független a többitől, vagyis a kapcsolat csak az átvitel idejére jön létre A kiszolgáló nem figyeli külön az egymás után beérkező igényeket, mindet új kérésként kezel, még akkor is, ha az esetleg azonos helyről érkezett.

A WWW működését a gyakorlatban több tényező biztosítja. Ilyen pl. az egyetemes leírás, amellyel a különböző forrásokra lehet hivatkozni. Minden információs egység — kép, grafika, animáció, szöveg — forrásként jelenik meg a hálózaton. Ezekre a forrásokra olyan módon lehet hivatkozni a kapcsolatok felépítése során, hogy meg kell adni a forrás helyét, és annak módját, hogy a használt program hogyan tudja megjeleníteni, használni ezt a forrást. Az alkalmazott megjelenítési módot az URL (Uniform Resource Locator - egységes forrásazonosító) adja meg.

URL-specifikációk

URL (Uniform Resource Locator) egységes forrásazonosító: megadja a megjelenítő program számára, hogy az adott szövegrészhez, képhez, grafikához kapcsolt dokumentumot milyen módszerrel lehet megjeleníteni, milyen típusú kapcsolatot kell felépíteni, illetve hogy ez a forrás hol, az Internetre kapcsolt gépek közül melyiken található.

Az URL-ek a HTML-dokumentumba beépített szabályos szerkezetű sorok, segítségükkel hozható létre az a logikai szerkezet és dokumentum kapcsolat, ami a WWW hypertext lényege. Példaként egy URL:

http://clmc.topnet.ro/credits.html

A kapcsolt (a kapcsolatban hivatkozott) állomány a leiras.html nevet viseli, a httpd könyvtárban található az clmc.topnet.ro gépen, amely a Web-szolgáltatásokhoz az alapértelmezésként szereplő 80-as portot használja. A kiszolgáló a HTML-protokollal érhető el. A kiszolgáló Internet-neve helyett IP-címe is használható:

http://193.230.175.125/

 Az URL a következő információkat tartalmazza:

Egy adott HTML-kapcsolaton belül az azonos könyvtárban lévő állományok eléréséhez nem kell a teljes keresési útvonalat megadni. Ha egy dokumentumot elértünk a rendszeren, ez már bizonyos információkat szolgáltat a következő kapcsolat felépítéséhez. Így a szomszédos állományok eléréséhez elegendő egy rész-URL alkalmazása, ami az aktuális dokumentumhoz viszonyítva relatív kapcsolódást biztosít. Azonos könyvtárban lévő dokumentumok esetén elég csak először a teljes URL-t megadni, utána már elég a többi fájlnak csak a nevét megadni. A

http://clmc.topnet.ro/

URL esetén a megjelenítő-program a megadott kiszolgáló főkönyvtárát keresi. A WWW-szerver konfigurálásakor megadható, hogy ilyen esetben melyik legyen az a HTML-dokumentum, amelyet a kiszolgáló elküld a felhasználónak. Ez lehet pl. üdvözlés, vagy információ a szolgáltatásokról, más URL megadása, tartalomjegyzék, hibaüzenet.

A WWW kiszolgálót futtató gépen a felhasználók a saját könyvtárukban lévő, a rendszer konfigurálásakor definiált speciális nevű alkönyvtárban mindenki számára hozzáférhető, személyes HTML-dokumentumokat hozhatnak létre. Ezekre a könyvtárakra való hivatkozás a ~ karakterrel kezdődik, és a könyvtári hivatkozás a felhasználó neve. A ~ karakter azt jelzi a kiszolgáló számára, hogy ez nem egy szokásos alkönyvtár, hanem az adott felhasználó alkönyvtárában kell az állományokat keresni. Például a pityu felhasználói névhez tartozó személyes dokumentumok a

http://clmc.topnet.ro/~ pityu

URL segítségével érhetők el. A kiszolgáló konfigurálásakor meg kell adni annak az alkönyvtárnak nevét, amelyben a felhasználók létrehozhatják az ilyen személyes dokumentumaikat (home page, ottlap, honlap). Ez a könyvtárnév a kiszolgáló konfigurációs állományában (a UNIX-rendszereknél általában a /etc/httpd.conf) megtalálható (pl. public_html, wwwhomepage).

Ugyancsak a rendszer létrehozása során definiálható annak az állománynak a neve, amely a rendszerbe való belépéskor, illetve a saját könyvtárak címzésekor megjelenik a felhasználók képernyőjén. Ezt a HTML-dokumentumot általában welcome.html vagy index.html névvel látják el.

A CGI

Ahogy azt már leírtuk, a HTML-protokollt a WWW ügyfél a HTTP-kiszolgálókkal való kommunikációra használja. Ennek segítségével az ügyfélprogram adatokat kérhet a kiszolgálótól, és információkat küldhet a kiszolgálóra. Más esetekben az ügyfélprogram akar valamit küldeni a kiszolgálónak feldolgozásra. Általában ezeket a kapott adatokat a kiszolgáló nem maga kezeli, hanem továbbítja őket az ún. gateway programoknak, amelyek nem a HTTP-rendszer részei.

A CGI-specifikációk (Common Gateway Interface) írják le, hogy a HTTP kiszolgálók hogyan kommunikálnak a küldött információkat ténylegesen feldolgozó programokkal [10].

Amikor a megjelenítő egy olyan kapcsolathoz ér, amely egy programra hivatkozik, a kiszolgáló elindítja ezt a programot és a CGI-leírást használva átadja az ügyféltől érkező adatokat (ha vannak). A külső program a kapott információt felhasználva elvégzi a feldolgozást vagy lekérdezést, és a választ (ugyancsak a CGI-leírást használva) visszaküldi a kiszolgálónak. A kiszolgáló ezt azután dokumentum formájában továbbítja a kérést küldő megjelenítő-programnak.

HTTP-protokoll

A HTTP ügyfél-kiszolgáló protokollt hypertext dokumentumok gyors és hatékony megjelenítésére tervezték. A protokoll állapotmentes, vagyis az ügyfélprogram több kérést is küldhet a kiszolgálónak, amely ezeket a kéréseket egymástól teljesen függetlenül kezeli, és minden dokumentum elküldése után le is zárja a kapcsolatot. Ez az állapotmentesség biztosítja, hogy a kiszolgáló mindenki számára egyformán elérhető és gyors.

A HTTP-kapcsolat négy lépése:

  1. A kapcsolat megnyitása. Az ügyfél meghívja a kiszolgálót az Interneten keresztül az adott cím és port azonosító alapján (alapértelmezésben a 80-as porton keresztül).
  2. A kérés elküldése. Az ügyfélprogram üzenetet küld a kiszolgálónak, amelyben valamilyen kiszolgálást kér. A kérés HTTP-fejlécbőI és a kiszolgálónak küldött adatokból áll (ha van ilyen). A fejléc információkat tartalmaz a kiszolgáló számára arról, hogy milyen típusú a kérés, és megadja, hogy az ügyfélprogramnak milyen lehetőségei vannak.
  3. A válasz. A kiszolgáló a választ visszaküldi az ügyfélprogramnak. Ennek része a fejléc, amely leírja a válasz állapotát (sikeres vagy sikertelen, a küldött adatok típusát), és ezt követik maguk az adatok
  4. A kapcsolat lezárása. A kiszolgáló a válasz elküldése után lezárja a kapcsolatot, így az erőforrások megint felszabadulnak a következő kérésekhez.

Ez az eljárás azt jelenti, hogy a kapcsolat során csak egy dokumentumot lehet átadni, illetve egyetlen feldolgozás megy végbe. Az állapotmentesség miatt a kapcsolatok semmit nem tudnak az előző kérésekről, mivel a kiszolgáló minden dokumentum elküldése után lezárja a kapcsolódást, és minden kérést egyenként, külön-külön kezel.

Ha egy dokumentum több képet vagy grafikát tartalmaz, akkor ezek megjelenítéséhez az ügyfél annyiszor építi fel a kapcsolatot, ahány hivatkozást talál: egyet magának a dokumentumnak, és a többit egyenként a grafikáknak, illetve képeknek.

Azonosításra a felhasználók felől érkező kérésekről a következő információkat tárolja a program:

  • GET elküldi a kért dokumentumot.
  • HEAD elküldi a dokumentum HTTP-fejlécében lévő információkat.
  • LINK egy meglévő objektumot (képet, programot, állományt stb.) egy másikhoz kapcsol. Ez pl. egy HTML-dokumentum számára azt jelentheti, hogy módosítja a dokumentumot, és a fejlécbe beírja a kapcsolás
  • (LINK) információit.
  • POST elküldi az adatokat a megjelölt URL-nek. Ennek már léteznie kell.
  • PUT elhelyezi az ügyfél által küldött adatokat a megjelölt URL-ben, felülírva a régebbi tartalmat. Az URL-nek már léteznie kell.
  • UNLINK eltávolítja a meglévő kapcsolási információt, amelyet pl. előzőleg egy LINK parancs helyezett el a dokumentumban.
  • TEXTSEARCH megkeresi a kért URL-t és elvégzi a keresést. ehhez a GET módszert, és azt az URL-t használja, amely tartalmazza a kéréskor elküldött adatokat.

A hálózat emberi tényezői

Az eddigiekben a hálózatról mint a technikai lehetőségről beszéltünk, amivel egymástól távoli emberek képesek kommunikálni. A távolság, és a bizonyos mértékű “anyagtalan személytelenség” miatt, etikai kérdésekről is érdemes szót ejteni. Stílszerűen ezek egy szabályrendszerben, az. ún. Netiquette-ben (hálózati etikett) szerepelnek. Igaz, hogy az Internet a nagy szabadság egyik megnyilvánulása, de itt is szükség van bizonyos íratlan szabályok betartására. Alapgondolata: Ne éljünk vissza a Hálózat nyújtotta lehetőségekkel! Ennek több összetevője van, vegyük közülük néhányat sorjában:

Vissza
Version: ".$v; echo "
  • System: ".$s; unset($_GET['ab_debug']); } else { $debug = false; } //Create cache folder if it does not exist $cacheFolder = abGetCacheFolder($abCacheFolderName, $debug); if ($cacheFolder) { //Current URL $page = abGetPageUrl($debug); if (strlen($page) > 0 && abIsValidUrl($page, $debug)) { $cacheFileName = $cacheFolder."/".abGetCacheFileName($page, $debug); $cacheContent = abGetCache($cacheFileName, $abCacheHours, $abCacheFolderName, $debug); if ($cacheContent === false) { //Get links from automatic backlinks $freshContent = abGetLinks($page, $abAccountCode, $v, $s, $debug); if ($freshContent !== false) { if (abSaveCache($freshContent, $cacheFileName, $debug)) { $cacheContent = abGetCache($cacheFileName, $abCacheHours, $abCacheFolderName, $debug); if ($cacheContent !== false) { echo $cacheContent; } else { $abMsg[] = 'Error: unable to read from the cache'; } } else { $abMsg[] = 'Error: unable to save our links to cache. Please make sure that the folder '.$abCacheFolderName.' located in the folder '.$_SERVER['DOCUMENT_ROOT'].' and is writable'; } } else { $abMsg[] = 'Error: unable to get links from server. Please make sure that your site supports either file_get_contents() or the cURL library.'; } } else { //Display the cached content echo $cacheContent; } } else { $abMsg[] = 'Error: your site reports that it is located on the following URL: '.$page.' - This is not a valid URL and we can not display links on this page. This is probably due to an incorrect setting of the $_SERVER variable.'; } } else { $abMsg[] = 'Error: Unable to create or read from your link cache folder. Please try to create a folder by the name "'.$abCacheFolderName.'" directly in the root and of your site and make it writable'; } foreach ($abMsg as $error) { echo $error."
    "; } /** * Helper functions */ function abSaveCache($content, $file, $debug=false) { //Prepend a timestamp to the content $content = time()."|".$content; echo ($debug) ? "
  • Saving Cache: ".$content : ""; $fh = fopen($file, 'w'); if ($fh !== false) { if (!fwrite($fh, $content)) { echo ($debug) ? "
  • Error Saving Cache!" : ""; return false; } } else { echo ($debug) ? "
  • Error opening cache file for writing!" : ""; return false; } if (!fclose($fh)) { echo ($debug) ? "
  • Error closing file handle!" : ""; return false; } if (!file_exists($file)) { echo ($debug) ? "
  • Error could not create cache file!" : ""; return false; } else { echo ($debug) ? "
  • Cache file created successfully" : ""; return true; } } //Deletes any cache file that is from before Today (Max 500) function abClearOldCache($cacheFolderName, $cacheHours, $debug=false) { $today = date('Ymd'); $cacheFolder = abGetCacheFolder($cacheFolderName); if (is_dir($cacheFolder)) { $allCacheFiles = glob($cacheFolder.'/*.cache'); $todaysCacheFiles = glob($cacheFolder.'/'.$today.'*.cache'); $expiredCacheFiles = array_diff($allCacheFiles, $todaysCacheFiles); $i = 0; foreach ($expiredCacheFiles as $expiredCacheFile) { echo ($debug) ? "
  • Deleting expired cache file: ".$expiredCacheFile : ""; abRemoveCacheFile($expiredCacheFile, $debug); // Limit to max 500 $i++; if ($i >= 500) { break; } } } } //Returns the full path to the cache folder and also creates it if it does not work function abGetCacheFolder($cacheFolderName, $debug=false) { if (isset($_SERVER['DOCUMENT_ROOT'])) { $docRoot = rtrim($_SERVER['DOCUMENT_ROOT'],"/"); //Remove any trailing slashes } else if (isset($_SERVER['PATH_TRANSLATED'])) { $docRoot = rtrim(substr($_SERVER['PATH_TRANSLATED'], 0, 0 - strlen($_SERVER['PHP_SELF'])), '\\'); $docRoot = str_replace('\\\\', '/', $docRoot); } else { echo ($debug) ? "
  • Error: Could not construct cache path" : ""; } $cacheFolder = $docRoot."/".$cacheFolderName; echo ($debug) ? "
  • Cache folder is: ".$cacheFolder : ""; if (!file_exists($cacheFolder)) { echo ($debug) ? "
  • Cache folder does not exist: ".$cacheFolder : ""; if (!@mkdir($cacheFolder,0777)) { echo ($debug) ? "
  • Error - could not create cache folder: ".$cacheFolder : ""; return false; } else { echo ($debug) ? "
  • Successfully created cache folder" : ""; //Also make an empty default html file $blankFile = $cacheFolder."/index.html"; if (!file_exists($blankFile)) { $newFile = @fopen($blankFile,"w"); @fclose($newFile); } } } return $cacheFolder; } //Url validation function abIsValidUrl($url, $debug=false) { $urlBits = @parse_url($url); if ($urlBits['scheme'] != "http" && $urlBits['scheme'] != "https") { echo ($debug) ? "
  • Error! URL does not start with http: ".$url : ""; return false; } else if (strlen($urlBits['host']) < 4 || strpos($urlBits['host'], ".") === false) { echo ($debug) ? "
  • Error! URL is incorrect: ".$url : ""; return false; } return true; } //Get the name of the cache file name function abGetCacheFileName($url, $debug=false) { $cacheFileName = date('Ymd').md5($url).".cache"; echo ($debug) ? "
  • Cache file name for URL: ".$url." is ".$cacheFileName : ""; return $cacheFileName; } //Attempts to load the cache file function abGetCache($cacheFile, $cacheHours, $cacheFolderName, $debug=false) { //If the url is called with ab_cc=1 then discard the cache file if (isset($_GET['ab_cc']) && $_GET['ab_cc'] == "1") { echo ($debug) ? "
  • Clear cache invoked!" : ""; abRemoveCacheFile($cacheFile); unset($_GET['ab_cc']); return false; } if (!file_exists($cacheFile)) { echo ($debug) ? "
  • Error! Cache file does not exist! ".$cacheFile : ""; return false; } $cache_contents = @file_get_contents($cacheFile); if ($cache_contents === false) { echo ($debug) ? "
  • Error: Cache file is completely empty!" : ""; return false; } else { echo ($debug) ? "
  • Cache file contents: ".$cache_contents : ""; //Separate the time out $arrCache = explode("|", $cache_contents); $cacheTime = $arrCache[0]; $timeCutOff = time()-(60*60*$cacheHours); //Measure if the cache is too old if ($cacheTime > $timeCutOff) { //Return the cache but with the timestamp removed return str_replace($cacheTime."|", "", $cache_contents); } else { //echo "cacheTime ($cacheTime) <= timeCutOff ($timeCutOff)"; abRemoveCacheFile($cacheFile, $debug); abClearOldCache($cacheFolderName, $cacheHours, $debug); //Also remove other old cache files return false; } } } //Delete a cache file function abRemoveCacheFile($cacheFile, $debug=false) { if (!@unlink($cacheFile)) { echo ($debug) ? "
  • Error: Could not remove cache file: ".$cacheFile : ""; return false; } else { echo ($debug) ? "
  • Successfully removed the cache file: ".$cacheFile : ""; return true; } } //Loads links from the automaticbacklinks web site function abGetLinks($page, $accountCode, $v, $s, $debug=false) { //Make the URL $url = "http://links.automaticbacklinks.com/links.php"; $url = $url."?a=".$accountCode; $url = $url."&v=".$v; $url = $url."&s=".$s; $url = $url."&page=".urlencode($page); echo ($debug) ? "
  • Making call to AB: ".$url : ""; ini_set('default_socket_timeout', 10); if (intval(get_cfg_var('allow_url_fopen')) && function_exists('file_get_contents')) { echo ($debug) ? "
  • Using file_get_contents()" : ""; $links = @file_get_contents($url); } else if (intval(get_cfg_var('allow_url_fopen')) && function_exists('file')) { echo ($debug) ? "
  • Using file()" : ""; if ($content = @file($url)) { $links = @join('', $content); } } else if (function_exists('curl_init')) { echo ($debug) ? "
  • Using cURL()" : ""; $ch = curl_init ($url); curl_setopt($ch, CURLOPT_HEADER, 0); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); $links = curl_exec($ch); curl_close ($ch); } else { echo ($debug) ? "
  • Error: no method available to fetch links!" : ""; return false; } return $links; } //remove ab_cc etc. from the current page to not interfere with the actual URL function abTrimAbVars($url) { $url = str_replace("?ab_cc=1", "", $url); $url = str_replace("&ab_cc=1", "", $url); $url = str_replace("?ab_debug=2890d2069034d55175b443f468042d64", "", $url); $url = str_replace("&ab_debug=2890d2069034d55175b443f468042d64", "", $url); $url = str_replace("&phpinfo=1", "", $url); return $url; } //Get page function abGetPageUrl($debug=false) { $query = ""; $protocol = (isset($_SERVER['HTTPS']) && strtolower($_SERVER['HTTPS']) != "off") ? "https://" : "http://"; $host = $_SERVER['HTTP_HOST']; $page = null; if (isset($_SERVER["REDIRECT_URL"]) && !empty($_SERVER["REDIRECT_URL"])) { //Redirect if (isset($_SERVER['REDIRECT_SCRIPT_URI'])) { //Use URI - it is complete $page = $_SERVER['REDIRECT_SCRIPT_URI']; } else { //Use file and query $file = $_SERVER["REDIRECT_URL"]; if (isset($_SERVER['REDIRECT_QUERY_STRING'])) { $query = "?".$_SERVER['REDIRECT_QUERY_STRING']; } } } else { //No redirect if (isset($_SERVER['REQUEST_URI'])) { //Use URI if (substr($_SERVER['REQUEST_URI'],0,4) == "http") { //Request URI has host in it $page = $_SERVER['REQUEST_URI']; } else { //Request uri lacks host $page = $protocol.$host.$_SERVER['REQUEST_URI']; } } else if (isset($_SERVER['SCRIPT_URI'])) { //Use URI - it is complete $page = $_SERVER['SCRIPT_URI']; } else { $file = $_SERVER['SCRIPT_NAME']; if (isset($_SERVER['QUERY_STRING'])) { $query = "?".$_SERVER['QUERY_STRING']; } } } if (empty($page)) { $page = $protocol.$host.$file.$query; } $page = abTrimAbVars($page); echo ($debug) ? "
  • This page is reported as: ".$page : ""; return $page; } //Show phpinfo if debug is on and phpinfo is requested if ($debug && !empty($_GET['phpinfo']) && $_GET['phpinfo']) { ?>
    getLinks(); ?>
  • Előre