diff --git a/src/ftp/Controller.java b/src/ftp/Controller.java index 9ec34877474d622583de0c3c48300fb336b9a71e..388b890e9ac684a6aef9d491dc409eae7209fa49 100644 --- a/src/ftp/Controller.java +++ b/src/ftp/Controller.java @@ -27,7 +27,6 @@ public class Controller extends Server { this.timeout = timeout; this.rbPeriod = rbPeriod; - openSelector(); } @@ -53,17 +52,7 @@ public class Controller extends Server { switch(args[0]) { case "JOIN": key.attach(new DstoreConnection(new Index(), Integer.parseInt(args[1]))); - - SocketChannel toDstore = null; - try { - toDstore = SocketChannel.open(new InetSocketAddress(Integer.parseInt(args[1]))); - toDstore.register(selector, SelectionKey.OP_WRITE); - } catch (IOException e) { - e.printStackTrace(); - } - - sendMessage("test",toDstore,buffer); - + sendMessage("LIST",key,buffer); break; } } diff --git a/src/ftp/Server.java b/src/ftp/Server.java index f2682c33df9fa881fe14fa92bcb6c5215253b497..1e50b2532b254be20ad19a4c6343e474aa6813ee 100644 --- a/src/ftp/Server.java +++ b/src/ftp/Server.java @@ -2,8 +2,10 @@ package ftp; import java.io.IOException; import java.net.InetSocketAddress; +import java.net.Socket; import java.nio.ByteBuffer; import java.nio.channels.*; +import java.util.Arrays; import java.util.Iterator; import java.util.Set; @@ -15,9 +17,19 @@ public abstract class Server { protected Selector selector; + /** + * @desc abstract method which handles server requests based on implmentation + * @param request request to be handled + * @param key corresponding key + * @param buffer buffer to be used for r/w + */ protected abstract void handleRequest(String request, SelectionKey key, ByteBuffer buffer); + /** + * @desc starts the selector and begins the server loop + * @throws IOException + */ protected void openSelector() throws IOException { selector = Selector.open(); ServerSocketChannel serverSocket = ServerSocketChannel.open(); @@ -26,6 +38,59 @@ public abstract class Server { serverSocket.register(selector, SelectionKey.OP_ACCEPT); ByteBuffer buffer = ByteBuffer.allocate(256); //buffer to read/write + System.out.println("Selector Started"); + + while (true) { + selector.select(); + Set<SelectionKey> selectedKeys = selector.selectedKeys(); + Iterator<SelectionKey> iter = selectedKeys.iterator(); + while (iter.hasNext()) { + + SelectionKey key = iter.next(); + + if (key.isAcceptable()) { + System.out.println("Server socket ready to accept connection"); + register(selector, serverSocket); + } + + if (key.isConnectable()) { + System.out.println("Channel is ready to connect to the server"); + } + + if (key.isReadable()) { + System.out.println("Channel has data to be read"); + String request = takeRequest(buffer, key); + handleRequest(request, key, buffer); + } + + iter.remove(); + } + } + } + + + /** + * @desc starts the selector and begins the server loop, registers given initial channels + * @param channels initial channels to be registered with the selector + * @throws IOException + */ + protected void openSelector(SocketChannel[] channels) throws IOException{ + selector = Selector.open(); + ServerSocketChannel serverSocket = ServerSocketChannel.open(); + serverSocket.bind(new InetSocketAddress(port)); + serverSocket.configureBlocking(false); + + serverSocket.register(selector, SelectionKey.OP_ACCEPT); + Iterator<SocketChannel> sockIt = Arrays.stream(channels).iterator(); + while (sockIt.hasNext()) { + SocketChannel channel = sockIt.next(); + channel.register(selector, SelectionKey.OP_READ | SelectionKey.OP_WRITE); + } + + ByteBuffer buffer = ByteBuffer.allocate(256); //buffer to read/write + + System.out.println("Selector Started"); + while (true) { selector.select(); Set<SelectionKey> selectedKeys = selector.selectedKeys(); @@ -35,10 +100,16 @@ public abstract class Server { SelectionKey key = iter.next(); if (key.isAcceptable()) { + System.out.println("Server socket ready to accept connection"); register(selector, serverSocket); } + if (key.isConnectable()) { + System.out.println("Channel is ready to connect to the server"); + } + if (key.isReadable()) { + System.out.println("Channel has data to be read"); String request = takeRequest(buffer, key); handleRequest(request, key, buffer); } @@ -49,13 +120,27 @@ public abstract class Server { } + /** + * @desc registers a newly accepted channel with the selector + * @param selector selector to be registered with + * @param serverSocket server socket which accepts the connection + * @throws IOException + */ protected void register(Selector selector, ServerSocketChannel serverSocket) throws IOException { SocketChannel client = serverSocket.accept(); + System.out.println("Channel accepted"); client.configureBlocking(false); client.register(selector, SelectionKey.OP_READ); } + /** + * @desc reads request from buffer + * @param buffer buffer to read request from + * @param key key linking to the channel + * @return returns the request + * @throws IOException + */ protected String takeRequest(ByteBuffer buffer, SelectionKey key) throws IOException { SocketChannel client = (SocketChannel) key.channel(); client.read(buffer); @@ -65,42 +150,100 @@ public abstract class Server { } - protected String sendMessage(String msg, SelectionKey key, ByteBuffer buffer) { - buffer.clear(); + /** + * @desc sends a message using a given key and waits for a response + * @param msg message to be sent + * @param key key of corresponding channel to send message through + * @param buffer buffer to r/w messages + * @return + */ + protected String sendMessageResponse(String msg, SelectionKey key, ByteBuffer buffer) { buffer = ByteBuffer.wrap(msg.getBytes()); -System.out.println(msg); + SocketChannel channel = (SocketChannel) key.channel(); String response = null; try { channel.write(buffer); buffer.clear(); + System.out.println("Sent message: " + msg); + channel.read(buffer); response = new String(buffer.array()).trim(); - buffer.clear(); } catch (IOException e) { e.printStackTrace(); } + return response; } - protected String sendMessage(String msg, SocketChannel channel, ByteBuffer buffer) { - buffer.clear(); + /** + * @desc sends a message using a given channel and waits for a response + * @param msg message to be sent + * @param channel channel to send message through + * @param buffer buffer to r/w messages + * @return + */ + protected String sendMessageResponse(String msg, SocketChannel channel, ByteBuffer buffer) { buffer = ByteBuffer.wrap(msg.getBytes()); String response = null; try { channel.write(buffer); buffer.clear(); + System.out.println("Sent message: " + msg); + channel.read(buffer); response = new String(buffer.array()).trim(); - buffer.clear(); } catch (IOException e) { e.printStackTrace(); } + return response; } + /** + * @desc sends a message using a given key, does not wait for a response + * @param msg message to be sent + * @param key key of corresponding channel to send message through + * @param buffer buffer to r/w messages + * @return + */ + protected void sendMessage(String msg, SelectionKey key, ByteBuffer buffer) { + buffer = ByteBuffer.wrap(msg.getBytes()); + + SocketChannel channel = (SocketChannel) key.channel(); + + try { + channel.write(buffer); + buffer.clear(); + System.out.println("Sent message: " + msg); + } catch (IOException e) { + e.printStackTrace(); + } + } + + + /** + * @desc sends a message using a given channel, does not wait for a response + * @param msg message to be sent + * @param channel channel to send message through + * @param buffer buffer to r/w messages + * @return + */ + protected void sendMessage(String msg, SocketChannel channel, ByteBuffer buffer) { + buffer = ByteBuffer.wrap(msg.getBytes()); + + try { + channel.write(buffer); + buffer.clear(); + System.out.println("Sent message: " + msg); + } catch (IOException e) { + e.printStackTrace(); + } + } + + } diff --git a/src/ftp/dstore1/Dstore.java b/src/ftp/dstore1/Dstore.java index c02abeced73adccd33de31fd426be1947339f039..5057094d23c75b51b31f3fca1af34f592009fcaf 100644 --- a/src/ftp/dstore1/Dstore.java +++ b/src/ftp/dstore1/Dstore.java @@ -7,6 +7,7 @@ import ftp.Server; import java.io.File; import java.io.IOException; import java.net.InetSocketAddress; +import java.net.SocketException; import java.nio.ByteBuffer; import java.nio.channels.SelectionKey; import java.nio.channels.SocketChannel; @@ -37,37 +38,24 @@ public class Dstore extends Server { this.file_folder = file_folder; + ByteBuffer buffer = ByteBuffer.allocate(256); + + // opening connection to controller // open(addr) acts as convenience method for open() and connect() // in blocking mode, so will wait for response before progressing // try { toController = SocketChannel.open(new InetSocketAddress(cport)); + toController.configureBlocking(false); } catch (IOException e) { e.printStackTrace(); } - ByteBuffer buffer = ByteBuffer.allocate(256); sendMessage("JOIN " + port, toController, buffer); - - openSelector(); - - - /* - // creating server socket to receive files - // - ServerSocketChannel serverSocket = ServerSocketChannel.open(); - serverSocket.bind(new InetSocketAddress(port)); - while (true) { - SocketChannel client = serverSocket.accept(); - - new Thread( () -> { - - } ).start(); - } - */ + openSelector(new SocketChannel[] {toController}); } @@ -93,10 +81,14 @@ public class Dstore extends Server { } - private File[] list() { - File folder = new File("./storage"); - return folder.listFiles(); - } +// /** +// * @desc lists the files of the datastore +// * @return +// */ +// private File[] list() { +// File folder = new File("./storage"); +// return folder.listFiles(); +// } @Override @@ -105,9 +97,14 @@ public class Dstore extends Server { switch(args[0]) { case "LIST": - String fileNames = Arrays.stream(list()) - .map(File::getName) + File folder = new File("./storage"); + String[] files = folder.list(); +// String fileNames = Arrays.stream(list()) +// .map(File::getName) +// .reduce("", (file1, file2) -> file1 + " " + file2); + String fileNames = Arrays.stream(files) .reduce("", (file1, file2) -> file1 + " " + file2); + System.out.println(fileNames); sendMessage(fileNames, key, buffer); break; diff --git a/src/ftp/dstore1/storage/test.txt b/src/ftp/dstore1/storage/test.txt new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391