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 program kommuniserer over nettverk – anten lokalt eller over internett – brukar dei protokollar for å sikre at data blir sende og mottekne korrekt. Den grunnleggjande modellen for nettverkskommunikasjon er klient-server-arkitekturen.

I dette kapittelet skal vi sjå på:
- TCP/IP-modellen
- Klient-server-arkitektur
- Sockets (nettverkskommunikasjon på lågt nivå)
- HTTP-protokollen i praksis
- Portnummer og IP-adresser

Klient-server-modellen
Klient-server er ein arkitektur der:
- Klienten sender førespurnader (eksempel: nettlesar, app)
- Serveren tek imot førespurnader og sender svar (eksempel: webserver, API-server)

Eksempel:
- Du (klient) ber om ei nettside → Webserveren (server) sender HTML
- Spotify-appen (klient) ber om ein song → Spotify-serveren (server) streamar musikk
- Python-program (klient) spør API → API-server (server) sender JSON-data

Serveren er alltid i gang og ventar på førespurnader, medan klienten startar kommunikasjonen.

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

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

3. Transportlaget:
- TCP (Transmission Control Protocol): Påliteleg, ordna levering
- UDP (User Datagram Protocol): Raskare, men upåliteleg
- Handterer portnummer (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)
- Ikkje noko du programmerer direkte

Når du sender data:
1. Applikasjonslaget pakkar data (f.eks. HTTP-førespurnad)
2. TCP deler opp i segment og legg til portnummer
3. IP legg til IP-adresser
4. Data blir sende fysisk over nettverket

TCP vs UDP
TCP (Transmission Control Protocol):
✅ Påliteleg – garanterer at data kjem fram
✅ Ordna – data kjem i rett rekkjefølgje
✅ Feilsjekking – oppdagar og rettar feil
❌ Tregare – mykje overhead
Bruksområde: HTTP, e-post, filoverføring

UDP (User Datagram Protocol):
✅ Raskare – mindre overhead
✅ Enklare – inga oppkopling
❌ Upåliteleg – data kan gå tapt
❌ Ingen rekkjefølgje-garanti
Bruksområde: Videostreaming, gaming, DNS

Tommelfingerregel: Bruk TCP når data må vere korrekt, UDP når fart er viktigare.

IP-adresse: Identifiserer ei eining på nettverket
- IPv4: 192.168.1.10 (4 delar, 0-255)
- IPv6: 2001:0db8:85a3::8a2e:0370:7334 (lengre, fleire adresser)
- 127.0.0.1 eller localhost = di eiga maskin

Portnummer: Identifiserer ei teneste/applikasjon på eininga
- 0-65535 (totalt 65536 portar)
- 0-1023: Velkjende portar (well-known ports)
- 80: HTTP
- 443: HTTPS
- 22: SSH
- 21: FTP
- 1024-49151: Registrerte portar
- 49152-65535: Dynamiske/private portar

Adresse-format:

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

Ein server kan ha mange tenester på same IP, men ulike portar.

Sockets

Ein socket er eit endepunkt for nettverkskommunikasjon. Det er grensesnittet mellom applikasjonen din og nettverket.

Typar:
- Stream socket (TCP): Påliteleg, toveis datastraum
- Datagram socket (UDP): Upåliteleg, meldingsbasert

Ein socket blir identifisert av:
- IP-adresse
- Portnummer
- Protokoll (TCP/UDP)

Python har ein innebygd socket-modul for lågnivå nettverksprogrammering.

✏️Eksempel: Enkel TCP-server

La oss lage ein enkel TCP-server som lyttar på ein 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() bind socket til IP og port
- listen() gjer serveren klar til å ta imot tilkoplingar
- accept() ventar på klient (blokkerer)
- recv(1024) tek imot opptil 1024 bytes

✏️Eksempel: Enkel TCP-klient

Her er ein klient som koplar 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()

Køyring:
1. Start serveren først (køyr server.py)
2. Start klienten (køyr 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 applikasjonsprotokollen for webben. Han byggjer på TCP.

HTTP-førespurnad 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: Innhald (HTML, JSON, osv.)

Eksempel:

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

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

La oss sende ein rå HTTP-førespurnad 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 korleis HTTP eigentleg fungerer under panseret – det er berre tekstmeldingar sende over TCP!

Som du ser av førre eksempel, er det mykje arbeid å handtere HTTP med rå sockets. Difor brukar vi requests-biblioteket:

Med sockets (lågnivå):
- Må lage HTTP-førespurnad manuelt
- Må parse HTTP-svar manuelt
- Må handtere encoding/decoding
- Må handtere HTTPS separat (SSL/TLS)
- Mykje kode for enkle oppgåver

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

Når bruke kva?
- requests: Når du jobbar med HTTP/API-ar (99 % av tilfella)
- sockets: Når du lagar eigne protokollar eller treng full kontroll

For webutvikling og API-bruk: Bruk alltid requests.

✏️Praktisk eksempel: Chat-server

La oss lage ein enkel chat-server som kan handtere fleire klientar:

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 svarar.
- TCP vs. UDP: påliteleg og ordna mot rask og forbindelseslaus.
- Sockets: endepunkt for nettverkskommunikasjon.
- TCP-server og -klient: enkel nettverkskommunikasjon i Python.
- Chat-server: praktisk eksempel på nettverksprogrammering.

Nøkkelbegrep


BegrepForklaring
Klient-serverKlienten ber, serveren svarar
TCPPåliteleg, ordna dataoverføring
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.