Учебники

Java NIO — ServerSocket Channel

Канал сокета сервера Java NIO снова является каналом выбираемого типа, используемым для потоковых сокетов, соединяющих сокеты. Канал сервера сокетов можно создать, вызвав его статический метод open () , при условии, что любой ранее существующий сокет еще не присутствует. Канал сервера сокетов создается путем вызова метода open, но еще не привязан. Для привязки сокета к каналу должен вызываться метод bind () .

Здесь необходимо упомянуть одну вещь: если канал не связан, и любая попытка ввода-вывода пытается быть предпринята, то NotYetBoundException выбрасывается этим каналом. Поэтому перед выполнением любой операции ввода-вывода необходимо убедиться, что канал ограничен.

Входящие соединения для канала сокета сервера прослушиваются путем вызова метода ServerSocketChannel.accept (). Когда метод accept () возвращается, он возвращает SocketChannel с входящим соединением. Таким образом, метод accept () блокируется до тех пор, пока не поступит входящее соединение. Если канал находится в неблокирующем режиме, метод accept немедленно вернет значение null, если нет ожидающих соединений. В противном случае он будет блокироваться на неопределенный срок, пока не будет доступно новое соединение или не возникнет ошибка ввода-вывода.

Сокет нового канала изначально не связан; он должен быть привязан к определенному адресу через один из методов привязки его сокета, прежде чем соединения могут быть приняты. Также новый канал создается путем вызова метода openServerSocketChannel общесистемного объекта SelectorProvider по умолчанию.

Как и сервер сокетов, канал сокетов может читать данные, используя метод read (). Во-первых, буфер выделен. Данные, считанные из ServerSocketChannel, сохраняются в буфере. Во-вторых, мы вызываем метод ServerSocketChannel.read (), и он считывает данные из ServerSocketChannel в буфер. Целочисленное значение метода read () возвращает количество байтов, записанных в буфер

Точно так же данные могут быть записаны в канал сокета сервера с использованием метода write () с использованием буфера в качестве параметра. Обычно используется метод write в цикле while, так как необходимо повторять метод write () до тех пор, пока в буфере не останется доступных байтов для записи.

Важные методы сокета канала

  • bind (SocketAddress local) — этот метод используется для привязки канала сокета к локальному адресу, который предоставляется в качестве параметра для этого метода.

  • accept () — этот метод используется для принятия соединения с сокетом этого канала.

  • connect (SocketAddress remote) — этот метод используется для подключения сокета к удаленному адресу.

  • finishConnect () — Этот метод используется для завершения процесса подключения канала сокета.

  • getRemoteAddress () — Этот метод возвращает адрес удаленного местоположения, к которому подключен сокет канала.

  • isConnected () — как уже упоминалось, этот метод возвращает статус подключения сокетного канала, т. е. подключен он или нет.

  • open () — метод Open используется для открытия канала сокета без указанного адреса. Этот удобный метод работает так, как если бы он вызывал метод open (), вызывал метод connect для получающегося канала сокета сервера, передавал его удаленно, а затем возвращал канал.

  • read (ByteBuffer dst) — этот метод используется для чтения данных из данного буфера через канал сокета.

  • setOption (SocketOption <T> name, T value) — этот метод устанавливает значение параметра сокета.

  • socket () — этот метод извлекает сокет сервера, связанный с этим каналом.

  • validOps () — этот метод возвращает набор операций, идентифицирующий поддерживаемые операции этого канала. Каналы сервера сокетов поддерживают только принятие новых соединений, поэтому этот метод возвращает SelectionKey.OP_ACCEPT.

bind (SocketAddress local) — этот метод используется для привязки канала сокета к локальному адресу, который предоставляется в качестве параметра для этого метода.

accept () — этот метод используется для принятия соединения с сокетом этого канала.

connect (SocketAddress remote) — этот метод используется для подключения сокета к удаленному адресу.

finishConnect () — Этот метод используется для завершения процесса подключения канала сокета.

getRemoteAddress () — Этот метод возвращает адрес удаленного местоположения, к которому подключен сокет канала.

isConnected () — как уже упоминалось, этот метод возвращает статус подключения сокетного канала, т. е. подключен он или нет.

open () — метод Open используется для открытия канала сокета без указанного адреса. Этот удобный метод работает так, как если бы он вызывал метод open (), вызывал метод connect для получающегося канала сокета сервера, передавал его удаленно, а затем возвращал канал.

read (ByteBuffer dst) — этот метод используется для чтения данных из данного буфера через канал сокета.

setOption (SocketOption <T> name, T value) — этот метод устанавливает значение параметра сокета.

socket () — этот метод извлекает сокет сервера, связанный с этим каналом.

validOps () — этот метод возвращает набор операций, идентифицирующий поддерживаемые операции этого канала. Каналы сервера сокетов поддерживают только принятие новых соединений, поэтому этот метод возвращает SelectionKey.OP_ACCEPT.

пример

В следующем примере показано, как отправить данные из Java NIO ServerSocketChannel.

C: /Test/temp.txt

Hello World!

Клиент: SocketChannelClient.java

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.util.EnumSet;

public class SocketChannelClient {
   public static void main(String[] args) throws IOException {
      ServerSocketChannel serverSocket = null;
      SocketChannel client = null;
      serverSocket = ServerSocketChannel.open();
      serverSocket.socket().bind(new InetSocketAddress(9000));
      client = serverSocket.accept();
      System.out.println("Connection Set:  " + client.getRemoteAddress());
      Path path = Paths.get("C:/Test/temp1.txt");
      FileChannel fileChannel = FileChannel.open(path, 
         EnumSet.of(StandardOpenOption.CREATE, 
            StandardOpenOption.TRUNCATE_EXISTING,
            StandardOpenOption.WRITE)
         );      
      ByteBuffer buffer = ByteBuffer.allocate(1024);
      while(client.read(buffer) > 0) {
         buffer.flip();
         fileChannel.write(buffer);
         buffer.clear();
      }
      fileChannel.close();
      System.out.println("File Received");
      client.close();
   }
}

Выход

Запущенный клиент ничего не напечатает, пока сервер не запустится.


Сервер: SocketChannelServer.java

import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.channels.SocketChannel;
import java.nio.file.Path;
import java.nio.file.Paths;

public class SocketChannelServer {
   public static void main(String[] args) throws IOException {
      SocketChannel server = SocketChannel.open();
      SocketAddress socketAddr = new InetSocketAddress("localhost", 9000);
      server.connect(socketAddr);
      Path path = Paths.get("C:/Test/temp.txt");
      FileChannel fileChannel = FileChannel.open(path);
      ByteBuffer buffer = ByteBuffer.allocate(1024);
      while(fileChannel.read(buffer) > 0) {
         buffer.flip();
         server.write(buffer);
         buffer.clear();
      }
      fileChannel.close();
      System.out.println("File Sent");
      server.close();
   }
}

Выход

Запустив сервер напечатает следующее.