Tilbake
4.5
Nettverkskommunikasjon

4.5 Nettverkskommunikasjon

TCP/IP, sockets og klient-server-arkitektur.

60 min
6 oppgaver
TCP/IPSocketsKlient-serverProtokoller
Du leser den tradisjonelle versjonen
Din fremgang i kapitlet
0 / 6 oppgaver

Når programmer kommuniserer over nettverk – enten lokalt eller over internett – bruker de protokoller for å sikre at data sendes og mottas korrekt. Den grunnleggende modellen for nettverkskommunikasjon er klient-server-arkitekturen.

I dette kapittelet skal vi se på:
- TCP/IP-modellen
- Klient-server-arkitektur
- Sockets (nettverkskommunikasjon på lavt nivå)
- HTTP-protokollen i praksis
- Portnumre og IP-adresser

Klient-server-modellen
Klient-server er en arkitektur der:
- Klienten sender forespørsler (eksempel: nettleser, app)
- Serveren mottar forespørsler og sender svar (eksempel: webserver, API-server)

Eksempler:
- Du (klient) ber om en nettside → Webserveren (server) sender HTML
- Spotify-appen (klient) ber om en sang → Spotify-serveren (server) streamer musikk
- Python-program (klient) spør API → API-server (server) sender JSON-data

Serveren er alltid i gang og venter på forespørsler, mens klienten starter kommunikasjonen.

Internett bygger på TCP/IP-protokollstakken, som har fire lag:

4. Applikasjonslaget:
- HTTP, HTTPS, FTP, SMTP, DNS
- Det programmet ditt jobber med direkte

3. Transportlaget:
- TCP (Transmission Control Protocol): Pålitelig, ordnet levering
- UDP (User Datagram Protocol): Raskere, men upålitelig
- Håndterer portnumre (port 80 = HTTP, port 443 = HTTPS)

2. Internetlaget:
- IP (Internet Protocol): Adressering og ruting
- IP-adresser (IPv4: 192.168.1.1, IPv6)

1. Linklaget:
- Fysisk overføring (Ethernet, Wi-Fi)
- Ikke noe du programmerer direkte

Når du sender data:
1. Applikasjonslaget pakker data (f.eks. HTTP-forespørsel)
2. TCP deler opp i segmenter og legger til portnummer
3. IP legger til IP-adresser
4. Data sendes fysisk over nettverket

TCP vs UDP
TCP (Transmission Control Protocol):
✅ Pålitelig – garanterer at data kommer frem
✅ Ordnet – data kommer i riktig rekkefølge
✅ Feilsjekking – oppdager og retter feil
❌ Tregere – mye overhead
Bruksområder: HTTP, e-post, filoverføring

UDP (User Datagram Protocol):
✅ Raskere – mindre overhead
✅ Enklere – ingen forbindelsesoppsett
❌ Upålitelig – data kan gå tapt
❌ Ingen rekkefølge-garanti
Bruksområder: Videostreaming, gaming, DNS

Tommelfingerregel: Bruk TCP når data må være korrekt, UDP når hastighet er viktigere.

IP-adresse: Identifiserer en enhet på nettverket
- IPv4: 192.168.1.10 (4 deler, 0-255)
- IPv6: 2001:0db8:85a3::8a2e:0370:7334 (lengre, flere adresser)
- 127.0.0.1 eller localhost = din egen maskin

Portnummer: Identifiserer en tjeneste/applikasjon på enheten
- 0-65535 (totalt 65536 porter)
- 0-1023: Velkjente porter (well-known ports)
- 80: HTTP
- 443: HTTPS
- 22: SSH
- 21: FTP
- 1024-49151: Registrerte porter
- 49152-65535: Dynamiske/private porter

Adresse-format:

IP:PORT
192.168.1.10:8080
localhost:5000
example.com:80

En server kan ha mange tjenester på samme IP, men ulike porter.

Sockets

En socket er et endepunkt for nettverkskommunikasjon. Det er grensesnittet mellom applikasjonen din og nettverket.

