Hay tienes para que te aburras más de lo que estás.
Tienes malas prácticas, debes mejorarlas dog, aqui algunos tips a repasar
* Método main hyper recargado, separa la lógica del negocio para que tu api sea mas usable, mi ejemplo no es el mejor, pero esa es la idea.
* Falta del uso de try-with resources
* Usa java.util.List en ves de java.awt.List
* Usa un buen IDE, o aprende a usar bien el que tienes
* Usa un analizador de código estático como sonar o findbugs
* Por cada datagrama UDP enviado desde el server, en el cliente debes crear también la cantidad igual o sea,
new DatagramPacket()
* Wrappers, las clases de bajo nivel con las de alto nivel, ByteArray de Input/OutputStream, envuélvelos/wrapper con otras clases de alto nivel, mas o menos como hiciste con ObjectInputStream, pero hazlo mas legible.
* Pues hace lo que se pide, introduce 4 número para llenar la java.util.List no la q estabas usando, error primordial.
* Son procesados en el servidor UDP para ser luego retornados
* Si en esos números introducidos está un asterisco, lo usamos como flag, para salirnos del while del cliente, e invocar a
.close(), otra cosa es que la conexión UDP se cierra distinto a la tcp, al invocar a .close() este libera el puerto usado por ese socket, pero segun lo que veo, el puerto queda si escaneamos en windows con un netstat -aon, pero sin poderse usar, con UDP, no hay garantía de la entrega de datagramas que viajan por la red, esto último se parece a la frase en mi blog, pero esta es más *****
Usa GeSHi
Server PoC
Cliente PoC
Versión Server PoC con builder básico.
Tienes malas prácticas, debes mejorarlas dog, aqui algunos tips a repasar
* Método main hyper recargado, separa la lógica del negocio para que tu api sea mas usable, mi ejemplo no es el mejor, pero esa es la idea.
* Falta del uso de try-with resources
* Usa java.util.List en ves de java.awt.List
* Usa un buen IDE, o aprende a usar bien el que tienes
* Usa un analizador de código estático como sonar o findbugs
* Por cada datagrama UDP enviado desde el server, en el cliente debes crear también la cantidad igual o sea,
new DatagramPacket()
* Wrappers, las clases de bajo nivel con las de alto nivel, ByteArray de Input/OutputStream, envuélvelos/wrapper con otras clases de alto nivel, mas o menos como hiciste con ObjectInputStream, pero hazlo mas legible.
* Pues hace lo que se pide, introduce 4 número para llenar la java.util.List no la q estabas usando, error primordial.
* Son procesados en el servidor UDP para ser luego retornados
* Si en esos números introducidos está un asterisco, lo usamos como flag, para salirnos del while del cliente, e invocar a
.close(), otra cosa es que la conexión UDP se cierra distinto a la tcp, al invocar a .close() este libera el puerto usado por ese socket, pero segun lo que veo, el puerto queda si escaneamos en windows con un netstat -aon, pero sin poderse usar, con UDP, no hay garantía de la entrega de datagramas que viajan por la red, esto último se parece a la frase en mi blog, pero esta es más *****
Usa GeSHi
Código (java) [Seleccionar]
import java.util.logging.Logger;
/**
* interface con Logger
*/
public interface UDPLogger {
default void info(final String info) {
Logger.getLogger("UdpLogger").info(info);
}
default void error(final String error) {
Logger.getLogger("UdpLogger").warning(error);
}
}
Server PoC
Código (java) [Seleccionar]
package com.foro;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.time.Instant;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.Locale;
import java.util.Objects;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
* @author rub´n
*/
public class ServerUDPListaProcesarPoC implements UDPLogger {
private static final int PUERTO = 13;
private ExecutorService es = Executors.newFixedThreadPool(50);
/**
* Unico constructor de esta clase
*/
public ServerUDPListaProcesarPoC() {
/*
* Async
*/
CompletableFuture.runAsync(this::initServer, es);
}
/**
* Equivalen a 2 datagramas aka UDP packets
*
* dos metodos que ejecutara el server al cliente
* la hora y la lista de numeros procesadas con la formula (n1 + n2 ) * n3 - n4;
* - enviarHoraAlCliente(datagramSocket, request);
* - enviarListaProcesadaAlCliente(datagramSocket, request);
*
*/
private void initServer() {
try (final DatagramSocket datagramSocket = new DatagramSocket(PUERTO)) {
info("Servidor UDP iniciado correctamente por el puerto: " + PUERTO);
while (Boolean.TRUE) {
try {
final byte[] byteBuffer = new byte[1024];
final DatagramPacket request = new DatagramPacket(byteBuffer, byteBuffer.length);
datagramSocket.receive(request);
enviarHoraAlCliente(datagramSocket, request);
enviarListaProcesadaAlCliente(datagramSocket, request);
} catch (IOException | RuntimeException e) {
error(e.toString());
}
}
} catch (IOException e) {
error(e.toString());
}
}
/**
* enviar hora al cliente
*
* @param request
* @param socket
*/
private void enviarHoraAlCliente(final DatagramSocket socket, final DatagramPacket request) {
/*
* Metodo que obtiene la hora como ejemplo
* solo ejemplo :D
*/
final byte[] data = getHora().getBytes();
/*
* Este datagrama se le enviara como respuesta al cliente
*/
final DatagramPacket response = new DatagramPacket(data, data.length, request.getAddress(), request.getPort());
try {
/*
* Enviando datos al cliente
*/
socket.send(response);
} catch (IOException e) {
error(e.toString());
}
/*
* Imprimimos el datagrama UDP originado, junto con la direccion ip del cliente mas el puerto
*/
info(new String(data) + " - " + request.getAddress() + ":" + request.getPort());
}
/**
* @param socket
* @param request
*/
private void enviarListaProcesadaAlCliente(final DatagramSocket socket, final DatagramPacket request) {
/*
* Request
*/
final byte[] data = procesarLista(request);
final DatagramPacket response = new DatagramPacket(data, data.length, request.getAddress(), request.getPort());
try {
/*
* Enviando datos al cliente
*/
socket.send(response);
} catch (IOException e) {
error(e.toString());
}
/*
* Imprimimos el datagrama UDP originado, junto con la direccion ip del cliente mas el puerto
*/
info(new String(data) + " - " + request.getAddress() + ":" + request.getPort());
}
/**
* (n1+n2)*n3-n4
* procesar lista aqui, o sea, leeremos esos bytes de la siguiente manera
*
*/
private byte[] procesarLista(final DatagramPacket listaEnFormaDeBytes) {
/*
* Wrappers, y escritos con Try-With resources
* constructor usado ByteArrayInputStream(byte buf[], int offset, int length)
* para evitar que el datagrama contenga algun valor mother fucker
*/
try (final ByteArrayInputStream byteArray = new ByteArrayInputStream(listaEnFormaDeBytes.getData(), listaEnFormaDeBytes.getOffset(), listaEnFormaDeBytes.getLength());
final InputStreamReader inputStreamReader = new InputStreamReader(byteArray);
final BufferedReader br = new BufferedReader(inputStreamReader)) {
String line;
String asterisco = "";
final StringBuilder sb = new StringBuilder();
while (Objects.nonNull(line = br.readLine())) {
if (line.contains("*")) {
asterisco = line.trim();
break;
}
sb.append(line);
}
if (asterisco.trim().contains("*")) {//si hay asterisco, obtenemos sus bytes
return "*".getBytes();
} else {
final String sLine = sb.toString().trim();
final int n1 = Integer.parseInt(sLine.split("-")[0]);
final int n2 = Integer.parseInt(sLine.split("-")[1]);
final int n3 = Integer.parseInt(sLine.split("-")[2]);
final int n4 = Integer.parseInt(sLine.split("-")[3]);
final int iResultado = (n1 + n2) * n3 - n4;
return ("-> Resultado (n1 + n2 ) * n3 - n4: " + iResultado).getBytes();
}
} catch (IOException ex) {
error(ex.toString());
}
return new byte[0];//cero en caso de algún error
}
/**
*
* @return String con la hora formateada
*/
private String getHora() {
return DateTimeFormatter.ofPattern("eeee, d 'de' MMMM 'de' uuuu hh:mm:ssS a")
.withLocale(Locale.getDefault())
.withZone(ZoneId.systemDefault())
.format(Instant.now());
}
public static void main(String... queVivaLaPachamama) {
new ServerUDPListaProcesarPoC();
}
}
Cliente PoC
Código (java) [Seleccionar]
package com.foro;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.Scanner;
import java.util.concurrent.CopyOnWriteArrayList;
import javax.swing.JOptionPane;
/**
* @author rub´n
*/
public class ClientUDPListaProcesarPoC implements UDPLogger {
private static final int PUERTO = 13;
private final byte[] byteBuffer = new byte[1024]; //1k
private static final Scanner LEER = new Scanner(System.in);
private Boolean isFinished = Boolean.FALSE;
/*
* Unico constructor de esta clase
*/
public ClientUDPListaProcesarPoC() {
initClientUDP();
}
private Boolean isFinished() {
return isFinished;
}
private void initClientUDP() {
while (!isFinished()) {
try (final DatagramSocket socket = new DatagramSocket(0)) {// Cero, produce un puerto aleatorio
socket.setSoTimeout(5000); //5 segundos de tiempo de espera maximo
final InetAddress localHost = InetAddress.getLocalHost();//conexion con localhost
final DatagramPacket request = new DatagramPacket(byteBuffer, byteBuffer.length, localHost, PUERTO);
final byte[] listaParaProcesarEnServidor = getListaParaProcesarEnServidor();
request.setData(listaParaProcesarEnServidor);
/*
* enviando los datos al servidor
*/
socket.send(request);
/*
* leyendo respuesta del server
*/
respuestasDelServidor(socket);
} catch (IOException e) {
error(e.toString());
}
}
}
/**
* @param socket
*/
private void respuestasDelServidor(final DatagramSocket socket) {
/*
* Aqui craremos 2 datagramas uno para la fecha y otro para la lista
* el primer datagrama equivale a la fecha, solo de ejemplo
*/
try {
final DatagramPacket response = new DatagramPacket(byteBuffer, byteBuffer.length);
socket.receive(response);
final String dataGrama1 = new String(response.getData(), response.getOffset(), response.getLength(), StandardCharsets.UTF_8);
info(dataGrama1);
/*
* En este datagrama si viene la lista con el resultado
*/
final DatagramPacket response2 = new DatagramPacket(byteBuffer, byteBuffer.length);
socket.receive(response2);
final String dataGrama2 = new String(response2.getData(), response2.getOffset(), response2.getLength(), StandardCharsets.UTF_8);
if (dataGrama2.equals("*")) {
info("Conexion cerrada");
JOptionPane.showMessageDialog(null, "Conexion cerrada.");
socket.close();
isFinished = Boolean.TRUE; //flag para salir del while de este cliente
}
info(dataGrama2);
} catch (IOException e) {
error(e.toString());
}
}
/**
* @return byte[] que seran enviados al Servidor para procesar
*/
private byte[] getListaParaProcesarEnServidor() {
final List<String> listaNumeros = new CopyOnWriteArrayList<>();
info("Introduce 4 numeros, o (*) para cerrar conexión");
for (int f = 0; f < 4; f++) {
info("Introduce numero " + (f + 1));
final String value = LEER.next().trim();
if (value.contains("*")) {//si contiene es *, salir del for
listaNumeros.add(value);
break;
}
listaNumeros.add(value);
}
/*
* String retornado con metodo join mas concatenacion de - entre sus numeros
* para usarlos como flag en el server desde la línea 153
* por ultimo invocamos a getBytes() gracias al paso anterior
*/
return String.join("-", listaNumeros).getBytes();
}
public static void main(String... MaduroMotherFucker) {
new ClientUDPListaProcesarPoC();
}
}
Versión Server PoC con builder básico.
Código (java) [Seleccionar]
package com.foro;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import static java.util.Objects.nonNull;
/**
* @author rub´n
*
*
ServerUDPListaProcesarPoC.newBuilder()
.conPuertoMasBufferSize(13, 1024)
.conFlagParaCerrarPuerto("*")
.conNumeroDeHilos(50)
.crearSocketUdp()
.respuesta()
.build();
*/
public class ServerUDPListaProcesarPoC implements UDPLogger {
private int puerto;
private int bufferSize;
private int numeroHilos;
private DatagramSocket socket;
private DatagramPacket datagramPacket;
private String flagParaCerrarPuerto;
private ExecutorService es;
/**
* Unico constructor de esta clase
*/
private ServerUDPListaProcesarPoC() {
}
public static ServerUDPListaProcesarPoC newBuilder() {
return new ServerUDPListaProcesarPoC();
}
public ServerUDPListaProcesarPoC conNumeroDeHilos(int numeroDeHilos) {
es = Executors.newFixedThreadPool(numeroDeHilos);
return this;
}
public ServerUDPListaProcesarPoC conPuertoMasBufferSize(final int puerto, final int bufferSize) {
this.bufferSize = bufferSize;
this.puerto = puerto;
return this;
}
public ServerUDPListaProcesarPoC conFlagParaCerrarPuerto(final String flag) {
this.flagParaCerrarPuerto = flag;
return this;
}
public ServerUDPListaProcesarPoC build() {
return new ServerUDPListaProcesarPoC();
}
/**
* Equivalen a 2 datagramas aka UDP packets
* <p>
* dos metodos que ejecutara el server al cliente
* la hora y la lista de numeros procesadas con la formula (n1 + n2 ) * n3 - n4;
* - enviarHoraAlCliente(datagramSocket, request);
* - enviarListaProcesadaAlCliente(datagramSocket, request);
*/
private ServerUDPListaProcesarPoC crearSocketUdp() {
try {
this.socket = new DatagramSocket(puerto);
info("Servidor UDP iniciado correctamente por el puerto: " + puerto);
} catch (IOException e) {
error(e.toString());
}
return this;
}
public ServerUDPListaProcesarPoC respuesta() {
CompletableFuture.runAsync(() -> {
while (Boolean.TRUE) {
final byte[] byteBuffer = new byte[bufferSize];
this.datagramPacket = new DatagramPacket(byteBuffer, byteBuffer.length);
try {
this.socket.receive(datagramPacket);
} catch (IOException e) {
e.printStackTrace();
}
enviarHoraAlCliente();
enviarListaProcesadaAlCliente();
}
},es);
return this;
}
/**
* enviar hora al cliente
*
*/
private ServerUDPListaProcesarPoC enviarHoraAlCliente() {
/*
* Metodo que obtiene la hora como ejemplo
* solo ejemplo :D
*/
final byte[] data = getHora().getBytes();
/*
* Este datagrama se le enviara como crearSocketUdp al cliente
*/
final DatagramPacket response = new DatagramPacket(data, data.length, this.datagramPacket.getAddress(), this.datagramPacket.getPort());
try {
/*
* Enviando datos al cliente
*/
this.socket.send(response);
} catch (IOException e) {
error(e.toString());
}
/*
* Imprimimos el datagrama UDP originado, junto con la direccion ip del cliente mas el puerto
*/
info(new String(data) + " - " + datagramPacket.getAddress() + ":" + datagramPacket.getPort());
return this;
}
/**
*/
private ServerUDPListaProcesarPoC enviarListaProcesadaAlCliente() {
/*
* Request
*/
final byte[] data = procesarLista(datagramPacket);
final DatagramPacket respuestaAlCliente = new DatagramPacket(data, data.length, datagramPacket.getAddress(), datagramPacket.getPort());
try {
/*
* Enviando datos al cliente
*/
this.socket.send(respuestaAlCliente);
} catch (IOException e) {
error(e.toString());
}
/*
* Imprimimos el datagrama UDP originado, junto con la direccion ip del cliente mas el puerto
*/
info(new String(data) + " - " + datagramPacket.getAddress() + ":" + datagramPacket.getPort());
return this;
}
/**
* (n1+n2)*n3-n4
* procesar lista aqui, o sea, leeremos esos bytes de la siguiente manera
*/
private byte[] procesarLista(final DatagramPacket listaEnFormaDeBytes) {
/*
* Wrappers, y escritos con Try-With resources
* constructor usado ByteArrayInputStream(byte buf[], int offset, int length)
* para evitar que el datagrama contenga algun valor mother fucker
*/
try (final ByteArrayInputStream byteArray = new ByteArrayInputStream(listaEnFormaDeBytes.getData(),
listaEnFormaDeBytes.getOffset(), listaEnFormaDeBytes.getLength());
final InputStreamReader inputStreamReader = new InputStreamReader(byteArray);
final BufferedReader br = new BufferedReader(inputStreamReader)) {
String line;
String asterisco = "";
final StringBuilder sb = new StringBuilder();
while (nonNull(line = br.readLine())) {
if (line.contains(flagParaCerrarPuerto)) {
asterisco = line.trim();
break;
}
sb.append(line);
}
if (asterisco.trim().contains(flagParaCerrarPuerto)) {//si hay asterisco, obtenemos sus bytes
return flagParaCerrarPuerto.getBytes();
} else {
final String sLine = sb.toString().trim();
final int n1 = Integer.parseInt(sLine.split("-")[0]);
final int n2 = Integer.parseInt(sLine.split("-")[1]);
final int n3 = Integer.parseInt(sLine.split("-")[2]);
final int n4 = Integer.parseInt(sLine.split("-")[3]);
final int iResultado = (n1 + n2) * n3 - n4;
return ("-> Resultado (n1 + n2 ) * n3 - n4: " + iResultado).getBytes();
}
} catch (IOException ex) {
error(ex.toString());
}
return new byte[0];//cero en caso de algún error
}
public static void main(String... queVivaLaPachamama) {
ServerUDPListaProcesarPoC.newBuilder()
.conPuertoMasBufferSize(13, 1024)
.conFlagParaCerrarPuerto("*")
.conNumeroDeHilos(50)
.crearSocketUdp()
.respuesta()
.build();
}
}