Socket

A Wikipédiából, a szabad enciklopédiából
Ez a szócikk az internetes socketeket tárgyalja. Lásd még: Unix domain socket, CPU socket, WebSocket.

A számítógép-hálózatokban a szoftvercsatorna, csatlakozó, Internet socket vagy egyszerűen socket egy Internet Protocol-alapú számítógépes hálózatban, például az interneten valamely kétirányú folyamatközi kommunikációs (IPC) hálózati folyam végpontja.

A socket kifejezést a TCP/IP protokollkészlet általában az operációs rendszer által biztosított API-jának megnevezésére is használják. Az Internet socketek lehetőséget nyújtanak a bejövő adatcsomag megfelelő alkalmazáshoz (processzhez vagy threadhez) való kézbesítésére, a helyi és távoli IP-címek és portok kombinációja alapján. Az operációs rendszer minden socketet egy kommunikáló alkalmazásprocesszhez vagy -szálhoz rendel.

A socket címe egy IP-cím (a számítógép helye) és egy portszám (ami az alkalmazáshoz köthető) együttese, hasonlóan ahhoz, ahogy a telefonkapcsolat egyik felét meghatározhatja egy telefonszám és a választott mellékállomás kombinációja.

A socket lényegében egy absztrakció, amit a Berkeley BSD Unix vezetett be. Ennek segítségével egy alkalmazói program egyszerűen hozzáférhet a TCP/IP protokollokhoz. A socket lényegében egy IP-címből, ami egy gazdagépet, és egy úgynevezett portcímből áll, ami egy alkalmazást azonosít az adott gazdagépen. Ezzel a két adattal az Interneten egyértelműen azonosíthatóak az alkalmazások.

Áttekintés[szerkesztés | forrásszöveg szerkesztése]

Egy internetes socketet a következők egyedi kombinációja jellemez:

  • Helyi socketcím: a helyi IP-cím és portszám
  • Távoli socketcím: távoli IP-cím és portszám; csak kiépült TCP-socketeknél. Ahogy lejjebb a kliens-szerver alfejezetben olvasható, ez azért szükséges, mert a TCP-szerver egyszerre több klienst is kiszolgálhat. A szerver egy socketet hoz létre minden kliens számára, ezek helyi socketcíme akár megegyezhet is.
  • Protokoll: A szállítási protokoll (pl. TCP, UDP), raw socket vagy más. Így tehát a TCP port 53 és az UDP port 53 különböző socketekre utal.

Az operációs rendszer, illetve a socketet létrehozó alkalmazás egyedi azonosító számmal hivatkozik a socketre, ez a socket azonosítója vagy száma. Az operációs rendszer az IP- és szállítási rétegbeli protokollfejlécekből kibányássza a socketcím-információt, majd továbbítja az IP-csomag hasznos részét a megfelelő alkalmazás számára.

Első verziója a BSD 1983-as kiadásában jelent meg.

Az IETF RFC-kben, internetes szabványokban, számos kézikönyvben, és ebben a cikkben is a socket kifejezés olyan entitásra utal, amit egyértelműen azonosít a socket száma. Más szakirodalomban[1] a socket kifejezés a socket címére utal, tehát „egy IP-cím és egy portszám kombinációjára”. A socket eredeti, az RFC 147-ben szereplő, az 1971-es ARPANET-hez kötődő definíciója szerint „a socketet egy 32 bites szám határozza meg, ahol a páros socketek a fogadó, a páratlanok a küldő socketek”. Napjainkban azonban a socket-alapú kommunikáció kétirányú.

Unix-szerű operációs rendszereken és Microsoft Windows alatt a netstat parancssori eszközzel lehet listázni az adott pillanatban élő socketeket és a kapcsolódó információkat (Unix/Linuxon a fájlrendszer alatt létező unix socketeket is listázza).

Sockettípusok[szerkesztés | forrásszöveg szerkesztése]

Többfajta internetes socket létezik:

