gadget59.ru лекции
Сокеты + JSON · Лекция · 28 слайдов

Сокеты в Java и JSON: Socket, ServerSocket, библиотека Jackson

Сокеты в Java и JSON

До сих пор наши программы работали в одиночку: читали файлы, писали в базы данных, рисовали окна. Но современные приложения почти всегда общаются по сети: браузер запрашивает страницу у сервера, мобильное приложение получает данные из облака, игра соединяется с другими игроками.

🔌 Сокеты 🖥️ Socket 📡 ServerSocket 📄 JSON 🔧 Jackson
Сегодня мы разберём два инструмента, которые работают вместе: сокеты (для передачи данных по сети) и JSON (для упаковки этих данных в удобный формат). В конце — практика, где мы соберём клиент-серверное приложение.
Формат: лекция + практика. Понадобится JDK и библиотека Jackson (подключим через Maven).

План лекции

Сегодня мы соединим две темы: сеть и формат данных.

  • 1 Что такое сокет и зачем он нужен
  • 2 TCP и UDP — два протокола передачи
  • 3 Класс Socket — клиент
  • 4 Класс ServerSocket — сервер
  • 5 Как передаются данные: потоки ввода-вывода
  • 6 Проблема: как передать сложный объект
  • 7 JSON — текстовый формат данных
  • 8 Библиотека Jackson
  • 9 Сериализация: объект → JSON
  • 10 Десериализация: JSON → объект
  • 11 Собираем всё вместе
  • 12 Типичные ошибки
Если вы не знакомы с потоками ввода-вывода — ничего страшного. Мы разберём всё по шагам.

Что такое сокет?

Сокет (от английского socket — «гнездо», «разъём») — это программный интерфейс, который позволяет двум программам обмениваться данными по сети.

Представьте себе телефонный разговор. Чтобы позвонить, вам нужен номер (IP-адрес) и добавочный (порт). Сокет — это «трубка», через которую вы говорите.

Программа A
→
Сокет
→
Сеть
→
Сокет
→
Программа B
В Java сокеты реализованы в пакете java.net. Это часть стандартной библиотеки, ничего дополнительно скачивать не нужно.

TCP и UDP — два протокола

Сокеты работают поверх одного из двух протоколов передачи данных.

📞
TCP
Transmission Control Protocol (протокол управления передачей). Надёжный, гарантирует доставку и порядок. Как телефонный разговор.
📮
UDP
User Datagram Protocol (протокол пользовательских датаграмм). Быстрый, но без гарантий. Как почтовые открытки.
КритерийTCPUDP Гарантия доставкиданет Порядок пакетовсохраняетсяне гарантируется Скоростьмедленнеебыстрее Где используетсявеб, почта, файлыигры, видео, DNS
В этой лекции мы работаем с TCP — он надёжнее и проще для понимания.

Класс Socket — клиент

Socket — это класс, который представляет клиентскую сторону соединения. Клиент подключается к серверу по IP-адресу и порту.

import java.net.Socket; // Подключиться к серверу localhost на порт 8080 Socket socket = new Socket("localhost", 8080);
  • "localhost" — адрес сервера. Если сервер на другом компьютере, указывается его IP.
  • 8080 — порт. Порт — это «дверь» на сервере, через которую принимаются подключения.
  • Если сервер недоступен, будет выброшено исключение ConnectException.
Порт — это число от 0 до 65535. Порты до 1024 заняты системными службами. Для своих приложений используйте порты от 1024 и выше.

Класс ServerSocket — сервер

ServerSocket — это класс, который представляет серверную сторону. Он «слушает» порт и ждёт, пока клиент подключится.

import java.net.ServerSocket; import java.net.Socket; // Сервер слушает порт 8080 ServerSocket serverSocket = new ServerSocket(8080); // Ждём подключения клиента (блокирует выполнение) Socket clientSocket = serverSocket.accept();
  • accept() блокирует программу, пока не придёт клиент.
  • Когда клиент подключился, возвращается новый Socket — соединение именно с этим клиентом.
  • Сам ServerSocket продолжает слушать порт для следующих клиентов.
accept() ждёт вечно, если никто не подключается. В реальных серверах это нормально — сервер работает постоянно.

Как передаются данные

После установки соединения данные передаются через потоки ввода-вывода сокета.

Клиент
→
OutputStream
→
Сеть
→
InputStream
→
Сервер
// Отправить данные серверу OutputStream out = socket.getOutputStream(); out.write("Привет!".getBytes()); // Прочитать данные от сервера InputStream in = socket.getInputStream(); int b = in.read();
Это те же самые InputStream и OutputStream, которые мы использовали для файлов. Сокет — это просто «файл», который находится на другом компьютере.

Проблема: как передать объект

Через сокет можно передавать байты. Но как передать объект Person(name, age)?

