Термин «сетевое программирование» относится к написанию программ, которые выполняются на нескольких устройствах (компьютерах), в которых все устройства подключены друг к другу с помощью сети.

Пакет java.net набора интерфейсов прикладного программирования J2SE содержит набор классов и интерфейсов, которые предоставляют подробные сведения о низкоуровневом взаимодействии, что позволяет писать программы, ориентированные на решение существующей проблемы.

Протоколы TCP и UDP

Пакет java.net обеспечивает поддержку двух общих сетевых протоколов:

  • TCP - TCP - это протокол управления передачей, который обеспечивает надежную связь между двумя приложениями. В Java TCP обычно используется через Интернет-протокол, который называется TCP/IP.
  • UDP - UDP - это протокол пользовательских дейтаграмм, протокол без установления соединения, который позволяет передавать пакеты данных между приложениями.

Данная глава надлежащим образом раскрывает следующие две темы:

  • Программирование сокетов - это наиболее широко используемая концепция в сетевой конфигурации, о которой было подробно изложено.
  • Обработка URL (унифицированный указатель ресурсов) - этот процесс будет рассмотрен отдельно. Перейдите по ссылке, чтобы узнать об обработке URL на языке Java.

Программирование сокетов

В Java сокеты обеспечивают механизм связи между двумя компьютерами, использующими TCP. Клиентская программа создает сокет на своем конце связи и пытается подключить этот сокет к серверу.

Когда соединение установлено, сервер создает объект сокета на своем конце связи. Клиент и сервер теперь могут общаться, записывая и считывая данные с сокета.

Класс java.net.Socket представляет собой сокет, а класс java.net.ServerSocket предоставляет механизм серверной программы для прослушивания клиентов и установления соединений с ними.

При установлении соединения TCP между двумя компьютерами с использованием сокетов, выполняются следующие этапы:

  • Сервер создает экземпляр объекта ServerSocket, определяющий, по какому номеру порта должна происходить связь.
  • Сервер вызывает метод accept() класса ServerSocket. Этот метод ожидает, пока клиент не подключится к серверу по указанному порту.
  • По завершению ожидания сервера клиент создает экземпляр объекта сокета, указывая имя сервера и номер порта подключения.
  • Конструктор класса Socket осуществляет попытку подключить клиента к указанному серверу и номеру порта. Если связь установлена, у клиента теперь есть объект Socket, способный связываться с сервером.
  • На стороне сервера метод accept() возвращает ссылку к новому сокету на сервере, который подключен к клиентскому сокету.

После того, как соединения установлены, связь может происходить с использованием потоков входных/выходных данных. Каждый сокет имеет и OutputStream (поток выходных данных), и InputStream (поток входных данных). OutputStream клиента подключен к InputStream сервера, а InputStream клиента подключен к OutputStream сервера.

TCP является двусторонним протоколом связи, поэтому данные могут передаваться по обоим потокам одновременно. Ниже приведены полезные классы, предоставляющие полный набор методов внедрения сокетов.

Конструкторы класса ServerSocket

Класс java.net.ServerSocket используется серверными приложениями для получения порта и прослушивания клиентских запросов.

Класс ServerSocket имеет четыре конструктора:

Конструктор и описание
1public ServerSocket(int port) throws IOException
Попытки создания серверного сокета, связанного с указанным портом. Исключение происходит, если порт уже связан другим приложением.
2public ServerSocket(int port, int backlog) throws IOException
Как и в предыдущем конструкторе, параметр backlog указывает, сколько входящих клиентов нужно сохранить в очереди ожидания.
3public ServerSocket(int port, int backlog, InetAddress address) throws IOException
Как и в предыдущем конструкторе, параметр InetAddress указывает локальный IP-адрес для осуществления привязки. InetAddress используется в серверах, которые могут иметь несколько IP-адресов, что позволяет серверу указывать IP-адрес приема запросов клиентов.
4public ServerSocket() throws IOException
Создает непривязанный сокет сервера. При использовании этого конструктора используйте метод привязки (), когда будете готовы привязать сокет сервера.

Если конструктор ServerSocket не выдает исключение, это означает, что ваше приложение успешно связано с указанным портом и готово к клиентским запросам.

Методы класса ServerSocket

Ниже приведены некоторые из распространенных методов в Java класса ServerSocket.

Методы и описание
1public int getLocalPort()
Возвращает порт, который прослушивает сокет сервера. Этот метод полезен, если вы передали 0 в качестве номера порта в конструкторе и позволили серверу найти порт.
2public Socket accept() throws IOException
Ожидает входящего клиента. Этот метод блокируется до тех пор, пока клиент не подключится к серверу на указанном порту или не истечет время ожидания сокета, при условии, что значение времени ожидания было установлено с помощью метода setSoTimeout(). В противном случае этот метод блокируется на неопределенный срок.
3public void setSoTimeout(int timeout)
Устанавливает значение времени ожидания клиента сокетом сервера во время accept().
4public void bind (хост SocketAddress, int backlog)
Привязывает сокет к указанному серверу и порту в объекте SocketAddress. Используйте этот метод, если вы создали ServerSocket с помощью конструктора без аргументов.

Когда ServerSocket вызывает accept(), метод не возвращается, пока клиент не подключится. После того, как клиент все-таки подключится, ServerSocket создает новый сокет для неуказанного порта и возвращает ссылку на этот новый сокет. Теперь между клиентом и сервером существует TCP-соединение, и связь может установиться.

Конструкторы класса Socket

Класс java.net.Socket представляет собой сокет, который клиент и сервер используют для связи друг с другом. Клиент получает объект сокета, создав его, тогда как сервер получает объект сокета из возвращаемого значения метода accept().

