Java NIO - Canal ServerSocket
O canal de soquete do servidor Java NIO é novamente um canal de tipo selecionável usado para fluxo de dados orientado por fluxo conectando soquetes. O canal de soquete do servidor pode ser criado chamando seu canal estático open() , desde que nenhum socket pré-existente já esteja presente. O canal de socket de servidor é criado invocando o método aberto, mas ainda não vinculado. bind() método deve ser chamado.
Um ponto a ser mencionado aqui é se o canal não está vinculado e qualquer operação de E / S é tentada, então NotYetBoundException é lançada por este canal. Portanto, deve-se garantir que o canal esteja vinculado antes de executar qualquer operação de E / S.
As conexões de entrada para o canal de soquete do servidor são ouvidas chamando o método ServerSocketChannel.accept (). Quando o método accept () retorna, ele retorna um SocketChannel com uma conexão de entrada. Portanto, o método accept () bloqueia até que uma conexão de entrada chegue. Se o canal estiver no modo sem bloqueio, o método accept retornará imediatamente nulo se não houver conexões pendentes. Caso contrário, bloqueará indefinidamente até que uma nova conexão esteja disponível ou ocorra um erro de E / S.
O soquete do novo canal é inicialmente desvinculado; ele deve ser vinculado a um endereço específico por meio de um dos métodos de vinculação de seu soquete antes que as conexões possam ser aceitas. Além disso, o novo canal é criado invocando o método openServerSocketChannel do objeto SelectorProvider padrão de todo o sistema.
Como canal de soquete, servidor de canal de soquete pode ler dados usando read()método. Primeiro, o buffer é alocado. Os dados lidos de um ServerSocketChannel são armazenados no buffer. Em segundo lugar, chamamos o método ServerSocketChannel.read () e ele lê os dados de um ServerSocketChannel em um buffer. O valor inteiro do método read () retorna quantos bytes foram gravados no buffer
Da mesma forma, os dados podem ser gravados no canal de soquete do servidor usando write() método usando buffer como parâmetro. Normalmente usa o método write em um loop while, pois é necessário repetir o método write () até que o buffer não tenha mais bytes disponíveis para gravar.
Métodos importantes de canal Socket
bind(SocketAddress local) - Este método é usado para vincular o canal de soquete ao endereço local que é fornecido como parâmetro para este método.
accept() - Este método é usado para aceitar uma conexão feita ao soquete deste canal.
connect(SocketAddress remote) - Este método é usado para conectar o soquete ao endereço remoto.
finishConnect() - Este método é usado para terminar o processo de conexão de um canal de socket.
getRemoteAddress() - Este método retorna o endereço do local remoto ao qual o soquete do canal está conectado.
isConnected() - Como já mencionado, este método retorna o status da conexão do canal socket, ou seja, se está conectado ou não.
open() - O método aberto é usado para abrir um canal de soquete para nenhum endereço especificado. Este método conveniente funciona como se invocasse o método open (), invocando o método de conexão no canal de soquete do servidor resultante, passando-o remoto e, em seguida, retornando esse canal.
read(ByteBuffer dst) - Este método é usado para ler dados de um determinado buffer através do canal de socket.
setOption(SocketOption<T> name, T value) - Este método define o valor de uma opção de soquete.
socket() - Este método recupera um soquete de servidor associado a este canal.
validOps() - Este método retorna um conjunto de operações que identifica as operações suportadas deste canal. Canais de soquete de servidor suportam apenas a aceitação de novas conexões, portanto, este método retorna SelectionKey.OP_ACCEPT.
Exemplo
O exemplo a seguir mostra como enviar dados do Java NIO ServerSocketChannel.
C: /Test/temp.txt
Hello World!
Cliente: 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();
}
}
Resultado
Executar o cliente não imprimirá nada até que o servidor seja iniciado.
Servidor: 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();
}
}
Resultado
Executar o servidor imprimirá o seguinte.
Connection Set: /127.0.0.1:49558
File Received