Autor
|
Tema: Cómo enviar un ArrayList del cliente al servidor usando UDP? (Leído 4,965 veces)
|
novato991
Desconectado
Mensajes: 4
|
Quiero enviar una lista de números al servidor para que este al leerlos efectúe las operaciones correspondientes y devuelva el resultado de las mismas al cliente. Luego volverá a pedir números al cliente y de nuevo le devolverá el resultado correspondiente, repitiéndose el proceso hasta que el cliente introduzca un *, entonces ahí se cerraría conexión con el servidor. Tengo que hacerlo obligatoriamente utilizando protocolo UDP. El problema es que al mandar los números por lo visto al servidor no le llegan dichos números y no hace nada. Cuando ejecuto el programa me pide los 4 números, los introduzco y ahí es donde se queda parado, el servidor no devuelve ningún resultado. Para guardar los números he utilizado el ArrayList numeros... el problema es el proceso para empaquetar esa lista de números en bytes, mandarlo al servidor y que este lo decodifique y lea esos números, ahí por lo visto no le llega la información al servidor. Soy un novato en esto de conexiones TCP/UDP, seguro que me habré equivocado pero no sé como solucionarlo, espero podáis orientarme un poco, porque estoy más perdido que un pulpo en un garaje. Dejo los códigos de Servidor y Cliente, a ver si podéis decirme dónde he fallado... import java.awt.List; import java.io.ByteArrayInputStream; import java.io.ObjectInputStream; import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.InetAddress; import java.util.ArrayList; public class Servidor { byte[] infoRecibida = new byte[1024]; byte[] infoEnviada = new byte[1024]; byte[] paquete = new byte[1024]; int n1,n2,n3,n4; int res; while (true) { System. out. println("Esperando datagrama..."); infoRecibida = new byte[1024]; serverSocket.receive(paqRecibido); // IP y puerto desde donde se manda mensaje int puerto = paqRecibido.getPort(); //Estas dos lineas supuestamente serían para poder leer el arraylist enviado desde el cliente, aunque igual estoy equivocado ArrayList<Integer> numeros = (ArrayList<Integer>)inputStream.readObject(); n1 = numeros.get(0); n2 = numeros.get(1); n3 = numeros.get(2); n4 = numeros.get(3); // Si alguno de los números introducidos es * // envío "x" al cliente para que este se cierre, posteriormente sale del bucle y se cierra también el servidor if (num1=="*"||num2=="*"||num3=="*"||num4=="*") { x = "x"; paquete = x.getBytes(); break; } //Hago las operaciones, el resultado lo paso a cadena y luego a bytes, para ser enviado al cliente res=(n1+n2)*n3-n4; infoEnviada=num.getBytes(); // ENVIO DATAGRAMA AL CLIENTE serverSocket.send(paqEnviado); } //Fin While serverSocket.close(); System. out. println("Socket cerrado..."); } }
import java.io.BufferedReader; import java.io.ByteArrayOutputStream; import java.io.InputStreamReader; import java.io.ObjectOutputStream; import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.InetAddress; import java.util.ArrayList; public class Cliente { //para recibir y enviar datos byte[] datosEnviados = new byte[1024]; byte[] datosRecibidos = new byte[1024]; InetAddress IPServidor = InetAddress. getByName(... ); //En el paréntesis iría el número de ip del servidor adonde quiero mandarlo int puerto = 6000; ArrayList<Integer> numeros = new ArrayList<>(); while(true) { //Rellenamos ArrayList numeros for(int i=0; i<4;i++) { System. out. println("Introduce un mensaje: "); cadena = in.readLine(); numeros. add(Integer. parseInt(cadena )); } //Empaquetamos ArrayList en bytes para poder enviarlo al servidor outputStream.writeObject(numeros); byte[] listData = out.toByteArray(); clientSocket.send(envio); outputStream.close(); //recibimos respuesta del servidor System. out. println("Esperando datagrama..."); clientSocket.receive(recibo); //Si el dato que devuelve el servidor es "x", salimos del bucle y se cierra el cliente if (numero.equals("x")) { break; } System. out. println("\t Datos: " + numero ); } //Fin While clientSocket.close(); //Cerramos cliente } }
Mod: Obligatorio el uso de etiquetas GeSHi para sources.
|
|
« Última modificación: 27 Mayo 2019, 16:13 pm por #!drvy »
|
En línea
|
|
|
|
rub'n
Desconectado
Mensajes: 1.217
(e -> λ("live now")); tatuar -> λ("α");
|
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 GeSHiimport 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 PoCpackage 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() { info("Servidor UDP iniciado correctamente por el puerto: " + PUERTO); try { final byte[] byteBuffer = new byte[1024]; datagramSocket.receive(request); enviarHoraAlCliente(datagramSocket, request); enviarListaProcesadaAlCliente(datagramSocket, request); error(e.toString()); } } error(e.toString()); } } /** * enviar hora al cliente * * @param request * @param socket */ /* * Metodo que obtiene la hora como ejemplo * solo ejemplo :D */ final byte[] data = getHora().getBytes(); /* * Este datagrama se le enviara como respuesta al cliente */ try { /* * Enviando datos al cliente */ socket.send(response); 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 */ /* * Request */ final byte[] data = procesarLista(request); try { /* * Enviando datos al cliente */ socket.send(response); 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 */ 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(); } error(ex.toString()); } return new byte[0];//cero en caso de algún error } /** * * @return String con la hora formateada */ 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 PoCpackage 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); /* * Unico constructor de esta clase */ public ClientUDPListaProcesarPoC() { initClientUDP(); } return isFinished; } private void initClientUDP() { while (!isFinished()) { socket.setSoTimeout(5000); //5 segundos de tiempo de espera maximo final byte[] listaParaProcesarEnServidor = getListaParaProcesarEnServidor(); request.setData(listaParaProcesarEnServidor); /* * enviando los datos al servidor */ socket.send(request); /* * leyendo respuesta del server */ respuestasDelServidor(socket); error(e.toString()); } } } /** * @param 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 { 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 */ 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); 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.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 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 { info("Servidor UDP iniciado correctamente por el puerto: " + puerto); error(e.toString()); } return this; } public ServerUDPListaProcesarPoC respuesta() { CompletableFuture.runAsync(() -> { final byte[] byteBuffer = new byte[bufferSize]; this. datagramPacket = new DatagramPacket(byteBuffer, byteBuffer. length); try { this.socket.receive(datagramPacket); 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 */ try { /* * Enviando datos al cliente */ this.socket.send(response); 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); try { /* * Enviando datos al cliente */ this.socket.send(respuestaAlCliente); 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 */ listaEnFormaDeBytes.getOffset(), listaEnFormaDeBytes.getLength()); 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(); } 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(); } }
|
|
« Última modificación: 5 Junio 2019, 16:19 pm por rub'n »
|
En línea
|
If you don't have time to read, you don't have the time (or the tools) to write, Simple as that. Stephen king
|
|
|
Serapis
|
Soy un novato en esto de conexiones TCP/UDP, seguro que me habré equivocado pero no sé como solucionarlo ... espero podáis orientarme un poco, porque estoy más perdido que un pulpo en un garaje. ... Quiero enviar una lista de números al servidor para que este al leerlos efectúe las operaciones correspondientes y......... devuelva el resultado de las mismas al cliente. Luego volverá a pedir números al cliente y de nuevo le devolverá el resultado correspondiente, repitiéndose el proceso hasta que el cliente introduzca un *, entonces ahí se cerraría conexión con el servidor. Tengo que hacerlo obligatoriamente utilizando protocolo UDP. Tú dí lo que quieras, pero esto apesta a virus que tira para atrás... incluso ese descargo de intenciones del 'pulpo perdido en el garage', hace que apeste todavía más... El protocolo UDP, no se inventó para envío masivo de datos, el que se empeña en ello, no puede tener otra finalidad que camuflar la comunicación de un troyano... Es lo mismo que si un tipo dice que quiere enviar 1000 toneladas de piezas metálicas pero que lo haga un ciclista pieza a pieza... un volumen grande se envía en camiones, trenes, etc... es más rápido y más barato. ...un transportista deja firma en albaranes, partidas de transporte, horarios, etc... que pueden rastrearse. Hacerlo a 'pequeña' escala solo puede tener malas intenciones, a base de no llamar la atención. Así que si alguien quiere mover 1000 toneladas de piezas en bicicleta, lo siento pero pensar que se trata de un terrorista pasa a ser la primera (y probablemente la única) sospecha.
|
|
|
En línea
|
|
|
|
|
Mensajes similares |
|
Asunto |
Iniciado por |
Respuestas |
Vistas |
Último mensaje |
|
|
Transferencia de archivos, usando un servidor y cliente [C#]
.NET (C#, VB.NET, ASP)
|
SeniorX
|
2
|
16,706
|
11 Junio 2006, 19:44 pm
por SeniorX
|
|
|
COMO ENVIAR UN ARCHIVO DE CLIENTE-SERVIDOR EN JAVA
Java
|
lexoazul
|
1
|
9,349
|
16 Octubre 2009, 16:58 pm
por Debci
|
|
|
[TUTORIAL] Aplicación Cliente-Servidor usando la API de Winsock
Programación Visual Basic
|
DJ_MAQUINA
|
0
|
4,389
|
9 Junio 2010, 05:05 am
por DJ_MAQUINA
|
|
|
Enviar datos entre servidor y cliente.
Análisis y Diseño de Malware
|
dopr
|
1
|
3,291
|
9 Agosto 2016, 14:51 pm
por fary
|
|
|
Enviar petición fin ack desde un cliente a un servidor ftp?
Dudas Generales
|
Saito_25
|
3
|
2,668
|
15 Mayo 2018, 20:58 pm
por engel lex
|
|