Zajecia 10. - Obsluga sieci w Java - zadania do samodzielnego wykonania
Organizacja
- Czas: 20-30 min
- Forma: samodzielnie lub w parach
- Zakres: od podstaw TCP/UDP do prostych uslug HTTP
Zadanie A (latwe): Klient TCP - kalkulator sumy
Wymagania:
- Serwer TCP odbiera linie w formacie
a+b(np.12+30) - Serwer zwraca wynik jako tekst
- Klient wysyla jedno dzialanie i wyswietla odpowiedz
Wskazowki:
- po stronie serwera uzyj
split(„\+”) - waliduj wejscie i obsluz bledny format
- zamykaj zasoby przez
try-with-resources
Rozwiazanie (przykladowy serwer):
try (ServerSocket server = new ServerSocket(5001)) { while (true) { try (Socket client = server.accept(); BufferedReader in = new BufferedReader(new InputStreamReader(client.getInputStream())); PrintWriter out = new PrintWriter(client.getOutputStream(), true)) { String expr = in.readLine(); String[] parts = expr.split("\\+"); if (parts.length != 2) { out.println("BLAD FORMATU"); continue; } int a = Integer.parseInt(parts[0].trim()); int b = Integer.parseInt(parts[1].trim()); out.println(a + b); } catch (Exception ex) { // obsluga pojedynczego klienta } } }
Zadanie B (latwe/srednie): UDP licznik wiadomosci
Wymagania:
- Odbiorca UDP nasluchuje na porcie 6001
- Dla kazdego datagramu wypisuje tresc i numer kolejnosci
- Po odebraniu
STOPkonczy dzialanie
Wskazowki:
- porownuj tekst po
trim() - uzyj stalego bufora i nowego
DatagramPacketna kazdereceive
Rozwiazanie (przykladowe):
int counter = 0; try (DatagramSocket socket = new DatagramSocket(6001)) { byte[] buffer = new byte[1024]; while (true) { DatagramPacket packet = new DatagramPacket(buffer, buffer.length); socket.receive(packet); String text = new String(packet.getData(), 0, packet.getLength(), StandardCharsets.UTF_8).trim(); counter++; System.out.println(counter + ": " + text); if ("STOP".equalsIgnoreCase(text)) break; } }
Zadanie C (srednie): Klient HTTP - pobieranie JSON
Wymagania:
- Pobierz dane z endpointu HTTP GET
- Wypisz kod statusu i 3 wybrane pola z JSON (np. id, title, completed)
- Dodaj obsluge timeout
Wskazowki:
- uzyj
HttpClientiHttpRequest - do prostego demo mozesz parsowac tekstowo lub przez biblioteke JSON
- endpoint testowy:
https://jsonplaceholder.typicode.com/todos/1
Rozwiazanie (przykladowe):
HttpClient client = HttpClient.newBuilder() .connectTimeout(Duration.ofSeconds(5)) .build(); HttpRequest request = HttpRequest.newBuilder() .uri(URI.create("https://jsonplaceholder.typicode.com/todos/1")) .timeout(Duration.ofSeconds(5)) .GET() .build(); HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString()); System.out.println("Status: " + response.statusCode()); System.out.println(response.body());
Zadanie D (srednie+): Wielowatkowy czat TCP (wersja mini)
Wymagania:
- Serwer akceptuje wielu klientow
- Kazda wiadomosc klienta jest rozglaszana do pozostalych
- Obsluz rozlaczenie klienta
Wskazowki:
- lista klientow:
CopyOnWriteArrayList<PrintWriter> - kazdy klient w osobnym watku
- przed broadcast usun nieaktywne polaczenia
Rozwiazanie (szkic):
static List<PrintWriter> clients = new CopyOnWriteArrayList<>(); void handle(Socket socket) { try (socket; BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream())); PrintWriter out = new PrintWriter(socket.getOutputStream(), true)) { clients.add(out); String line; while ((line = in.readLine()) != null) { for (PrintWriter c : clients) { if (c != out) c.println(line); } } } catch (IOException ignored) { } finally { // usun writer klienta z listy } }
Zadanie E (trudniejsze): Mini REST API - notatki
Wymagania:
- Serwer HTTP z endpointami:
GET /notes- lista notatek (JSON)POST /notes- dodanie notatki (tekst)
- Przechowywanie w pamieci (
List<String>)
Wskazowki:
- start:
HttpServer.create(new InetSocketAddress(8081), 0) - dla
POSTodczytaj body zexchange.getRequestBody() - ustaw odpowiednie kody: 200, 201, 405
Rozwiazanie (szkic):
List<String> notes = Collections.synchronizedList(new ArrayList<>()); server.createContext("/notes", exchange -> { String method = exchange.getRequestMethod(); if ("GET".equalsIgnoreCase(method)) { String json = notes.stream().map(s -> "\"" + s + "\"").collect(Collectors.joining(",", "[", "]")); byte[] bytes = json.getBytes(StandardCharsets.UTF_8); exchange.sendResponseHeaders(200, bytes.length); try (OutputStream os = exchange.getResponseBody()) { os.write(bytes); } } else if ("POST".equalsIgnoreCase(method)) { String body = new String(exchange.getRequestBody().readAllBytes(), StandardCharsets.UTF_8).trim(); notes.add(body); exchange.sendResponseHeaders(201, -1); } else { exchange.sendResponseHeaders(405, -1); } });
Zadanie F (dla chetnych): HTTPS + naglowek autoryzacji
Wymagania:
- Wyslij zapytanie HTTPS GET z naglowkiem
Authorization: Bearer … - Wypisz status i czas odpowiedzi
- Dodaj retry do 3 prob dla bledow 5xx
Wskazowki:
- zmierz czas przez
System.nanoTime() - token przekazuj z argumentu programu albo zmiennej srodowiskowej
- nie loguj calego tokenu
Rozwiazanie (fragment):
long start = System.nanoTime(); HttpRequest req = HttpRequest.newBuilder() .uri(URI.create("https://example.com/api/me")) .header("Authorization", "Bearer " + token) .GET() .build(); HttpResponse<String> res = client.send(req, HttpResponse.BodyHandlers.ofString()); long ms = (System.nanoTime() - start) / 1_000_000; System.out.println("Status=" + res.statusCode() + ", czas=" + ms + "ms");
Kryteria oceny
- Dzialajaca komunikacja klient-serwer
- Poprawna obsluga bledow i timeoutow
- Czytelnosc kodu i podzial odpowiedzialnosci
- Plus: watki, walidacja danych, sensowne logowanie
Proponowany dobor zadan na 20-30 min
- Grupa poczatkujaca: A + B
- Grupa srednia: A + C + fragment D
- Grupa zaawansowana: C + D lub E (+F dla chetnych)