Vannak nem internetes socketek is, ezek más hálózati protokollokra épülnek, pl. az Systems Network Architecture-re (SNA).[3] Lásd még a Unix domain socketeket (UDS), amiket a belső processzközi kommunikációra használnak.

A socketek állapota és a kliens-szerver modell[szerkesztés | forrásszöveg szerkesztése]

A szolgáltatásokat nyújtó processzek, a szerverek induláskor, „figyel”, „hallgatózó” vagy „hallgató” (listening) állapotban lévő socketeket hoznak létre. Ezek a socketek arra várakoznak, hogy egy kliens megszólítsa őket. Egy hallgatózó TCP socket esetén a netstat által kijelzett távoli cím 0.0.0.0 és a távoli port 0 lehet. Egy TCP szerver jellemzően úgy szolgál ki egyszerre több klienst, hogy minden klienshez létrehoz egy gyerekprocesszt, és a TCP-kapcsolatok a gyerekprocessz és a kliens között épülnek ki. Egyedi, „dedikált socketek” jönnek létre minden ilyen kapcsolathoz. Ezek akkor tekinthetők „élő” (established) állapotúnak, amikor a távoli sockettel kiépül a socket-socket közötti virtuális áramkör (virtual connection/virtual circuit, VC), más néven TCP session vagy munkamenet, ami egy duplex bytestream átvitelét biztosítja.

A netstat parancs által kijelzett további TCP socketállapotok közé tartoznak: Syn-sent, Syn-Recv, Fin-wait1, Fin-wait2, Time-wait, Close-wait és Closed, amik a kapcsolat kiépülésének és lezárásának különböző lépéseire utalnak (a magyar változatokat lásd a netstat cikkben).[4]

A szerver tehát létrehozhat egyidejűleg több, ugyanazzal a helyi portszámmal és IP-címmel rendelkező TCP socketet, melyek mindegyikéhez tartozik egy saját gyermek-szerverprocessz, ami a saját kliensprocesszét szolgálja ki. Ezeket az operációs rendszer különböző socketeknek tekinti, mivel a távoli socket címe különbözik; tehát különböznek a socket-párban (rendezett szám-n-es vagy tuple), lásd lejjebb.

Egy UDP socket állapota sosem lehet „élő” (established), mivel az UDP kapcsolat nélküli. Így a netstat nem mutatja az UDP socketek állapotát. Egy UDP szerver nem is hoz létre az egyidejűleg kiszolgált kliensek számára külön gyerekprocesszeket, ehelyett ugyanaz a processz kezeli az összes távoli klienstől érkező adatcsomagokat, beérkezésük sorrendjében. Ez azt is jelenti, hogy az UDP socketeket nem azonosítja egyértelműen a távoli címük, csak a helyi cím, bár természetesen minden üzenethez tartozik egy megfelelő távoli socketcím.

Socketpárok[szerkesztés | forrásszöveg szerkesztése]

Az egymással kommunikáló helyi és távoli socketet együtt socketpár névvel illetik. Minden socketpár leírható egy egyedi rendezett 4-esként, ami a forrás és cél-IP-címekből és portcímekből áll, azaz a helyi és a távoli socketcímekből.[5][6] A föntebb leírtak szerint a TCP esetében minden egyedi socketpár-négyeséhez tartozik egy socketszám, míg az UDP-nél minden egyedi helyi socketcímhez tartozik egy socketszám.

Implementációs kérdések[szerkesztés | forrásszöveg szerkesztése]

A TCP Socket folyamatábrája

A socketeket általában egy API programkönyvtár segítségével valósítják meg, ahogy már az 1983-as Berkeley sockets esetében is történt. A legtöbb implementáció a Berkeley socketeken alapul, ahogy például az 1991-es Winsock is. Más API-megvalósítások is léteznek, mint a STREAMS-alapú Transport Layer Interface (TLI).

Az API-t használó alkalmazások fejlesztését socket-programozásnak vagy hálózati programozásnak is nevezik.

