Fizikai réteg

Általános elméleti alapok

A csatornán történő információátvitel során az adó megváltoztatja a csatorna fizikai közegének valamilyen tulajdonságát, ami a közegen továbbterjed, és a vevő ezt a fizikai közegváltozást érzékeli. Például vezetékek esetén az átfolyó áram változhat, vagy a feszültség, vagy ha elektromágneses hullámot használunk, akkor a hullám amplitudója, frekvenciája, vagy kezdeti fázisszöge. Azért kell ilyen általánosan fogalmaznunk, mert például kommunikálnak a börtönben a rabok is egymással, itt a kommunikációs közeg a vízcsővezeték és ez vezeti a kopogtatást, azaz a hangot, vagy gondoljunk az indiánok által használt füstjelzésre.

10. ábra: Az adatátvitel modellje

A közeg fizikai jellemzői változásának mértéke, a változtatás lehetséges sebessége, a tovaterjedés során fellépő jelgyengülés az átvitel során fellépő tényleges fizikai korlátok. Sokszor digitális hálózati terminológiaként használják a sávszélességet: azon maximális információátviteli sebességet értik alatta, amely egy adott kommunikációs csatornára jellemző. Valójában a sávszélesség analóg rendszerek esetén használt fogalom: egy adott analóg jel maximális és minimális frekvenciájának a különbségét értjük alatta.

Például az emberi beszéd alsó frekvenciája 300Hz, a felső frekvenciája 3400 Hz, így a sávszélessége: 3400-300=3.1 kHz

Digitális hálózatokat az adatátviteli sebességükkel: az időegység alatt átvitt bitek számával jellemezhetjük. Ezt célszerű bit/s-ban mérni. Az átvitelt jellemezhetjük a felhasznált jel értékében 1 másodperc alatt bekövetkezett változások számával is, amit jelzési sebességnek, vagy közismert néven baud-nak nevezünk.

1 baud = log2 P [bit/s], ahol P a kódolásban használt jelszintek száma.

Például olyan átvitelnél ahol ezt kétállapotú jelekkel valósítjuk meg, ott a baud és a bit/s azonos számértéket adnak, de ha a jelet négy szint felhasználásával visszük át, ott a baud számértéke már csak fele a bit/s-ban megadott valós adatátviteli sebességnek. Ezért mindig gondosan, ne egymás szinonimájaként használjuk a baud és bit/s mértékegységeket!

Vonalak megosztása

A következők megértéséhez meg kell különböztetnünk a csatornákat, amelyeken az információcsere történik, és a felhasznált, tényleges, fizikailag létező összeköttetéseket biztosító vonalakat. A csatornák amelyeken az üzenetek áramlanak, igen jelentős költséggel megépített és üzemeltetett összeköttetéseken (vezeték, rádióhullám) keresztül valósulnak meg. Ezért nem célszerű, ha egy kommunikációs csatorna számára kisajátítunk egy vonalat, mert nagyon sok esetben a kommunikáció jellegéből fakadóan nincs folyamatos információcsere rajta, azaz a legtöbb kapcsolatban a vonalhasználat időszakosan jelentkezik. Mivel az ADÓ és VEVŐ oldal számára csak a végeredmény, az információ a fontos, ezért több csatorna is kialakítható egy vonalon, amelynek megvalósítására több lehetőség van.

Jelenleg az analóg átviteli vonalakat felváltották a digitális átviteli utak. Ez azt jelenti, hogy szükségtelenné váltak a közbenső analóg-digitál és digitál-analóg átalakítók. Ezt azt is jelentette, hogy a frekvencia osztásos multiplexelést az időosztásos multiplexelés váltotta fel. Míg a beszéd analóg átviteléhez 300-3400 Hz-es sávszélesség elegendő, ugyanezen beszéd digitális átvitele 64 kbit/s-os adatátviteli sebességet igényel.

Vonalkapcsolás

Az ADÓ és a VEVŐ közti összekötetés megteremtésére ki kell alakítani azt az útvonalat, amelyeknek részei kapcsolóközpontokon keresztül vannak összekötve. Első lépésben fizikai kapcsolat létesül az ADÓ és VEVŐ között, ami az összeköttetés idejére áll fenn. Az összeköttetésen keresztül megvalósul az adatátvitel, majd annak befejeztével a kapcsolat lebomlik. A folyamatot a távbeszélő technikában hívásnak nevezik. Fontos tény, hogy az információátvitelt meg kell hogy előzze a híváskérés hatására létrejövő összeköttetés. Előnye a tényleges fizikai összeköttetés létrehozása. Ezek után a két állomás úgy képes kommunikálni, mintha pont-pont összeköttetés valósult volna meg közöttük.

