package es.um.redes.nanoFiles.tcp.server; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; import java.net.InetSocketAddress; import java.net.ServerSocket; import java.net.Socket; public class NFServer implements Runnable { public static final int PORT = 10000; private NFServerState state = new NFServerState(); private ServerSocket serverSocket = null; public ServerSocket getServerSocket() { return serverSocket; } public NFServer() throws IOException { /* * done: (Boletín SocketsTCP) Crear una direción de socket a partir del puerto * especificado (PORT) */ /* * done: (Boletín SocketsTCP) Crear un socket servidor y ligarlo a la dirección * de socket anterior */ InetSocketAddress serverSocketAddress = new InetSocketAddress(PORT); serverSocket = new ServerSocket(); serverSocket.bind(serverSocketAddress); } /** * Método para ejecutar el servidor de ficheros en primer plano. Sólo es capaz * de atender una conexión de un cliente. Una vez se lanza, ya no es posible * interactuar con la aplicación. * */ public void test() { if (serverSocket == null || !serverSocket.isBound()) { System.err.println( "[fileServerTestMode] Failed to run file server, server socket is null or not bound to any port"); return; } else { System.out .println("[fileServerTestMode] NFServer running on " + serverSocket.getLocalSocketAddress() + "."); } while (true) { /* * done: (Boletín SocketsTCP) Usar el socket servidor para esperar conexiones de * otros peers que soliciten descargar ficheros. */ /* * done: (Boletín SocketsTCP) Tras aceptar la conexión con un peer cliente, la * comunicación con dicho cliente para servir los ficheros solicitados se debe * implementar en el método serveFilesToClient, al cual hay que pasarle el * socket devuelto por accept. */ boolean connectionOk = false; Socket socket = null; try { socket = serverSocket.accept(); connectionOk = true; } catch (IOException e) { // conn refused } if (connectionOk) { System.out.println("accepted"); try { DataInputStream dis = new DataInputStream(socket.getInputStream()); DataOutputStream dos = new DataOutputStream(socket.getOutputStream()); int intNumber = dis.readInt(); System.out.println("received " + intNumber); int newInt = intNumber + 1; dos.writeInt(newInt); System.out.println("sent " + newInt); } catch (IOException e) { // ??????? } } } } /** * Método que ejecuta el hilo principal del servidor en segundo plano, esperando * conexiones de clientes. * * @see java.lang.Runnable#run() */ public void run() { boolean stopServer = false; // HAY QUE CAMBIAR ESTO PORQUE NO SÉ DE DÓNDE COJONES SALE (ver TODO l. 147) /* * TODO: (Boletín SocketsTCP) Usar el socket servidor para esperar conexiones de * otros peers que soliciten descargar ficheros */ /* * TODO: (Boletín SocketsTCP) Al establecerse la conexión con un peer, la * comunicación con dicho cliente se hace en el método * serveFilesToClient(socket), al cual hay que pasarle el socket devuelto por * accept */ /* * TODO: (Boletín TCPConcurrente) Crear un hilo nuevo de la clase * NFServerThread, que llevará a cabo la comunicación con el cliente que se * acaba de conectar, mientras este hilo vuelve a quedar a la escucha de * conexiones de nuevos clientes (para soportar múltiples clientes). Si este * hilo es el que se encarga de atender al cliente conectado, no podremos tener * más de un cliente conectado a este servidor. */ while (!stopServer) { Socket socket = null; boolean connectionOk = false; try { socket = serverSocket.accept(); connectionOk = true; } catch (IOException e) { System.err.println("Connection refused"); } if (connectionOk) { NFServerThread serverThread = new NFServerThread(socket, state); serverThread.start(); int connNum = state.getNumberOfConnections(); InetSocketAddress clientAddr = (InetSocketAddress) socket.getRemoteSocketAddress(); System.out.println("New connection from " + clientAddr); System.out.println("Total connections = " + connNum); } } } /* * TODO: (Boletín SocketsTCP) Añadir métodos a esta clase para: 1) Arrancar el * servidor en un hilo nuevo que se ejecutará en segundo plano 2) Detener el * servidor (stopserver) 3) Obtener el puerto de escucha del servidor etc. */ /** * Método de clase que implementa el extremo del servidor del protocolo de * transferencia de ficheros entre pares. * * @param socket El socket para la comunicación con un cliente que desea * descargar ficheros. */ public static void serveFilesToClient(Socket socket) { /* * TODO: (Boletín SocketsTCP) Crear dis/dos a partir del socket */ /* * TODO: (Boletín SocketsTCP) Mientras el cliente esté conectado, leer mensajes * de socket, convertirlo a un objeto PeerMessage y luego actuar en función del * tipo de mensaje recibido, enviando los correspondientes mensajes de * respuesta. */ /* * TODO: (Boletín SocketsTCP) Para servir un fichero, hay que localizarlo a * partir de su hash (o subcadena) en nuestra base de datos de ficheros * compartidos. Los ficheros compartidos se pueden obtener con * NanoFiles.db.getFiles(). Los métodos lookupHashSubstring y * lookupFilenameSubstring de la clase FileInfo son útiles para buscar ficheros * coincidentes con una subcadena dada del hash o del nombre del fichero. El * método lookupFilePath() de FileDatabase devuelve la ruta al fichero a partir * de su hash completo. */ InetSocketAddress clientAddr = (InetSocketAddress) socket.getRemoteSocketAddress(); try { while(true) { DataOutputStream dos = new DataOutputStream(socket.getOutputStream()); DataInputStream dis = new DataInputStream(socket.getInputStream()); } } catch (IOException e) { e.printStackTrace(); } } }