A TCP/IP datagrammok kezelésében két különböző protokoll játszik szerepet. Az üzenetek széttördelését, összeállítását, az elveszett részek újraadását, a datagrammok helyes sorrendjének visszaállítását mind a TCP (transmission control protocol - átvitelvezérlési protokoll) végzi. Az egyes datagrammok útvonalának a meghatározását (routing) az IP (internet protocol) hajtja végre. Mindez azt a látszatot kelti, hogy a munka tetemes része a TCP-re hárul. Kis kiterjedésű hálózatokban ez így is van, azonban az Interneten egy datagrammnak a rendeltetési helyre való juttatása igen összetett feladatot jelenthet. Egy datagramm több hálózaton mehet keresztül míg végül eljut a célállomásra. Például a Rutgers Egyetemről kiindulva a John von Neumann Supercomputing Center-ig soros vonalon keresztül, majd onnan (egy pár Ethernet hálózaton átjutva) 56Kbaud telefonvonalakon keresztül jut el egy másik NSFnet hálózatra stb...A különböző átviteli közegekből adódó inkompatibilitások kezelése és a célállomásokhoz vezető útvonalak végigkövetése komplex feladat. Meg kell jegyezni azonban, hogy a TCP és az IP közti interfész rendkívül egyszerű: a TCP egy datagrammot ad át az IP-nek egy rendeltetési címmel együtt. Az IP semmit sem tud arról, hogy ez az információ hogyan viszonyul más datagrammokhoz.
Aki idáig eljutott, abban felmerülhet a gyanú, hogy az eddig elmondottak nem alkotnak egészen teljes keretet. Szó volt ugyan az Internet címekről, de arról nem: vajon hogyan lehet egy adott rendszer esetén az ahhoz befutó különböző kapcsolatokat nyomon követni? Nyilván nem elegendő csupán a datagrammnak a helyes címre való továbbítása. A TCP-nek még azt is tudnia kell, hogy az adott datagramm melyik kapcsolathoz tartozik. A probléma megoldását a demultiplexálás v. nyalábbontás néven ismert eljárás adja, amely a TCP/IP-ben valójában több különböző szinten folyik. A demultiplexáláshoz szükséges információt az ún. fejlécek hordozzák. A fejléc azokat az extra okteteket jelenti, amelyeket a különböző protokollok ragasztanak a datagrammok elejére, hogy azokat nyomon tudják követni. A dolog hasonlít ahhoz, amikor a levelet a borítékba tesszük, majd azt megcímezzük. A különbség annyi, hogy a modern hálózatokban ez jóval többször történik: olyan mintha a levelet egy kis borítékba tennénk, majd azt a titkárnőnk egy nagyobb borítékba helyezné, amit a központ egy még nagyobb borítékban továbbítana stb...Az alábbiakban a tipikus TCP/IP hálózaton keresztül haladó üzenetre rárakódó fejléceket tekintjük át:
Kezdetnek vegyünk egy egyszerű adatfolyamot (pl. egy állomány tartalma), amelyet egy másik számítógépnek szeretnénk elküldeni:
....................................................................Ezt a TCP megcsonkítja. (Ennek érdekében tudatni kell a protokollal, hogy mekkora az a maximális adatméret, amelyet az adott hálózat még kezelni tud. Valójában az összeköttetés két végén a TCP-k közlik egymással az általuk kezelhető maximális méretet, majd veszik a kisebbiket.)
.... .... .... .... .... .... .... .... ....Minden datagramm elé egy TCP fejléc kerül, amely legalább 20 oktetből áll. Ezek közül a legfontosabbak: egy forrás- és egy célport, valamint egy sorszám. A portok az összeköttetések végpontjait azonosítják. Tegyük fel például, hogy egyszerre 3 felhasználó továbbít állományokat. A TCP ezekhez az átvitelekhez az 1000, 1001 és 1002 portokat rendelheti. Datagramm küldésekor az allokált port válik a forrásporttá, mivel innen indul ki a datagramm. A kapcsolat másik végénél lévő TCP szintén hozzárendeli a saját portját az átvitelhez. A küldő oldali TCP-nek a célport számát is tudnia kell (ezt az információt a kapcsolat felépülésekor szerzi meg; lásd lejjebb), amelyet az a fejléc célport mezőjébe helyez. Ha a másik oldalról érkezik egy datagramm, akkor annak TCP fejlécében a forrás- és a célportok tartalma ellentétes, hiszen ekkor az a forrás, ez pedig a rendeltetési hely. Minden datagrammnak van egy sorszáma, amely a vevő oldalt arról biztosítja, hogy minden adatot helyes sorrendben kapjon meg, és ne veszítsen el egyet se a datagrammok közül. (További részleteket illetően lásd a TCP specifikációkat.) A TCP valójában nem a datagrammokat, hanem az okteteket sorszámozza. Ha például minden datagramm 500 oktet adatot tartalmaz, akkor az első datagramm sorszáma 0, a másodiké 500, a következőé 1000, az az utánié 1500 stb...lesz. Végül essék szó az ellenőrzőösszegről: ez egy olyan szám, amelyet a datagrammban lévő oktetek összeadásával kapunk (többé-kevésbé; lásd a TCP specifikációt. Az OSI szállítási rétege ezt úgy képzi, hogy az adatokat 16 bites számokként összeadja, majd veszi ennek egyes komplemensét - a fordító.) Az eredmény aztán bekerül a TCP fejlécbe. A vevő oldali TCP is kiszámítja a fenti algoritmus szerinti ellenőrzőösszeget. Ha a kettő nem egyezik, akkor a datagrammal az átvitel közben valahol valami baj történt és azt a protokoll eldobja. A datagramm mostanra tehát így néz ki:
<<-------------------------32 bit------------------------------>> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Forrásport | Célport | | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -+-+-+-+-+-+ | Sorszám | | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Ráültetett nyugta | | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | TCP | Fenn- |U|A|P|R|S|F| | | |fejrész| tartott |R|C|S|S|Y|I| Ablak | |hossza | |G|K|H|T|N|N| | | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Ellenőrzőösszeg | Sürgősségi mutató | | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | tényleges adatok ... következő 500 oktet | .......Ha a TCP fejlécet T-vel jelöljük, akkor az eredeti állományunk így néz ki:
T.... T.... T.... T.... T.... T.... T.... T.... T....A fejlécben vannak olyan mezők, amelyekről még nem esett szó. A legtöbbjük az összeköttetés menedzselésével kapcsolatos információkat hordozza. A datagrammnak a rendeltetési helyre való megérkezését a vevő egy nyugtával hozza a küldő oldal tudomására. Ez a szám a datagramm TCP fejlécében a Ráültetett nyugta mezőben jelenik meg. Például egy olyan csomag elküldése, amelynek nyugtamezőjében 1500 szerepel, azt jelenti, hogy az 1500-as oktetig bezárólag minden datagramm eljutott a rendeltetési helyre. Amennyiben a küldő oldal egy adott időn belül nem kap nyugtát, akkor újból elküldi az adatot. Az Ablak mezőben lévő érték az összeköttetés alatt forgalomban lévő adatok mennyiségét határozza meg. Nem lenne szerencsés, ha minden egyes datagramm elküldése előtt meg kellene várni az előző nyugtáját, mert így a forgalom rendkívüli mértékben lelassulna. Másrészt viszont nem lehet folytonosan küldeni az adatokat, hiszen például egy gyorsabb számítógép adatárama elárasztaná a lassabb gépeket. Ennek megoldására mindkét oldal az Ablak mezőben elhelyezett oktetek számával közli, hogy éppen mekkora adatmennyiséget képes még befogadni. Az adatok vételével ez a szám, azaz az ablak mérete, folyamatosan csökken. Amikor eléri a nullát a küldőnek szüneteltetnie kell az adatok továbbítását. A vevő ablakmérete az adatok feldolgozása során nő, ami jelzi, hogy kész további adatok fogadására. Gyakran ugyanaz a datagramm használható az újabb adatok engedélyezésére és nyugtázásra is (aktualizált ablak segítségével). A Sürgősségi mutató mezőben lévő érték beállításával bármelyik oldal utasíthatja a másikat arra, hogy a feldolgozást egy adott oktettel folytassa. A gyakorlatban többek között ez az aszinkron eseményekkel kapcsolatban használatos, például amikor vezérlőkarakter vagy más, a kimenetet megszakító parancs kerül továbbításra. A többi mezőről ez a dokumentum nem hivatott szólni.