Néhány példa az API által nyújtott jellemző függvényekre vagy eljárásokra[7]:

  • A socket() létrehoz egy új, adott sockettípusnak megfelelő, egész számmal azonosított socketet, és rendszererőforrásokat rendel hozzá.
  • A bind() jellemzően szerveroldalon használatos, egy socketet hozzárendel egy socket-címstruktúrához, azaz egy adott helyi portszámhoz és IP-címhez.
  • A listen() szerveroldalon használatos, egy kapcsolt TCP socketet hallgatózó állapotba állít.
  • A connect() kliensoldalon használatos, szabad helyi portszámot rendel egy sockethez. TCP socket esetén megkísérel új TCP kapcsolatot létrehozni.
  • Az accept() szerveroldalon használatos. Elfogad egy a távoli klienstől érkezett, új TCP-kapcsolat létesítésére irányuló próbálkozást, és létrehoz egy új socketet, amihez az iménti TCP-kapcsolat címpárosát rendeli hozzá.
  • A send() és recv(), avagy write() és read(), esetleg recvfrom() és sendto() a távoli sockettel való kommunikációra (küldés/fogadásra) szolgálnak.
  • A close() hatására a rendszer felszabadítja a sockethez rendelt erőforrásokat. TCP esetén a kapcsolat megszakad.
  • A gethostbyname() és gethostbyaddr() feloldja a hostneveket és -címeket.
  • A select() socketek egy listájából visszaadja azokat, amelyekből olvasni lehet, amelyekbe írni lehet, vagy amelyekkel probléma adódott.
  • A poll() egy socket állapotának vizsgálatára szolgál. Tesztelni lehet, hogy a socket írható, olvasható, vagy probléma adódott vele.

Socketek hálózati eszközökben[szerkesztés | forrásszöveg szerkesztése]

A socket koncepciója alapvetően az internetprotokoll szállítási rétegében jelenik meg. A hálózati eszközök, pl. útválasztók és hálózati kapcsolók nem kell, hogy implementálják a szállítási réteget, mivel a switchek az adatkapcsolati rétegben, a routerek a hálózati rétegben működnek. Az állapottartó tűzfalak, hálózati címfordítók és proxyk azonban számon tartják az aktív socketpárokat. A fair queuing, a layer 3 switching és a routerek quality of service (QoS) megoldásainál a csomagok áramlása (packet flow) meghatározható a socketpárok információinak kinyerésével.

A hálózati eszközökön általában elérhetők a raw socketek, és útválasztási protokollokban (pl. IGMP, OSPF), illetve az Internet Control Message Protocolban (ICMP) van szükség rá.

Korai megvalósítások[szerkesztés | forrásszöveg szerkesztése]

Az 1983-as Berkeley sockets (úgy is, mint a BSD socket API) az 1983-ban megjelent 4.2BSD Unix operációs rendszer API-jaként jelent meg először. De csak 1989-ben tudott a Kaliforniai Egyetem (UC Berkeley) az AT&T licenckorlátozásaitól mentes operációs rendszert és hálózati könyvtárat kiadni.[8]

Az 1987-es Transport Layer Interface (TLI) az AT&T UNIX System V Release 3 (SVR3) hálózati API-ja volt,[9] ami a Release 4-be (SVR4) is utat talált.[10][11]

Szintén a korai implementációk közé tartoznak a TOPS-20-ra[12] , az MVS-re[12], a VM-re[12] és az IBM-DOS-ra (PCIP)[12][13] kihozott megvalósítások.

Jegyzetek[szerkesztés | forrásszöveg szerkesztése]

Források[szerkesztés | forrásszöveg szerkesztése]

  • Ez a szócikk részben vagy egészben az Internet socket című angol Wikipédia-szócikk ezen változatának fordításán alapul. Az eredeti cikk szerkesztőit annak laptörténete sorolja fel.

További információk[szerkesztés | forrásszöveg szerkesztése]