Сетевое программирование в Java: создание надежных сетевых приложений с java.net
Сетевое программирование — написание программ, выполняемых на нескольких устройствах, соединённых сетью. Пакет java.net предоставляет низкоуровневые детали связи, позволяя фокусироваться на логике приложения.
Поддерживаемые протоколы
- TCP (Transmission Control Protocol) — надёжное соединение, поток байтов. Обычно поверх IP (TCP/IP).
- UDP (User Datagram Protocol) — без соединения, датаграммы.
Сокетное программирование (Socket Programming)
Сокеты — механизм связи двух компьютеров через TCP.
- Сервер создаёт
ServerSocketна порту. - Сервер вызывает
accept()— блокируется до подключения клиента. - Клиент создаёт
Socketс адресом сервера и портом. - Конструктор Socket пытается соединиться; при успехе клиент получает Socket.
- На сервере
accept()возвращает новый Socket, соединённый с клиентом.
После соединения: у каждого сокета есть InputStream и OutputStream. Клиентский OutputStream → Серверный InputStream, и наоборот. TCP — двусторонний, данные могут идти одновременно.
Класс ServerSocket
Конструкторы:
| Конструктор | Описание |
|---|---|
ServerSocket(int port) | Связывает с портом. Исключение, если порт занят. |
ServerSocket(int port, int backlog) | backlog — размер очереди ожидающих клиентов. |
ServerSocket(int port, int backlog, InetAddress address) | Привязка к конкретному IP (для многосетевых серверов). |
ServerSocket() | Несвязанный сокет; позже bind(). |
Основные методы:
| Метод | Описание |
|---|---|
getLocalPort() | Порт, на котором слушает сервер. |
accept() | Блокирует до подключения клиента. Возвращает новый Socket. |
setSoTimeout(int timeout) | Таймаут для accept(). |
bind(SocketAddress, int backlog) | Связка для no-arg конструктора. |
Класс Socket
Представляет сокет клиента и сервера (после accept). 5 конструкторов клиента:
| Конструктор | Описание |
|---|---|
Socket(String host, int port) | Подключение к хосту:порт. |
Socket(InetAddress host, int port) | То же, хост как InetAddress. |
Socket(String host, int port, InetAddress localAddr, int localPort) | С указанием локального адреса/порта. |
Socket(InetAddress host, int port, InetAddress localAddr, int localPort) | Аналогично с InetAddress. |
Socket() | Неподключённый; нужен connect(). |
Полезные методы:
| Метод | Описание |
|---|---|
connect(SocketAddress, int timeout) | Подключение (для no-arg конструктора). |
getInetAddress() | Адрес удалённого компьютера. |
getPort() | Удалённый порт. |
getLocalPort() | Локальный порт. |
getRemoteSocketAddress() | Адрес удалённого сокета. |
getInputStream() | Входной поток (подключён к OutputStream удалённого). |
getOutputStream() | Выходной поток (подключён к InputStream удалённого). |
close() | Закрытие сокета. |
Класс InetAddress
Представляет IP-адрес. Полезные методы:
| Метод | Описание |
|---|---|
getByName(String host) | IP по имени хоста. |
getByAddress(byte[] addr) | InetAddress из байтов IP. |
getLocalHost() | Локальный хост. |
getHostAddress() | IP в текстовом виде. |
getHostName() | Имя хоста для IP. |
Пример: клиент (GreetingClient)
import java.net.*; import java.io.*;
public class GreetingClient {
public static void main(String[] args) {
String serverName = args[0];
int port = Integer.parseInt(args[1]);
try {
System.out.println("Connecting to " + serverName + " on port " + port);
Socket client = new Socket(serverName, port);
System.out.println("Connected to " + client.getRemoteSocketAddress());
DataOutputStream out = new DataOutputStream(client.getOutputStream());
out.writeUTF("Hello from " + client.getLocalSocketAddress());
DataInputStream in = new DataInputStream(client.getInputStream());
System.out.println("Server says: " + in.readUTF());
client.close();
} catch (IOException e) { e.printStackTrace(); }
}
}
Пример: сервер (GreetingServer)
import java.net.*; import java.io.*;
public class GreetingServer extends Thread {
private ServerSocket serverSocket;
public GreetingServer(int port) throws IOException {
serverSocket = new ServerSocket(port);
serverSocket.setSoTimeout(10000);
}
public void run() {
while (true) {
try {
System.out.println("Waiting for client on port " + serverSocket.getLocalPort() + "...");
Socket server = serverSocket.accept();
System.out.println("Connected to " + server.getRemoteSocketAddress());
DataInputStream in = new DataInputStream(server.getInputStream());
System.out.println(in.readUTF());
DataOutputStream out = new DataOutputStream(server.getOutputStream());
out.writeUTF("Thank you for connecting to " + server.getLocalSocketAddress() + "\nGoodbye!");
server.close();
} catch (SocketTimeoutException s) {
System.out.println("Socket timed out!"); break;
} catch (IOException e) { e.printStackTrace(); break; }
}
}
public static void main(String[] args) {
int port = Integer.parseInt(args[0]);
try { new GreetingServer(port).start(); } catch (IOException e) { e.printStackTrace(); }
}
}
Запуск
$ java GreetingServer 6066
Waiting for client on port 6066...
$ java GreetingClient localhost 6066
Connecting to localhost on port 6066
Just connected to localhost/127.0.0.1:6066
Server says: Thank you for connecting to /127.0.0.1:6066
Goodbye!
java
- Освоение операторов Java: типы, синтаксис и практические примеры
- Комментарии в Java: типы, использование и лучшие практики
- Освоение улучшенного цикла for в Java: синтаксис, примеры и лучшие практики
- Освоение строк в Java: создание, методы и лучшие практики
- Интерфейсы в Java: концепции, реализация и лучшие практики
- Анонимные внутренние классы в Java: определение, синтаксис и практические примеры
- Try-with-resources в Java: автоматическое управление ресурсами
- Аннотации в Java: типы, размещение и практические примеры
- Assertions в Java: практическое руководство по обнаружению багов и обеспечению надежности кода
- Понимание Java Vector: использование, особенности и сравнение с ArrayList