Typer:
- Stream socket (TCP): Pålitelig, toveis datastrøm
- Datagram socket (UDP): Upålitelig, meldingsbasert

En socket identifiseres av:
- IP-adresse
- Portnummer
- Protokoll (TCP/UDP)

Python har en innebygd socket-modul for lavnivå nettverksprogrammering.

✏️Eksempel: Enkel TCP-server

La oss lage en enkel TCP-server som lytter på en port:

import socket

# Opprett socket
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

# Bind til adresse og port
host = 'localhost'
port = 9999

server_socket.bind((host, port))

# Lytt etter tilkoblinger (maks 5 i kø)
server_socket.listen(5)
print(f"Server lytter på {host}:{port}")

while True:
    # Aksepter tilkobling
    client_socket, address = server_socket.accept()
    print(f"Tilkobling fra {address}")

    # Motta data
    data = client_socket.recv(1024).decode('utf-8')
    print(f"Mottatt: {data}")

    # Send svar
    melding = f"Echo: {data}"
    client_socket.send(melding.encode('utf-8'))

    # Lukk tilkobling
    client_socket.close()

Forklaring:
- AF_INET = IPv4
- SOCK_STREAM = TCP
- bind() binder socket til IP og port
- listen() gjør serveren klar til å motta tilkoblinger
- accept() venter på klient (blokkerer)
- recv(1024) mottar opptil 1024 bytes

✏️Eksempel: Enkel TCP-klient

Her er en klient som kobler til serveren:

import socket

# Opprett socket
client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

# Koble til server
host = 'localhost'
port = 9999

client_socket.connect((host, port))
print(f"Koblet til {host}:{port}")

# Send data
melding = "Hei fra klienten!"
client_socket.send(melding.encode('utf-8'))

# Motta svar
svar = client_socket.recv(1024).decode('utf-8')
print(f"Svar fra server: {svar}")

# Lukk forbindelse
client_socket.close()

Kjøring:
1. Start serveren først (kjør server.py)
2. Start klienten (kjør client.py)

Output (server):

Server lytter på localhost:9999
Tilkobling fra ('127.0.0.1', 54321)
Mottatt: Hei fra klienten!

Output (klient):

Koblet til localhost:9999
Svar fra server: Echo: Hei fra klienten!

HTTP (HyperText Transfer Protocol) er applikasjonsprotokollenfor webben. Den bygger på TCP.

HTTP-forespørsel består av:
1. Startlinje: Metode, URL, HTTP-versjon
2. Headers: Metadata (Content-Type, User-Agent, osv.)
3. Tom linje
4. Body: Data (for POST/PUT)

Eksempel:

GET /api/users HTTP/1.1
Host: example.com
User-Agent: Mozilla/5.0
Accept: application/json

HTTP-respons består av:
1. Statuslinje: HTTP-versjon, statuskode, statusmelding
2. Headers: Metadata
3. Tom linje
4. Body: Innhold (HTML, JSON, osv.)

Eksempel:

HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 53

{"id": 1, "navn": "Emma", "alder": 18}
✏️Eksempel: HTTP-forespørsel med sockets

La oss sende en rå HTTP-forespørsel med sockets:

import socket

def http_request(host, path='/'):
    """Send HTTP GET-forespørsel med socket"""
    # Opprett socket
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

    # Koble til server (port 80 for HTTP)
    s.connect((host, 80))

    # Lag HTTP-forespørsel
    request = f"GET {path} HTTP/1.1\r\n"
    request += f"Host: {host}\r\n"
    request += "Connection: close\r\n"
    request += "\r\n"

    # Send forespørsel
    s.send(request.encode('utf-8'))

    # Motta svar
    response = b''
    while True:
        chunk = s.recv(4096)
        if not chunk:
            break
        response += chunk

    # Lukk socket
    s.close()

    # Dekod og returner
    return response.decode('utf-8', errors='ignore')

