I need to build a Napster-based Centralized Peer-to-Peer File Sharing Applicatio
ID: 3679583 • Letter: I
Question
I need to build a Napster-based Centralized Peer-to-Peer File Sharing Application using Socket and Multi-thread Programming in Java. The application will be designed as a hybrid version of client-server and P2P programming models and by using threads. Centralized Multi-threaded Directory Server: A centralized server will listen on a certain port for incoming connection requests from peers. It will create a separate thread and a socket for each thread and the connection will be active as long as peers are online. The server will provide the following functionalities to the peers: Register peers: The directory server will listen to a TCP socket at a well-known port. A new client peer will contact the directory server at this port and indicate its presence. In addition, the directory server also listens to a UDP socket and every 60 seconds the client peer issues a 'HELLO' message to the UDP port of the registry. If the directory server has not received a HELLO message from a client peer in 200 seconds, the client is removed from the list of available clients. After registration, the client sends a list of files available at the client to the directory server. Search files: Peers will make a search request for a certain file they are looking for to the directory server. The directory server will search on its data structures and return a list of peers (along with their IPs) that have the file requested to the requesting peer. Update peer/file list: When a download takes place, the downloading peer informs the server that it has a new file added to its shared folder and the server will make a change in the file list of the peer. When a peer is offline, the server deletes all information regarding the peer from its data structures. Peer: Peer can interact with the directory server and other peers. It registers itself with the directory server by providing its IP and file list that it wants to share. The peer can search for a certain file and when the server responds with the list of peers who have the file, the peer selects one of the peers and makes a connection request to the peer to download the file. Do not forget while onedownload is in progress, the peer client may have other search requests and download operations. The peer should have a GUI to connect, search for files, list peers and monitor download activity. At the same time, the peer is also a server. When a peer registers with the centralized server, it also launches a peer server to serve download requests coming from other peers. The peer server will be multi-threaded and will be able to serve more than one peer at the same time. It will listen for incoming connections and send requested files. Side note: Any updates to the shared data structures by the threads should be synchronized. All communication will be across TCP sockets except the HELLO messages which are UDP datagrams. The registry has to listen to a well-known ports for registration of new clients and for file queries. Each client also listens for requests for file transfers on a TCP socket If you could comment the code so I know how it works I am trying to figure out how to do this myself as well, Thank you This is what I have so far: * * To change this license header, choose License Headers in Project Properties. * To change this template file, choose Tools | Templates * and open the template in the editor. */ package DirectoryServer; import java.io.IOException; import java.net.*; import java.nio.ByteBuffer; import java.nio.CharBuffer; import java.nio.channels.Channel; import java.nio.channels.DatagramChannel; import java.nio.channels.SelectionKey; import java.nio.channels.Selector; import java.nio.channels.ServerSocketChannel; import java.nio.channels.SocketChannel; import java.nio.charset.Charset; import java.nio.charset.CharsetEncoder; import java.util.Iterator; import java.util.Set; /** * * UDP and TCP Simultaneous listening logic referenced * http://www.java2s.com/Code/Java/Network-Protocol/HandlesTCPandUDPconnectionsandprovidesexceptionhandlinganderrorlogging.htm */ public class DirectoryServer { public static void main(String args[]) throws IOException { CharsetEncoder encoder = Charset.forName("US-ASCII").newEncoder(); int port = 13; if (args.length > 0) port = Integer.parseInt(args[0]); SocketAddress localport = new InetSocketAddress(port); //tcp channel ServerSocketChannel tcpserver = ServerSocketChannel.open(); tcpserver.socket().bind(localport); //udp channel DatagramChannel udpserver = DatagramChannel.open(); udpserver.socket().bind(localport); //selector object will do the blocking tcpserver.configureBlocking(false); udpserver.configureBlocking(false); Selector selector = Selector.open(); tcpserver.register(selector, SelectionKey.OP_ACCEPT); udpserver.register(selector, SelectionKey.OP_READ); ByteBuffer receiveBuffer = ByteBuffer.allocate(0); // Now loop forever, processing client connections while (true) { try { // Wait for a client to connect selector.select(); String date = new java.util.Date().toString() + " "; ByteBuffer response = encoder.encode(CharBuffer.wrap(date)); // Get the SelectionKey objects for the channels that have // activity on them. These are the keys returned by the // register() methods above. They are returned in a // java.util.Set. Set keys = selector.selectedKeys(); // Iterate through the Set of keys. for (Iterator i = keys.iterator(); i.hasNext();) { // Get a key from the set, and remove it from the set SelectionKey key = (SelectionKey) i.next(); i.remove(); // Get the channel associated with the key Channel c = (Channel) key.channel(); // Now test the key and the channel to find out // whether something happend on the TCP or UDP channel if (key.isAcceptable() && c == tcpserver) { // A client has attempted to connect via TCP. // Accept the connection now. SocketChannel client = tcpserver.accept(); // If we accepted the connection successfully, // the send our respone back to the client. if (client != null) { //TODO: TCP thread logic client.close(); // close connection } } else if (key.isReadable() && c == udpserver) { // A UDP datagram is waiting. Receive it now, // noting the address it was sent from. SocketAddress clientAddress = udpserver.receive(receiveBuffer); // If we got the datagram successfully, send // the date and time in a response packet. if (clientAddress != null) udpserver.send(response, clientAddress); //TODO: UDP thread logic } } } catch (java.io.IOException e) { } } } } /* * To change this license header, choose License Headers in Project Properties. * To change this template file, choose Tools | Templates * and open the template in the editor. */ package DirectoryServer; /** * */ public class DirectoryThread extends Thread { @Override public void run() { } } /* * To change this license header, choose License Headers in Project Properties. * To change this template file, choose Tools | Templates * and open the template in the editor. */ package PeerClient; import java.net.Socket; /** * */ public class PeerServerThread extends Thread { private Socket socket = null; private static final int BUFFER_SIZE = 32768; public PeerServerThread(Socket socket) { super("PeerServerThread"); this.socket = socket; } @Override public void run() { } } I also have a Client that I will use to search through the Window.. I am looking for where to go from where I am at this point.. I still need these things: - All GUI Features (including initial connection with files, searching through files, listing peers, and download status) - Peer Server Download logic and connection logic with other peers - Peer Server connection logic to the directory server - Directory Server peer registration logic (Possibly look into using a DHT or Distributed hash table) - Directory Server UDP message checking logic any comments on code would also be very helpful for understanding, thank you
Explanation / Answer
PeerClient.java
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
import java.io.IOException;
import java.net.ServerSocket;
public class PeerClient extends javax.swing.JFrame {
/**
* Creates new form PeerClient
*/
public PeerClient() {
initComponents();
}
/**
* This method is called from within the constructor to initialize the form.
* WARNING: Do NOT modify this code. The content of this method is always
* regenerated by the Form Editor.
*/
@SuppressWarnings("unchecked")
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
private void initComponents() {
jFrame1 = new javax.swing.JFrame();
jFrame2 = new javax.swing.JFrame();
jInternalFrame1 = new javax.swing.JInternalFrame();
jTextField1 = new javax.swing.JTextField();
jButton1 = new javax.swing.JButton();
jButton2 = new javax.swing.JButton();
jLabel1 = new javax.swing.JLabel();
jPanel1 = new javax.swing.JPanel();
javax.swing.GroupLayout jFrame1Layout = new javax.swing.GroupLayout(jFrame1.getContentPane());
jFrame1.getContentPane().setLayout(jFrame1Layout);
jFrame1Layout.setHorizontalGroup(
jFrame1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGap(0, 400, Short.MAX_VALUE)
);
jFrame1Layout.setVerticalGroup(
jFrame1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGap(0, 300, Short.MAX_VALUE)
);
javax.swing.GroupLayout jFrame2Layout = new javax.swing.GroupLayout(jFrame2.getContentPane());
jFrame2.getContentPane().setLayout(jFrame2Layout);
jFrame2Layout.setHorizontalGroup(
jFrame2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGap(0, 400, Short.MAX_VALUE)
);
jFrame2Layout.setVerticalGroup(
jFrame2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGap(0, 300, Short.MAX_VALUE)
);
setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
setTitle("P2P File Share Client");
setResizable(false);
jInternalFrame1.setTitle("Search");
jInternalFrame1.setCursor(new java.awt.Cursor(java.awt.Cursor.DEFAULT_CURSOR));
jInternalFrame1.setVisible(true);
jTextField1.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
jTextField1ActionPerformed(evt);
}
});
jButton1.setText("Search");
jButton2.setText("Stop");
jButton2.setEnabled(false);
jLabel1.setText("Search");
javax.swing.GroupLayout jInternalFrame1Layout = new javax.swing.GroupLayout(jInternalFrame1.getContentPane());
jInternalFrame1.getContentPane().setLayout(jInternalFrame1Layout);
jInternalFrame1Layout.setHorizontalGroup(
jInternalFrame1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(jInternalFrame1Layout.createSequentialGroup()
.addContainerGap()
.addGroup(jInternalFrame1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(jTextField1)
.addGroup(jInternalFrame1Layout.createSequentialGroup()
.addComponent(jButton1)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 27, Short.MAX_VALUE)
.addComponent(jButton2))
.addGroup(jInternalFrame1Layout.createSequentialGroup()
.addComponent(jLabel1)
.addGap(0, 0, Short.MAX_VALUE)))
.addContainerGap())
);
jInternalFrame1Layout.setVerticalGroup(
jInternalFrame1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(jInternalFrame1Layout.createSequentialGroup()
.addGap(15, 15, 15)
.addComponent(jLabel1)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(jTextField1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGap(18, 18, 18)
.addGroup(jInternalFrame1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(jButton1)
.addComponent(jButton2))
.addContainerGap(186, Short.MAX_VALUE))
);
jTextField1.getAccessibleContext().setAccessibleDescription("");
jPanel1.setBorder(javax.swing.BorderFactory.createLineBorder(new java.awt.Color(0, 0, 0)));
javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1);
jPanel1.setLayout(jPanel1Layout);
jPanel1Layout.setHorizontalGroup(
jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGap(0, 532, Short.MAX_VALUE)
);
jPanel1Layout.setVerticalGroup(
jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGap(0, 0, Short.MAX_VALUE)
);
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
getContentPane().setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addComponent(jInternalFrame1)
.addGap(18, 18, 18)
.addComponent(jPanel1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addContainerGap())
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
.addGap(117, 117, 117)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
.addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(jInternalFrame1))
.addContainerGap())
);
pack();
}// </editor-fold>//GEN-END:initComponents
private void jTextField1ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jTextField1ActionPerformed
// TODO add your handling code here:
}//GEN-LAST:event_jTextField1ActionPerformed
private static void startPeerServer(){
try {
int port = 8000; //change this at some point
try {
ServerSocket socket = new ServerSocket(port);
System.out.println("Started on port: " + port);
while (true) {
new PeerServerThread(socket.accept()).start();
}
} catch (IOException e) {
System.err.println("Could not listen on port: " + port);
System.err.println(e.getMessage());
System.exit(-1);
}
} catch (NumberFormatException e) {
System.out.println("Please supply a valid port number");
}
}
/**
* @param args the command line arguments
*/
public static void main(String args[]) {
/* Set the Nimbus look and feel */
//<editor-fold defaultstate="collapsed" desc=" Look and feel setting code (optional) ">
/* If Nimbus (introduced in Java SE 6) is not available, stay with the default look and feel.
* For details see http://download.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html
*/
try {
for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
if ("Nimbus".equals(info.getName())) {
javax.swing.UIManager.setLookAndFeel(info.getClassName());
break;
}
}
} catch (ClassNotFoundException ex) {
java.util.logging.Logger.getLogger(PeerClient.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
} catch (InstantiationException ex) {
java.util.logging.Logger.getLogger(PeerClient.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
} catch (IllegalAccessException ex) {
java.util.logging.Logger.getLogger(PeerClient.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
} catch (javax.swing.UnsupportedLookAndFeelException ex) {
java.util.logging.Logger.getLogger(PeerClient.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
}
//</editor-fold>
/* Create and display the form */
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
new PeerClient().setVisible(true);
}
});
startPeerServer();
}
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JButton jButton1;
private javax.swing.JButton jButton2;
private javax.swing.JFrame jFrame1;
private javax.swing.JFrame jFrame2;
private javax.swing.JInternalFrame jInternalFrame1;
private javax.swing.JLabel jLabel1;
private javax.swing.JPanel jPanel1;
private javax.swing.JTextField jTextField1;
// End of variables declaration//GEN-END:variables
}
PeerServerThread.java
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
import java.net.Socket;
public class PeerServerThread extends Thread
{
private Socket socket = null;
private static final int BUFFER_SIZE = 32768;
public PeerServerThread(Socket socket) {
super("PeerServerThread");
this.socket = socket;
}
@Override
public void run() {
}
}
Related Questions
drjack9650@gmail.com
Navigate
Integrity-first tutoring: explanations and feedback only — we do not complete graded work. Learn more.