❌
Склеить в строку
«Иван,25» — работает, но легко ошибиться: а если в имени есть запятая?
✅
JSON
Структурированный формат, который понимают все языки.
// JSON-представление объекта Person { "name": "Иван", "age": 25 }
JSON (JavaScript Object Notation, «запись объектов JavaScript») — это текстовый формат обмена данными. Он читается человеком и легко разбирается программами.

JSON — основные правила

JSON состоит из пар «ключ: значение» и массивов.

{ "name": "Иван", "age": 25, "isStudent": true, "hobbies": ["Java", "Базы данных"] }
ТипПример строка"Иван" число25 логическоеtrue / false массив["Java", "Python"] объект{ "name": "Иван" } nullnull
JSON используется почти везде: в веб-API, в конфигурационных файлах, при обмене данными между программами.

Библиотека Jackson

Вручную собирать и разбирать JSON неудобно. Для этого есть библиотеки. Самая популярная в Java — Jackson.

<!-- pom.xml (Maven) --> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>2.15.2</version> </dependency>
📤
Сериализация
Java-объект → JSON-строка
📥
Десериализация
JSON-строка → Java-объект
Jackson — не единственная библиотека. Есть ещё Gson от Google. Но Jackson — стандарт в корпоративной разработке.

Сериализация: объект → JSON

Превратить Java-объект в JSON-строку очень просто.

import com.fasterxml.jackson.databind.ObjectMapper; ObjectMapper mapper = new ObjectMapper(); Person person = new Person("Иван", 25); String json = mapper.writeValueAsString(person); System.out.println(json); // {"name":"Иван","age":25}
  • ObjectMapper — главный класс Jackson.
  • writeValueAsString() — превращает объект в JSON.
  • Jackson сам обходит все поля объекта и создаёт JSON.
Чтобы Jackson мог сериализовать объект, у класса должны быть геттеры (или публичные поля).

Десериализация: JSON → объект

Обратная операция — из JSON-строки получить Java-объект.

String json = "{\"name\":\"Иван\",\"age\":25}"; Person person = mapper.readValue(json, Person.class); System.out.println(person.getName()); // Иван System.out.println(person.getAge()); // 25
  • readValue() — принимает JSON-строку и класс, в который нужно превратить.
  • Jackson сам создаёт объект и заполняет поля.
  • Для этого у класса должен быть конструктор без аргументов (или аннотации Jackson).
Сериализация и десериализация — это «перевод» между миром Java-объектов и миром текста (JSON).

Собираем всё вместе: клиент и сервер

Вот как выглядит полная цепочка передачи объекта по сети.

Клиент: Person → JSON
↓
JSON-строка → байты → сокет
↓
Сервер: сокет → байты → JSON
↓
JSON → Person
// Клиент отправляет String json = mapper.writeValueAsString(person); out.println(json); // Сервер получает String received = in.readLine(); Person person = mapper.readValue(received, Person.class);
Теперь мы можем передавать по сети любые объекты, а не только строки. Это основа любого сетевого приложения.

Пример клиента

Полный код клиента, который подключается к серверу и отправляет JSON.

import java.io.*; import java.net.*; import com.fasterxml.jackson.databind.ObjectMapper; public class Client { public static void main(String[] args) throws Exception { Socket socket = new Socket("localhost", 8080); ObjectMapper mapper = new ObjectMapper(); Person person = new Person("Иван", 25); String json = mapper.writeValueAsString(person); PrintWriter out = new PrintWriter(socket.getOutputStream(), true); out.println(json); socket.close(); } }
PrintWriter с параметром true автоматически сбрасывает буфер после каждой строки. Это удобно для сокетов.

Пример сервера

Сервер принимает JSON, разбирает его и выводит данные.

import java.io.*; import java.net.*; import com.fasterxml.jackson.databind.ObjectMapper; public class Server { public static void main(String[] args) throws Exception { ServerSocket serverSocket = new ServerSocket(8080); System.out.println("Сервер запущен на порту 8080"); Socket clientSocket = serverSocket.accept(); System.out.println("Клиент подключился"); BufferedReader in = new BufferedReader( new InputStreamReader(clientSocket.getInputStream())); String json = in.readLine(); ObjectMapper mapper = new ObjectMapper(); Person person = mapper.readValue(json, Person.class); System.out.println("Получен: " + person.getName()); clientSocket.close(); serverSocket.close(); } }
Запустите сервер, потом клиент — и увидите, как данные передаются по сети.

Типичные ошибки

1. Забыли закрыть сокет
Сокеты — это ресурсы. Их нужно закрывать через try-with-resources или close().
2. Порт уже занят
Ошибка BindException. Значит, кто-то уже слушает этот порт. Выберите другой.
3. Сервер не запущен
Клиент получит ConnectException. Сначала запускайте сервер, потом клиента.
4. Jackson не видит поля
Нужны геттеры и конструктор без аргументов. Или аннотации @JsonProperty.
5. Забыли про кодировку
При передаче русских символов используйте PrintWriter и BufferedReader с указанием UTF-8.
6. Слушаете не тот интерфейс
Если сервер на другом компьютере, клиент должен подключаться к его IP, а не к localhost.