# Test
response = http_request('example.com', '/')
print(response[:500])  # Første 500 tegn

Output:

HTTP/1.1 200 OK
Content-Type: text/html; charset=UTF-8
Content-Length: 1256
...

<!doctype html>
<html>
<head>
    <title>Example Domain</title>
...

Dette viser hvordan HTTP egentlig fungerer under panseret – det er bare tekstmeldinger sendt over TCP!

Som du ser av forrige eksempel, er det mye arbeid å håndtere HTTP med rå sockets. Derfor bruker vi requests-biblioteket:

Med sockets (lavnivå):
- Må lage HTTP-forespørsel manuelt
- Må parse HTTP-svar manuelt
- Må håndtere encoding/decoding
- Må håndtere HTTPS separat (SSL/TLS)
- Mye kode for enkle oppgaver

Med requests (høynivå):
- Enkel API: requests.get(url)
- Automatisk parsing av JSON
- Automatisk håndtering av HTTPS
- Innebygd støtte for cookies, sessions, osv.
- Få linjer kode

Når bruke hva?
- requests: Når du jobber med HTTP/API-er (99% av tilfellene)
- sockets: Når du lager egne protokoller eller trenger full kontroll

For webutvikling og API-bruk: Alltid bruk requests.

✏️Praktisk eksempel: Chat-server

La oss lage en enkel chat-server som kan håndtere flere klienter:

import socket
import threading

klienter = []

def haandter_klient(client_socket, address):
    """Håndter en klient i egen tråd"""
    print(f"{address} koblet til")

    while True:
        try:
            # Motta melding
            melding = client_socket.recv(1024).decode('utf-8')
            if not melding:
                break

            print(f"{address}: {melding}")

            # Send til alle andre klienter
            for klient in klienter:
                if klient != client_socket:
                    klient.send(f"{address}: {melding}".encode('utf-8'))

        except:
            break

    # Fjern klient og lukk
    klienter.remove(client_socket)
    client_socket.close()
    print(f"{address} koblet fra")

def start_server():
    """Start chat-server"""
    server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    server.bind(('localhost', 9999))
    server.listen(5)

    print("Chat-server startet på localhost:9999")

    while True:
        client_socket, address = server.accept()
        klienter.append(client_socket)

        # Start ny tråd for hver klient
        thread = threading.Thread(target=haandter_klient, args=(client_socket, address))
        thread.start()

start_server()

Chat-klient:

import socket
import threading

def motta_meldinger(s):
    """Motta meldinger i egen tråd"""
    while True:
        try:
            melding = s.recv(1024).decode('utf-8')
            if melding:
                print(f"\n{melding}")
        except:
            break

# Koble til server
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('localhost', 9999))

# Start tråd for å motta meldinger
thread = threading.Thread(target=motta_meldinger, args=(s,))
thread.start()

# Send meldinger
while True:
    melding = input()
    s.send(melding.encode('utf-8'))

Dette viser praktisk bruk av sockets for sanntidskommunikasjon.

Oppsummering

I dette kapittelet har du lært:

- Klient-server-modellen: klient ber, server svarer.
- TCP vs. UDP: pålitelig og ordnet mot rask og forbindelsesloes.
- Sockets: endepunkt for nettverkskommunikasjon.
- TCP-server og -klient: enkel nettverkskommunikasjon i Python.
- Chat-server: praktisk eksempel på nettverksprogrammering.

Noekkelbegreper


BegrepForklaring
Klient-serverKlienten ber, serveren svarer
TCPPålitelig, ordnet dataoverfoering
SocketEndepunkt for nettverkskommunikasjon

Oppgaver

Dette kapitlet er skrevet av Anthropics toppmodeller (Claude Opus og Claude Fable) og er foreløpig ikke manuelt gjennomgått — kvalitetskontrollen gjøres av uavhengige KI-agenter, og innmeldte feil rettes fortløpende. Funnet en feil? Meld fra, så retter vi den. Les mer om hvordan innholdet lages.