Класс Socket имеет пять конструкторов, которые клиент использует для подключения к серверу.

Конструктор и описание
1public Socket(String host, int port) throws UnknownHostException, IOException.
Этот метод предпринимает попытку подключения к указанному серверу через указанный порт. Если этот конструктор не выдает исключение, то соединение установлено успешно, и клиент подключен к серверу.
2public Socket(InetAddress host, int port) throws IOException
Этот метод идентичен предыдущему конструктору, за исключением того, что хост обозначается объектом InetAddress.
3public Socket(String host, int port, InetAddress localAddress, int localPort) throws IOException.
Подключается к указанному хосту и порту, создавая сокет на локальном хосте по указанному адресу и порту.
4public Socket(InetAddress host, int port, InetAddress localAddress, int localPort) throws IOException.
Этот метод идентичен предыдущему конструктору, за исключением того, что хост обозначается объектом InetAddress вместо строки адреса.
5public Socket()
Создает неподключенный сокет. Используйте метод connect() для подключения такого сокета к серверу.

При возврате конструктора Socket, он не просто создает экземпляр объекта сокета, но фактически пытается подключиться к указанному серверу и порту.

Некоторые методы, изучающие класс сокета, перечислены здесь. Обратите внимание, что и клиент, и сервер имеют объект сокета, поэтому эти методы могут вызываться как клиентом, так и сервером.

Методы класса Socket

Метод и описание
1public void connect(SocketAddress host, int timeout) throws IOException
Этот метод подключает сокет к указанному хосту. Этот метод необходим только при создании экземпляра сокета с помощью конструктора без аргументов.
2public InetAddress getInetAddress()
Этот метод возвращает адрес другого компьютера, к которому подключен этот сокет.
3public int getPort()
Возвращает порт, к которому привязан сокет на удаленной машине.
4public int getLocalPort()
Возвращает порт, к которому привязан сокет на локальной машине.
5public SocketAddress getRemoteSocketAddress()
Возвращает адрес удаленного сокета.
6public InputStream getInputStream() throws IOException
Возвращает поток входных данных сокета. Поток входных данных подключен к потоку выходных данных удаленного сокета.
7public OutputStream getOutputStream() throws IOException
Возвращает поток выходных данных сокета. Поток выходных данных подключен к потоку входных данных удаленного сокета.
8public void close() throws IOException
Закрывает сокет, что делает данный объект сокета не способным снова подключаться к любому серверу.

Методы класса InetAddress

Этот класс представляет адрес Интернет-протокола (IP). Следующие полезные методы, которые понадобятся при программировании сокетов, представлены ниже:

и описание
1static InetAddress getByAddress(byte[] addr)
Возвращает объект InetAddress с учетом необработанного IP-адреса.
2static InetAddress getByAddress(String host, byte[] addr)
Создает InetAddress на основе предоставленного имени хоста и IP-адреса.
3static InetAddress getByName(String host)
Определяет IP-адрес хоста, учитывая имя хоста.
4String getHostAddress()
Возвращает строку IP-адреса в текстовой форме.
5String getHostName()
Получает имя хоста для данного IP-адреса.
6static InetAddress InetAddress getLocalHost()
Возвращает локальный хост.
7String toString()
Конвертирует этот IP-адрес в адресную строку.

Пример Socket Client

Следующая GreetingClient – это клиентская программа, которая подключается к серверу с помощью сокета, отправляет приветствие, а затем ожидает ответа.

// Название файла GreetingClient.java
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("Подключение к " + serverName + " на порт " + port);
         Socket client = new Socket(serverName, port);
         
         System.out.println("Просто подключается к " + client.getRemoteSocketAddress());
         OutputStream outToServer = client.getOutputStream();
         DataOutputStream out = new DataOutputStream(outToServer);
         
         out.writeUTF("Привет из " + client.getLocalSocketAddress());
         InputStream inFromServer = client.getInputStream();
         DataInputStream in = new DataInputStream(inFromServer);
         
         System.out.println("Сервер ответил " + in.readUTF());
         client.close();
      } catch (IOException e) {
         e.printStackTrace();
      }
   }
}

Пример Socket Server

Следующая программа GreetingServer является примером серверного приложения, которое использует класс сокета для прослушивания клиентов по номеру порта, указанному в аргументе командной строки.

// Название файла GreetingServer.java
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("Ожидание клиента на порт " + 
               serverSocket.getLocalPort() + "...");
            Socket server = serverSocket.accept();
            
            System.out.println("Просто подключается к " + server.getRemoteSocketAddress());
            DataInputStream in = new DataInputStream(server.getInputStream());
            
            System.out.println(in.readUTF());
            DataOutputStream out = new DataOutputStream(server.getOutputStream());
            out.writeUTF("Спасибо за подключение к " + server.getLocalSocketAddress()
               + "\nПока!");
            server.close();
            
         } catch (SocketTimeoutException s) {
            System.out.println("Время сокета истекло!");
            break;
         } catch (IOException e) {
            e.printStackTrace();
            break;
         }
      }
   }
   
   public static void main(String [] args) {
      int port = Integer.parseInt(args[0]);
      try {
         Thread t = new GreetingServer(port);
         t.start();
      } catch (IOException e) {
         e.printStackTrace();
      }
   }
}

Скомпилируйте клиент и сервер, а затем запустите сервер следующим образом:

$ java GreetingServer 6066
Ожидание клиента на порт 6066...

Проверьте клиентскую программу следующим образом:

$ java GreetingClient localhost 6066
Подключение к localhost на порт 6066
Просто подключается к localhost/127.0.0.1:6066
Сервер ответил Спасибо за подключение к /127.0.0.1:6066
Пока!

Оглавление