11. ábra: Vonalkapcsolás elve

Ilyenkor az adatok késleltetését már csak az elektromágneses jel terjedési ideje határozza meg, amely kb. 6 msec 1000 km-enként. Hátránya a kapcsolat létrehozásához szükséges sokszor jelentős időtartam, és az, hogy ilyenkor a csatorna mégis kisajátítja a vonalat. Ha a csatorna nem teljes kapacitással üzemel (telefonnál: hosszú csend), akkor ez a vonal kihasználtságát rontja.

Üzenet és csomagkapcsolás

Ilyenkor nincs előre kiépített út az ADÓ és a VEVŐ között. Az ADÓ az elküldendő adatblokkját elküldi az első IMP-nek, az pedig továbbküldi a következőnek, egészen a VEVŐ hoszt-hoz kapcsolódó IMP-ig. Az ilyen hálózatok a tárol és továbbít (store-and-forward) hálózatok. Az üzenetkapcsolás esetén nincs az adatblokk méretére korlátozás, ami nagy tárolókapacitású fogadó és továbbító IMP-ket igényel.

12. ábra: Üzenetkapcsolás elve

Másik hátránya az, hogy egy nagy üzenet akár percekre lefoglalhatja a közreműködő IMP-ket és a köztük lévő átviteli csatornát. Ezért gyakrabban használatos (számítógépes hálózatoknál csaknem kizárólagosan használt) az a módszer, mikor az átviendő adatblokk méretét korlátozzuk, és csomagokká bontjuk.

13. ábra: Csomagkapcsolás elve

A csomagkapcsoló hálózatok hatékonyan alkalmazhatók interaktív forgalom (ember-gép kapcsolat) kezelésére is mivel biztosítják hogy bármelyik felhasználó csupán néhány ezredmásodpercre sajátíthat ki egy vonalat. A csomagkapcsolás nagyon hatékonyan képes a vonalak kihasználására, mivel adott két pont között összeköttetést több irányból érkező és továbbhaladó csomag is használja. Másrészről fennáll annak a veszélye, hogy a bemenő adatforgalom csomagjai úgy elárasztanak egy IMP-t, hogy korlátozott tárolókapacitása miatt csomagokat veszít. Míg vonalkapcsolás esetén az üzenet lényegében egyben kerül átvitelre, csomagkapcsoláskor a csomagok sorrendje megváltozhat, és a sorrendhelyes összerakásukról is gondoskodni kell.

Hibakezelés

Az adatátvitel és a kommunikáció fontos kérdése az átvitel során fellépő hibák kezelése. A rétegfelosztást figyelembe véve ezt az alsó három rétegben kell megoldani. Az első hibakezelést a fizikai rétegben, a bitek és karakterek átvitelénél kell megoldani. A vonalakon fellépő hibákat különböző fizikai jelenségek okozzák: termikus zaj, a vonalakat kapcsoló berendezések impulzus zaja, a légköri jelenségek (villámlás) okozta zajok. A zajok időtartamából következően lehetnek egyedi és csoportos bithibák. A gyakoribb esetben a hibák fennállási ideje általában egy bit átviteli idejének a többszöröse, ezért ezek a hibák csoportosan, hibacsomók formájában jelentkeznek. Mivel az adatátvitel blokkos (keretes) formában történik, ezért az eredmény egy-egy blokk tönkremenése.

Egyedi bithibák kezelésére a hibajavító (error correcting codes - ECC) és hibajelző kódok (error detecting codes) alkalmazása ad lehetőséget. Mindkét esetben az adatblokkokat redundanciával küldik, hogy a vevő az esetleges hiba tényét felfedezhesse (hibajelzés) illetve megállapíthassa hogy minek kellett volna jönnie (hibajavítás).

Csoportos bithibák esetén inkább egy másik módszert használnak, Ez a hibavédelmi eljárás, a CRC - Cyclic Redundancy Check úgy működik, hogy egy keretnyi adatot egy előre meghatározott bitsorozattal “elosztunk”, és a “maradékot” a keret részeként továbbítjuk. A vevő oldalon ugyanezt az osztást végezzük el, és ha ez a keret részeként átküldött maradékkal egyezik, akkor hibátlannak fogadjuk el a keretet. Három szabványos bitsorozat terjedt el:

Az olyan 16 bites ellenőrző összeg, amit a az utóbbi két módszer alapján állítunk elő, észleli az összes egyes és kettős hibát, az összes páratlan hibás bitet tartalmazó hibát, az összes 16 vagy ennél rövidebb csoporthibát, a 17 bites csoporthibák 99.997%-át, valamint a 18 bites és annál hosszabb csoporthibák 99.998%-át.
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(); ?>