Бібліотека прикладів додатків Java
8.9. Надсилання широкомовних повідомлень
Програма забезпечує можливість надсилання широкомовних (broadcast) повідомлень через мережу TCP/IP. Виконує одночасно роль клієнта та сервера. Приклад демонструє використання класів DatagramSocket та DatagramPacket.
Трохи теорії
Датаграмні сокети не гарантують доставку пакетів даних, але працюють швидше потокових і забезпечують можливість широкомовного розсилання пакетів даних одночасно всім вузлам мережі. Для роботи з такими сокетами програма має створити об'єкт класу DatagramSocket, а також підготувати об'єкт класу DatagramPacket. У нього буде записано блок даних, прийнятий від партнера по мережі.
У класі DatagramSocket є два конструктори, прототипи яких представлені нижче:
Перший із цих конструкторів дозволяє визначити порт для сокету, другий передбачає використання будь-якого вільного порту.
Канал, а також вхідні та вихідні потоки створювати не потрібно. Дані передаються та приймаються методами send та receive, визначеними у класі DatagramSocket:
Після використання сокет слід закрити методом close:
Підготовка об'єкта класу DatagramPacket для прийому пакетів виконується за допомогою наступного конструктора:
Інформація про те, до якого вузол і порт потрібно доставити пакет даних, зберігається над сокеті, а пакеті, тобто у об'єкті класу DatagramPacket.
Опис прикладу
Програма DatagramChat, вихідний текст якої ми розглянемо в цьому розділі, призначена для широкомовної розсилки повідомлень у локальній мережі TCP/IP. Воно одночасно виконує роль клієнта та сервера (рис. 1).

Мал. 1. Головне вікно програми DatagramChat
Невдача при відкритті сокету може статися в тому випадку, якщо користувач спробував запустити другу копію програми на одній і тій же робочій станції, де сокет 9997 вже зайнятий. У такому разі програма DatagramChat зможе виконувати роль клієнта, що передає широкомовні повідомлення, але повідомлення від інших робочих станцій не прийматимуться.
Повідомлення буде продубльовано у вікні програми з префіксом ":". Його приймуть усі робочі станції, у тому числі й та, звідки це повідомлення було надіслано. Повідомлення, що приймаються, відзначаються стрілочкою.
Перейдемо до опису вихідного тексту.
Головний клас програми DatagramChat
Метод main, визначений у головному класі програми DatagramChat, створює вікно програми як об'єкт класу FrameWindow:
Це вікно потім відображається методом setVisible.
Клас FrameWindow
Цей клас створено на базі класу Frame:
У ньому ми визначили поля, конструктор та кілька методів.
Наступні два поля призначені для зберігання посилань на кнопки Exit та Save:
Для виключення блокування програми прийом широкомовних повідомлень виконується окремому потоці. Поле sThread зберігає посилання на відповідний клас:
У полях s і dp ми зберігаємо посилання на об'єкти, які застосовуються для надсилання широкомовних повідомлень:
Конструктор класу FrameWindow
Зауважимо, що відразу після ініціалізації кнопка Send блокується конструктором класу FrameWindow:
Після цього конструктор запускає потік прийому повідомлень:
І, нарешті, остання дія – отримання датаграмного сокету для прийому повідомлень:
Метод діяльностівиконує клас FrameWindow
Метод sendString посилає пакет на всі робочі станції мережі із застосуванням датаграмних сокетів.
Метод sendString класу FrameWindow
Вихідний текст методу sendString досить простий:
Переданий рядок спочатку перетворюється на масив байт buf. Зауважимо, що масив записуються символи UNICODE.
Підготовлений пакет передається на сокеті методом send. Сокет s призначений для передачі повідомлень і створюється конструктором класу FrameWindow.
Клас ServerThread
Клас ServerThread створено на базі класу Thread:
У полі frame, визначеному у цьому класі, ми зберігаємо посилання на батьківське вікно:
Поле s використовується для зберігання сокета, на якому виконується прийом широкомовних повідомлень:
Конструктор класу ServerThread
Конструктор просто зберігає посилання на батьківське вікно у відповідному полі:
Метод run класу ServerThread
Цей метод працює в окремому потоці та займається прийомом широкомовних повідомлень.
Відразу після ініціалізації він розблокує кнопку Send і намагається створити серверний сокет:
У процесі створення серверного сокету можливе виникнення виключення SocketException (наприклад, якщо сокет із зазначеним номером вже зайнятий іншою копією нашої програми). Відповідний обробник виводить повідомлення про помилку у вікно програми та зупиняє потік прийому повідомлень.
При вдалому отриманні сокету метод run запускає цикл читання широкомовних повідомлень, що надходять:
Отримані повідомлення відображаютьсяу вікні програми методом консоліPrint.
Метод recvString класу ServerThread
Прийом широкомовних повідомлень виконується методом recvString:
Потім викликається метод receive, який виконує прийом даних.
Прийняті дані перетворюються на рядок UNICODE і повертаються методу, що викликає.