conexión TCP
La base de TCP es Socket. En la conexión TCP, usaremos ServerSocket y Socket. Después de que el cliente y el servidor establezcan una conexión, el resto es básicamente el control de E/S.
Primero veamos una comunicación TCP simple, que se divide en cliente y servidor.
El código de cliente es el siguiente:
public static void main (String [] args) lanza IOException
{
Conector hembra = nulo;
BufferedReader br = nulo;
PrintWriter pw = nulo;
BufferedReader brTemp = nulo;
intentar
{
socket = nuevo Socket(InetAddress.getLocalHost(), 5678);
br = nuevo BufferedReader(nuevo InputStreamReader(socket.getInputStream()));
pw = nuevo PrintWriter(socket.getOutputStream());
brTemp = nuevo BufferedReader (nuevo InputStreamReader (System.in));
mientras (verdadero)
{
Línea de cadena = brTemp.readLine();
pw.println(línea);
pw.flush();
if (line.equals("end")) descanso;
System.out.println(br.readLine());
}
}
captura (Excepción ex)
{
System.err.println(ex.getMessage());
}
finalmente
{
si (socket! = nulo) socket.close();
si (br! = nulo) br.close();
si (brTemp! = nulo) brTemp.close();
si (pw != nulo) pw.close();
}
}
}
public static void main (String [] args) lanza IOException
{
Servidor ServerSocket = nulo;
Cliente de socket = nulo;
BufferedReader br = nulo;
PrintWriter pw = nulo;
intentar
{
servidor = nuevo ServerSocket(5678);
cliente = servidor.aceptar();
br = nuevo BufferedReader(nuevo InputStreamReader(client.getInputStream()));
pw = nuevo PrintWriter(client.getOutputStream());
mientras (verdadero)
{
Línea de cadena = br.readLine();
pw.println("Respuesta:" + línea);
pw.flush();
if (line.equals("end")) descanso;
}
}
captura (Excepción ex)
{
System.err.println(ex.getMessage());
}
finalmente
{
si (servidor! = nulo) servidor.close();
if (cliente! = nulo) cliente.close();
si (br! = nulo) br.close();
si (pw != nulo) pw.close();
}
}
}
El código anterior básicamente describe el marco principal del cliente y el servidor durante el proceso de comunicación TCP. Podemos encontrar que en el código anterior, el servidor solo puede procesar una solicitud del cliente a la vez. no se puede paralelizar. Este no es el mismo que el método de procesamiento del servidor en nuestra impresión. Podemos agregar subprocesos múltiples al servidor. Cuando llega una solicitud del cliente, creamos un subproceso para procesar la solicitud correspondiente.
El código mejorado del lado del servidor es el siguiente:
clase ServerThread extiende Thread
{
socket privado socket = nulo;
hilo de servidor público (zócalo)
{
this.socket = enchufe;
}
ejecución pública vacía() {
BufferedReader br = nulo;
PrintWriter pw = nulo;
intentar
{
br = nuevo BufferedReader(nuevo InputStreamReader(socket.getInputStream()));
pw = nuevo PrintWriter(socket.getOutputStream());
mientras (verdadero)
{
Línea de cadena = br.readLine();
pw.println("Respuesta:" + línea);
pw.flush();
if (line.equals("end")) descanso;
}
}
captura (Excepción ex)
{
System.err.println(ex.getMessage());
}
finalmente
{
si (zócalo! = nulo)
intentar {
socket.cerrar();
} captura (IOException e1) {
e1.printStackTrace();
}
si (br! = nulo)
intentar {
br.cerrar();
} captura (IOException e) {
e.printStackTrace();
}
si (pw != nulo) pw.close();
}
}
}
En el proceso de programación, tenemos el concepto de "recurso". Por ejemplo, la conexión de la base de datos es un recurso típico. Para mejorar el rendimiento, generalmente no destruimos la conexión de la base de datos directamente, sino que utilizamos el grupo de conexiones de la base de datos para administrar múltiples. Las bases de datos se gestionan y reutilizan. Para las conexiones de Socket, también es un recurso. Cuando nuestro programa requiere una gran cantidad de conexiones de Socket, será un enfoque muy ineficiente si es necesario restablecer cada conexión.
De manera similar al grupo de conexiones de la base de datos, también podemos diseñar un grupo de conexiones TCP. La idea aquí es que usamos una matriz para mantener múltiples conexiones de Socket y otra matriz de estado para describir si cada conexión de Socket está en uso. Conexión de socket, recorremos la matriz de estado y eliminamos la primera conexión de socket no utilizada. Si todas las conexiones están en uso, se genera una excepción. Esta es una "estrategia de programación" muy intuitiva y simple. En muchos marcos comerciales o de código abierto (Apache/Tomcat), habrá "grupos de recursos" similares.
El código para el grupo de conexiones TCP es el siguiente:
dirección InetAddress privada = nula;
puerto internacional privado;
Socket privado[] arrSockets = null;
booleano privado [] arrStatus = nulo;
recuento de int privado;
TcpConnectionPool público (dirección InetAddress, puerto int, recuento int)
{
esta.dirección = dirección;
this.port = puerto;
este .count = contar;
arrSockets = nuevo Socket[recuento];
arrStatus = nuevo booleano[recuento];
inicio();
}
inicio vacío privado()
{
intentar
{
para (int i = 0; i < contar; i++)
{
arrSockets[i] = new Socket(dirección.getHostAddress(), puerto);
estadoarr[i] = falso;
}
}
captura (Excepción ex)
{
System.err.println(ex.getMessage());
}
}
getConnection de socket público()
{
si (arrSockets == nulo) init();
int yo = 0;
para(i = 0; i < contar; i++)
{
si (arrStatus[i] == falso)
{
arrStatus[i] = verdadero;
romper;
}
}
if (i == count) throw new RuntimeException ("no tengo conexión disponible por ahora.");
devolver arrSockets[i];
}
conexión de liberación pública vacía (zócalo)
{
si (arrSockets == nulo) init();
para (int i = 0; i < contar; i++)
{
si (arrSockets[i] == conector)
{
estadoarr[i] = falso;
romper;
}
}
}
reconstrucción de vacío público()
{
inicio();
}
destrucción de vacío público ()
{
si (arrSockets == nulo) regresa;
para(int i = 0; i < contar; i++)
{
intentar
{
arrSockets[i].close();
}
captura (Excepción ex)
{
System.err.println(ex.getMessage());
continuar;
}
}
}
}
UDP es un método de conexión diferente de TCP. Generalmente se usa en situaciones que requieren un alto rendimiento en tiempo real y bajos requisitos de precisión, como videos en línea. UDP tendrá "pérdida de paquetes". En TCP, si el servidor no se inicia, se informará una excepción cuando el cliente envíe un mensaje, pero para UDP, no se generará ninguna excepción.
Las dos clases utilizadas para la comunicación UDP son DatagramSocket y DatagramPacket, este último almacena el contenido de la comunicación.
El siguiente es un ejemplo simple de comunicación UDP. Al igual que TCP, también se divide en dos partes: Cliente y Servidor. El código del cliente es el siguiente:
principal vacío estático público (String [] argumentos)
{
intentar
{
InetAddress host = InetAddress.getLocalHost();
puerto int = 5678;
BufferedReader br = nuevo BufferedReader (nuevo InputStreamReader (System.in));
mientras (verdadero)
{
Línea de cadena = br.readLine();
byte[] mensaje = line.getBytes();
Paquete DatagramPacket = nuevo DatagramPacket (mensaje, longitud del mensaje, host, puerto);
Conector DatagramSocket = nuevo DatagramSocket();
socket.enviar(paquete);
socket.cerrar();
if (line.equals("end")) descanso;
}
br.cerrar();
}
captura (Excepción ex)
{
System.err.println(ex.getMessage());
}
}
}
principal vacío estático público (String [] argumentos)
{
intentar
{
puerto int = 5678;
DatagramSocket dsSocket = nuevo DatagramSocket(puerto);
byte[] buffer = nuevo byte[1024];
Paquete DatagramPacket = nuevo DatagramPacket (búfer, búfer.longitud);
mientras (verdadero)
{
dsSocket.receive(paquete);
Mensaje de cadena = nueva cadena (búfer, 0, paquete.getLength());
System.out.println(packet.getAddress().getHostName() + ":" + mensaje);
si (message.equals("end")) descanso;
paquete.setLength(buffer.length);
}
dsSocket.close();
}
captura (Excepción ex)
{
System.err.println(ex.getMessage());
}
}
}
La multidifusión utiliza un método similar a UDP. Utiliza direcciones IP de clase D y los números de puerto UDP estándar se refieren a direcciones entre 224.0.0.0 y 239.255.255.255, excluyendo 224.0.0.0.
La clase utilizada en multidifusión es MulticastSocket, que tiene dos métodos a los que prestar atención: joinGroup y LeaveGroup.
El siguiente es un ejemplo de multidifusión. El código del cliente es el siguiente:
principal vacío estático público (String [] argumentos)
{
BufferedReader br = nuevo BufferedReader (nuevo InputStreamReader (System.in));
intentar
{
Dirección InetAddress = InetAddress.getByName("230.0.0.1");
puerto int = 5678;
mientras (verdadero)
{
Línea de cadena = br.readLine();
byte[] mensaje = line.getBytes();
Paquete DatagramPacket = nuevo DatagramPacket (mensaje, longitud del mensaje, dirección, puerto);
MulticastSocket multicastSocket = nuevo MulticastSocket();
multicastSocket.send(paquete);
if (line.equals("end")) descanso;
}
br.cerrar();
}
captura (Excepción ex)
{
System.err.println(ex.getMessage());
}
}
}
principal vacío estático público (String [] argumentos)
{
puerto int = 5678;
intentar
{
MulticastSocket multicastSocket = nuevo MulticastSocket(puerto);
Dirección InetAddress = InetAddress.getByName("230.0.0.1");
multicastSocket.joinGroup(dirección);
byte[] buffer = nuevo byte[1024];
Paquete DatagramPacket = nuevo DatagramPacket (búfer, búfer.longitud);
mientras (verdadero)
{
multicastSocket.receive(paquete);
Mensaje de cadena = nueva cadena (búfer, paquete.getLength());
System.out.println(packet.getAddress().getHostName() + ":" + mensaje);
si (message.equals("end")) descanso;
paquete.setLength(buffer.length);
}
multicastSocket.close();
}
captura (Excepción ex)
{
System.err.println(ex.getMessage());
}
}
}
NIO es un nuevo conjunto de API IO introducido en JDK1.4. Tiene nuevos diseños en gestión de búfer, comunicación de red, acceso a archivos y operaciones de juego de caracteres. Para la comunicación de red, NIO utiliza los conceptos de buffers y canales.
El siguiente es un ejemplo de NIO, que es muy diferente del estilo de codificación que mencionamos anteriormente.
principal vacío estático público (String [] argumentos)
{
Cadena de host="127.0.0.1";
puerto int = 5678;
Canal SocketChannel = nulo;
intentar
{
Dirección InetSocketAddress = nueva InetSocketAddress(host,puerto);
Juego de caracteres juego de caracteres = Charset.forName("UTF-8");
Decodificador CharsetDecoder = charset.newDecoder();
Codificador CharsetEncoder = charset.newEncoder();
Búfer ByteBuffer = ByteBuffer.allocate(1024);
CharBuffer charBuffer = CharBuffer.allocate(1024);
canal = SocketChannel.open();
canal.connect(dirección);
Solicitud de cadena = "GET / /r/n/r/n";
canal.write(encoder.encode(CharBuffer.wrap(solicitud)));
mientras ((canal.leer (búfer))! = -1)
{
buffer.flip();
decodificador.decode(búfer, charBuffer, falso);
charBuffer.flip();
System.out.println(charBuffer);
buffer.clear();
charBuffer.clear();
}
}
captura (Excepción ex)
{
System.err.println(ex.getMessage());
}
finalmente
{
si (canal! = nulo)
intentar {
canal.cerrar();
} captura (IOException e) {
// TODO Bloque de captura generado automáticamente
e.printStackTrace();
}
}
}
}