Безопасность: SSL/TLS

Обычные сокеты передают данные открытым текстом. Любой, кто «слушает» сеть, может их прочитать.

🔓
Socket
Данные передаются как есть. Подходит для локальной сети и нечувствительных данных.
🔒
SSLSocket
Данные шифруются. Нужно для паролей, личной информации, банковских данных.
// Вместо Socket используем SSLSocket SSLSocketFactory factory = (SSLSocketFactory) SSLSocketFactory.getDefault(); SSLSocket socket = (SSLSocket) factory.createSocket("example.com", 443);
SSLSocket — часть стандартной библиотеки Java (javax.net.ssl). Но для реальных приложений лучше использовать HTTP-клиенты, которые делают всё сами.

Многопоточность на сервере

Наш сервер обрабатывает только одного клиента за раз. Что, если их десять?

while (true) { Socket client = serverSocket.accept(); // Каждого клиента обрабатываем в отдельном потоке new Thread(() -> { // обработать клиента }).start(); }
  • Основной поток продолжает слушать порт.
  • Каждый клиент обслуживается в своём потоке.
  • Клиенты не мешают друг другу.
Именно так работают реальные серверы. Потоки мы разбирали в лекции по многопоточности (oaip21.html).

Шпаргалка

Сохраните этот слайд — здесь всё, что нужно для практики.

ЗадачаКод Подключиться к серверуnew Socket("host", port) Запустить серверnew ServerSocket(port) Принять клиентаserverSocket.accept() Отправить строкуnew PrintWriter(socket.getOutputStream(), true).println("text") Прочитать строкуnew BufferedReader(new InputStreamReader(socket.getInputStream())).readLine() Объект → JSONmapper.writeValueAsString(obj) JSON → объектmapper.readValue(json, Person.class)
Этих команд достаточно для 90% сетевых задач.

Итоги лекции

Подведём итоги. Вот что вы теперь знаете.

  • ✅ Сокет — интерфейс для обмена данными между программами по сети.
  • ✅ TCP — надёжный протокол с гарантией доставки.
  • ✅ Socket — клиентская сторона соединения.
  • ✅ ServerSocket — серверная сторона, слушает порт.
  • ✅ Потоки — данные передаются через InputStream и OutputStream.
  • ✅ JSON — текстовый формат для передачи объектов.
  • ✅ Jackson — библиотека для сериализации и десериализации JSON.
  • ✅ Сериализация — объект → JSON.
  • ✅ Десериализация — JSON → объект.
  • ✅ try-with-resources — обязательное закрытие сокетов.
На практике мы соберём полноценное клиент-серверное приложение, которое передаёт объекты через сокеты в формате JSON.

Домашнее задание

Задания для самостоятельной работы. Первые три обязательны, остальные — для оценки «отлично».

  1. Подключите Jackson к проекту через Maven.
  2. Создайте класс Book(title, author, year) с геттерами и конструктором без аргументов.
  3. Напишите программу, которая сериализует Book в JSON и выводит результат в консоль.
  4. Напишите программу, которая десериализует JSON-строку обратно в Book.
  5. Запустите сервер и клиент из лекции. Убедитесь, что данные передаются.
  6. Доработайте сервер, чтобы он отвечал клиенту «Получено!».
Если задание кажется сложным — разбейте его на части. Одна операция = один метод.

Что дальше?

На практике мы соберём настоящее клиент-серверное приложение.

  • Практика: создание клиент-серверного приложения «Список книг».
  • Клиент отправляет книгу в JSON на сервер.
  • Сервер принимает, сохраняет в список и отвечает подтверждением.
  • Клиент запрашивает список всех книг.
  • Сервер отправляет список в JSON.
Это финальный шаг: соединить сокеты, JSON и объектно-ориентированное программирование в одном приложении.

Советы перед практикой

Несколько советов, которые сэкономят время.

🖥️
Запускайте сервер первым
Потом клиент. Иначе — ошибка подключения.
📖
Читайте ошибки
Java пишет, что именно не так и в какой строке.
🧪
Экспериментируйте
Меняйте данные, добавляйте поля, ломайте и чините.
🚫
Не бойтесь ошибок
Каждая ошибка — подсказка.
Сокеты + JSON — это основа любого сетевого приложения. Освоив это, вы сможете делать чаты, игры, API и многое другое.

Спасибо за внимание!

🔌

Сокеты — это мост между программами

Теперь вы умеете передавать данные по сети и упаковывать их в JSON. Это фундамент современных приложений.

🔌 Сокеты 📄 JSON 🔧 Jackson 🚀 практика