quemen redes

This commit is contained in:
binlaab
2026-04-20 22:38:38 +02:00
parent aa8b7b30fb
commit 25bf19ee9c
15 changed files with 414 additions and 42 deletions

View File

@@ -7,6 +7,8 @@ import java.io.RandomAccessFile;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.UnknownHostException;
import java.text.SimpleDateFormat;
import java.util.Date;
import es.um.redes.nanoFiles.tcp.message.PeerMessage;
import es.um.redes.nanoFiles.tcp.message.PeerMessageOps;
@@ -18,20 +20,25 @@ public class NFConnector {
private InetSocketAddress serverAddr;
private DataInputStream dis;
private DataOutputStream dos;
public NFConnector(InetSocketAddress fserverAddr) throws UnknownHostException, IOException {
serverAddr = fserverAddr;
/*
* TODO: (Boletín SocketsTCP) Se crea el socket a partir de la dirección del
* done: (Boletín SocketsTCP) Se crea el socket a partir de la dirección del
* servidor (IP, puerto). La creación exitosa del socket significa que la
* conexión TCP ha sido establecida.
*/
/*
* TODO: (Boletín SocketsTCP) Se crean los DataInputStream/DataOutputStream a
* done: (Boletín SocketsTCP) Se crean los DataInputStream/DataOutputStream a
* partir de los streams de entrada/salida del socket creado. Se usarán para
* enviar (dos) y recibir (dis) datos del servidor.
*/
socket = new Socket(serverAddr.getAddress(), serverAddr.getPort());
dis = new DataInputStream(socket.getInputStream());
dos = new DataOutputStream(socket.getOutputStream());
@@ -39,9 +46,33 @@ public class NFConnector {
public void test() {
/*
* TODO: (Boletín SocketsTCP) Enviar entero cualquiera a través del socket y
* done: (Boletín SocketsTCP) Enviar entero cualquiera a través del socket y
* después recibir otro entero, comprobando que se trata del mismo valor.
*/
/* double rand = Math.random() * 100;
int intNumber = (int) rand;
dos.writeInt(intNumber);
System.out.println("sent " + intNumber);
int newIntNumber = dis.readInt();
System.out.println("received " + intNumber);
*/
try {
PeerMessage msgOut = new PeerMessage(PeerMessageOps.OPCODE_REQUEST_PEER_FILES);
msgOut.writeMessageToOutputStream(dos);
System.out.println("sent " + PeerMessageOps.opcodeToOperation(msgOut.getOpcode()));
PeerMessage msgIn = PeerMessage.readMessageFromInputStream(dis);
System.out.println("received " + PeerMessageOps.opcodeToOperation(msgIn.getOpcode()));
System.out.println("(" + new SimpleDateFormat("HH:mm:ss:SS").format(new Date()));
if (msgIn.getOpcode() == PeerMessageOps.OPCODE_PEER_FILE) {
System.out.println("file content: ");
System.out.println("last = " + msgIn.getLast());
System.out.println("fileSize = " + msgIn.getFileSize());
System.out.println("hash = " + msgIn.getFileHash());
System.out.println("long = " + msgIn.getFilenameLong());
System.out.println("val = " + msgIn.getFilenameVal());
}
socket.close();
} catch (IOException e) { e.printStackTrace(); }
}

View File

@@ -10,7 +10,7 @@ public class PeerMessage {
public static final byte HASH_LENGTH = 40;
private byte opcode;
/*
@@ -18,6 +18,11 @@ public class PeerMessage {
* específicos para crear mensajes con otros campos, según sea necesario
*
*/
private boolean last;
private long fileSize;
private String fileHash;
private byte filenameLong;
private String filenameVal;
@@ -40,9 +45,49 @@ public class PeerMessage {
return opcode;
}
public boolean isLast() {
return last;
}
public void setLast(boolean last) {
this.last = last;
}
public boolean getLast() {
return last;
}
public long getFileSize() {
return fileSize;
}
public void setFileSize(long fileSize) {
this.fileSize = fileSize;
}
public String getFileHash() {
return fileHash;
}
public void setFileHash(String fileHash) {
this.fileHash = fileHash;
}
public byte getFilenameLong() {
return filenameLong;
}
public void setFilenameLong(byte filenameLong) {
this.filenameLong = filenameLong;
}
public String getFilenameVal() {
return filenameVal;
}
public void setFilenameVal(String filenameVal) {
this.filenameVal = filenameVal;
}
/**
* Método de clase para parsear los campos de un mensaje y construir el objeto
@@ -65,6 +110,31 @@ public class PeerMessage {
PeerMessage message = new PeerMessage();
byte opcode = dis.readByte();
switch (opcode) {
case PeerMessageOps.OPCODE_REQUEST_PEER_FILES:
case PeerMessageOps.OPCODE_PEER_FILES_ERROR: break;
case PeerMessageOps.OPCODE_PEER_FILE: {
boolean last = false;
byte lastVal = dis.readByte();
if (lastVal == 1) {
last = true;
}
long fileSize = dis.readLong();
byte[] fileHash = new byte[HASH_LENGTH];
dis.readFully(fileHash);
byte filenameLong = dis.readByte();
byte[] filenameVal = new byte[filenameLong];
dis.readFully(filenameVal);
message.setLast(last);
message.setFileSize(fileSize);
message.setFileHash(new String(fileHash));
message.setFilenameLong(filenameLong);
message.setFilenameVal(new String(filenameVal));
}
@@ -87,6 +157,21 @@ public class PeerMessage {
dos.writeByte(opcode);
switch (opcode) {
case PeerMessageOps.OPCODE_REQUEST_PEER_FILES:
case PeerMessageOps.OPCODE_PEER_FILES_ERROR: break;
case PeerMessageOps.OPCODE_PEER_FILE: {
byte lastVal = 0;
if (last) {
lastVal = 1;
}
dos.writeByte(lastVal);
dos.writeLong(fileSize);
dos.write(fileHash.getBytes());
dos.write(filenameLong);
dos.write(filenameVal.getBytes());
break;
}

View File

@@ -12,7 +12,9 @@ public class PeerMessageOps {
* los diferentes tipos de mensajes del protocolo de comunicación con un par
* servidor de ficheros (valores posibles del campo "operation").
*/
public static final byte OPCODE_REQUEST_PEER_FILES = 1;
public static final byte OPCODE_PEER_FILE = 2;
public static final byte OPCODE_PEER_FILES_ERROR = 3;
@@ -22,14 +24,14 @@ public class PeerMessageOps {
* su representación textual a "valid_operations_str" EN EL MISMO ORDEN.
*/
private static final Byte[] _valid_opcodes = { OPCODE_INVALID_CODE,
OPCODE_REQUEST_PEER_FILES,
OPCODE_PEER_FILE,
OPCODE_PEER_FILES_ERROR
};
private static final String[] _valid_operations_str = { "INVALID_OPCODE",
"REQUEST_PEER_FILES",
"PEER_FILE",
"PEER_FILES_ERROR"
};
private static Map<String, Byte> _operation_to_opcode;

View File

@@ -1,6 +1,9 @@
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;
@@ -11,22 +14,26 @@ 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 {
/*
* TODO: (Boletín SocketsTCP) Crear una direción de socket a partir del puerto
* done: (Boletín SocketsTCP) Crear una direción de socket a partir del puerto
* especificado (PORT)
*/
/*
* TODO: (Boletín SocketsTCP) Crear un socket servidor y ligarlo a la dirección
* 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);
}
/**
@@ -47,16 +54,40 @@ public class NFServer implements Runnable {
while (true) {
/*
* TODO: (Boletín SocketsTCP) Usar el socket servidor para esperar conexiones de
* done: (Boletín SocketsTCP) Usar el socket servidor para esperar conexiones de
* otros peers que soliciten descargar ficheros.
*/
/*
* TODO: (Boletín SocketsTCP) Tras aceptar la conexión con un peer cliente, la
* 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) {
// ???????
}
}
}
@@ -69,6 +100,7 @@ public class NFServer implements Runnable {
* @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
@@ -87,6 +119,26 @@ public class NFServer implements Runnable {
* 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);
}
}
@@ -129,7 +181,15 @@ public class NFServer implements Runnable {
* 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();
}
}

View File

@@ -0,0 +1,29 @@
package es.um.redes.nanoFiles.tcp.server;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;
public class NFServerState {
private int numberOfConnections;
private ArrayList<Socket> sockets;
public NFServerState() {
numberOfConnections = 0;
sockets = new ArrayList<>();
}
public int getNumberOfConnections() {
return numberOfConnections;
}
public List<Socket> getSockets() {
// tu puta madre va a hacer copias
return sockets;
}
public void updateState(Socket socket) {
sockets.add(socket);
numberOfConnections++;
}
}

View File

@@ -10,7 +10,15 @@ public class NFServerThread extends Thread {
* (un socket distinto para "conversar" con un cliente)
*/
private Socket socket;
public NFServerThread(Socket externalSocket, NFServerState state) {
socket = externalSocket;
state.updateState(socket);
}
public void run() {
NFServer.serveFilesToClient(socket);
}
}