commented classes and functions
git-svn-id: svn://anubis/gvsu@65 45c1a28c-8058-47b2-ae61-ca45b979098e
This commit is contained in:
parent
111b16aecd
commit
32633264d5
@ -1,8 +1,19 @@
|
|||||||
|
|
||||||
|
/* Author: Josh Holtrop
|
||||||
|
* GVSU, CS654, Project 1
|
||||||
|
* Date: 2008-03-11
|
||||||
|
*/
|
||||||
|
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
import java.net.*;
|
import java.net.*;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
|
/* FileServer implements a multithreaded file server. The listening
|
||||||
|
* server itself can be run in a thread, and each incoming connection
|
||||||
|
* request to download a file is handled in its own thread, so that
|
||||||
|
* multiple files can be downloaded at the same time, and so that
|
||||||
|
* the entire server can run asynchronously from the main application.
|
||||||
|
*/
|
||||||
public class FileServer implements Runnable
|
public class FileServer implements Runnable
|
||||||
{
|
{
|
||||||
private int m_port;
|
private int m_port;
|
||||||
@ -35,6 +46,7 @@ public class FileServer implements Runnable
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* a class to handle a single file upload */
|
||||||
private class FileHandler implements Runnable
|
private class FileHandler implements Runnable
|
||||||
{
|
{
|
||||||
private Socket m_socket;
|
private Socket m_socket;
|
||||||
|
@ -1,4 +1,10 @@
|
|||||||
|
|
||||||
|
/* Author: Josh Holtrop
|
||||||
|
* GVSU, CS654, Project 1
|
||||||
|
* Date: 2008-03-11
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* KaZa is the launcher class for the KaZa application */
|
||||||
public class KaZa
|
public class KaZa
|
||||||
{
|
{
|
||||||
public static void main(String args[])
|
public static void main(String args[])
|
||||||
|
@ -1,8 +1,21 @@
|
|||||||
|
|
||||||
|
/* Author: Josh Holtrop
|
||||||
|
* GVSU, CS654, Project 1
|
||||||
|
* Date: 2008-03-11
|
||||||
|
*/
|
||||||
|
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
import java.net.*;
|
import java.net.*;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
|
/* KaZaClient implements a file server client which can connect
|
||||||
|
* to a "Mini Napster Hub" (implemented in KaZaServer) and search
|
||||||
|
* for files to download. The files shared by the KaZaClient are
|
||||||
|
* stored in a directory and described by ".kaza" files. The format
|
||||||
|
* of a .kaza description file is a plain text file containing two
|
||||||
|
* lines, the first of which is the name of the actual file to
|
||||||
|
* share and the second of which is a brief description of the file.
|
||||||
|
*/
|
||||||
public class KaZaClient
|
public class KaZaClient
|
||||||
{
|
{
|
||||||
public static final int LISTEN_PORT = 3443;
|
public static final int LISTEN_PORT = 3443;
|
||||||
@ -15,6 +28,9 @@ public class KaZaClient
|
|||||||
private FileServer m_fileServer;
|
private FileServer m_fileServer;
|
||||||
private HashMap<Integer, ClientDownloader> m_clientDownloaders;
|
private HashMap<Integer, ClientDownloader> m_clientDownloaders;
|
||||||
|
|
||||||
|
/* make a KaZaClient object using the given user name,
|
||||||
|
* connection speed (Kbps), path to the directory of shared files,
|
||||||
|
* and hostname of the MNH group leader to connect to */
|
||||||
public KaZaClient(String userName, int kbps,
|
public KaZaClient(String userName, int kbps,
|
||||||
String sharedFolder, String server)
|
String sharedFolder, String server)
|
||||||
{
|
{
|
||||||
@ -59,6 +75,7 @@ public class KaZaClient
|
|||||||
m_clientDownloaders = new HashMap<Integer, ClientDownloader>();
|
m_clientDownloaders = new HashMap<Integer, ClientDownloader>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* check if a given file download is still active */
|
||||||
public boolean isDownloadActive(int index)
|
public boolean isDownloadActive(int index)
|
||||||
{
|
{
|
||||||
synchronized (m_clientDownloaders)
|
synchronized (m_clientDownloaders)
|
||||||
@ -67,8 +84,10 @@ public class KaZaClient
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* check if the client is connected */
|
||||||
public boolean connected() { return m_connected; }
|
public boolean connected() { return m_connected; }
|
||||||
|
|
||||||
|
/* close the client, sends QUIT message to MNH server */
|
||||||
public void close()
|
public void close()
|
||||||
{
|
{
|
||||||
if (m_connected)
|
if (m_connected)
|
||||||
@ -82,6 +101,8 @@ public class KaZaClient
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* this method is called when the user wants the client
|
||||||
|
* to send a search message to its MNH group leader */
|
||||||
public Vector<SearchResult> performSearch(String query)
|
public Vector<SearchResult> performSearch(String query)
|
||||||
{
|
{
|
||||||
Vector<SearchResult> results = new Vector<SearchResult>();
|
Vector<SearchResult> results = new Vector<SearchResult>();
|
||||||
@ -145,6 +166,8 @@ public class KaZaClient
|
|||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* SearchResult stores data fields describing a "hit" that is returned
|
||||||
|
* by the MNH group leader */
|
||||||
public class SearchResult
|
public class SearchResult
|
||||||
{
|
{
|
||||||
String peerAddress = "";
|
String peerAddress = "";
|
||||||
@ -172,6 +195,8 @@ public class KaZaClient
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* called by the user instructing the KaZaClient to begin
|
||||||
|
* downloading a file from a peer user */
|
||||||
public int downloadFile(String host, String fileName)
|
public int downloadFile(String host, String fileName)
|
||||||
{
|
{
|
||||||
ClientDownloader cd = new ClientDownloader(host, fileName);
|
ClientDownloader cd = new ClientDownloader(host, fileName);
|
||||||
@ -184,11 +209,15 @@ public class KaZaClient
|
|||||||
return cd.getIndex();
|
return cd.getIndex();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* this method returns a unique index for a given file download */
|
||||||
public synchronized int getTransferIndex()
|
public synchronized int getTransferIndex()
|
||||||
{
|
{
|
||||||
return m_transferIndex++;
|
return m_transferIndex++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* this class implements a threaded file downloader so that a
|
||||||
|
* file download can occur at the same time that the user is
|
||||||
|
* searching for other files or downloading other files */
|
||||||
public class ClientDownloader implements Runnable
|
public class ClientDownloader implements Runnable
|
||||||
{
|
{
|
||||||
private String m_host;
|
private String m_host;
|
||||||
|
@ -1,9 +1,17 @@
|
|||||||
|
|
||||||
|
/* Author: Josh Holtrop
|
||||||
|
* GVSU, CS654, Project 1
|
||||||
|
* Date: 2008-03-11
|
||||||
|
*/
|
||||||
|
|
||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
import java.awt.event.*;
|
import java.awt.event.*;
|
||||||
import javax.swing.*;
|
import javax.swing.*;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
|
/* KaZaGUI provides a tabbed interface for launching a server,
|
||||||
|
* connecting to a server, and search for files on a server
|
||||||
|
*/
|
||||||
public class KaZaGUI extends JFrame
|
public class KaZaGUI extends JFrame
|
||||||
{
|
{
|
||||||
private ActionEventHandler m_handler;
|
private ActionEventHandler m_handler;
|
||||||
@ -38,6 +46,7 @@ public class KaZaGUI extends JFrame
|
|||||||
private JButton m_serverPeerConnectButton;
|
private JButton m_serverPeerConnectButton;
|
||||||
private JLabel m_serverPeerGroupLeadersLabel;
|
private JLabel m_serverPeerGroupLeadersLabel;
|
||||||
|
|
||||||
|
/* construct the GUI and initialize parameters */
|
||||||
public KaZaGUI()
|
public KaZaGUI()
|
||||||
{
|
{
|
||||||
super("Josh's KaZa application for CS654!");
|
super("Josh's KaZa application for CS654!");
|
||||||
@ -64,6 +73,9 @@ public class KaZaGUI extends JFrame
|
|||||||
m_timer.start();
|
m_timer.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* a class that receives messages when GUI events such as buttons
|
||||||
|
* being pressed occur
|
||||||
|
*/
|
||||||
private class ActionEventHandler implements ActionListener
|
private class ActionEventHandler implements ActionListener
|
||||||
{
|
{
|
||||||
private KaZaGUI m_kg;
|
private KaZaGUI m_kg;
|
||||||
@ -77,6 +89,7 @@ public class KaZaGUI extends JFrame
|
|||||||
{
|
{
|
||||||
if (e.getSource() == m_browseButton)
|
if (e.getSource() == m_browseButton)
|
||||||
{
|
{
|
||||||
|
/* show a directory selection dialog box */
|
||||||
JFileChooser fc = new JFileChooser();
|
JFileChooser fc = new JFileChooser();
|
||||||
fc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
|
fc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
|
||||||
fc.showOpenDialog(m_kg);
|
fc.showOpenDialog(m_kg);
|
||||||
@ -84,10 +97,14 @@ public class KaZaGUI extends JFrame
|
|||||||
}
|
}
|
||||||
else if (e.getSource() == m_closeButton)
|
else if (e.getSource() == m_closeButton)
|
||||||
{
|
{
|
||||||
|
/* exit the application */
|
||||||
|
if (m_client != null)
|
||||||
|
m_client.close();
|
||||||
System.exit(0);
|
System.exit(0);
|
||||||
}
|
}
|
||||||
else if (e.getSource() == m_connectButton)
|
else if (e.getSource() == m_connectButton)
|
||||||
{
|
{
|
||||||
|
/* client wants to connect to a MNH server */
|
||||||
ConnectionSpeed cs = (ConnectionSpeed) m_speedCombo.getSelectedItem();
|
ConnectionSpeed cs = (ConnectionSpeed) m_speedCombo.getSelectedItem();
|
||||||
m_client = new KaZaClient(m_userNameField.getText(),
|
m_client = new KaZaClient(m_userNameField.getText(),
|
||||||
cs.getKbps(),
|
cs.getKbps(),
|
||||||
@ -108,6 +125,7 @@ public class KaZaGUI extends JFrame
|
|||||||
}
|
}
|
||||||
else if (e.getSource() == m_serverStartButton)
|
else if (e.getSource() == m_serverStartButton)
|
||||||
{
|
{
|
||||||
|
/* start MNH server */
|
||||||
if (m_server == null)
|
if (m_server == null)
|
||||||
{
|
{
|
||||||
m_server = new KaZaServer();
|
m_server = new KaZaServer();
|
||||||
@ -129,6 +147,7 @@ public class KaZaGUI extends JFrame
|
|||||||
{
|
{
|
||||||
if (m_server != null)
|
if (m_server != null)
|
||||||
{
|
{
|
||||||
|
/* update server status messages */
|
||||||
Object[] clients = m_server.getClientList();
|
Object[] clients = m_server.getClientList();
|
||||||
String caption = "Clients (" + clients.length + "): ";
|
String caption = "Clients (" + clients.length + "): ";
|
||||||
boolean first = true;
|
boolean first = true;
|
||||||
@ -156,6 +175,7 @@ public class KaZaGUI extends JFrame
|
|||||||
m_serverPeerGroupLeadersLabel.setText(caption);
|
m_serverPeerGroupLeadersLabel.setText(caption);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* print transfer status messages to the Transfers panel */
|
||||||
synchronized (m_activeDownloads)
|
synchronized (m_activeDownloads)
|
||||||
{
|
{
|
||||||
Set<Integer> indices = m_activeDownloads.keySet();
|
Set<Integer> indices = m_activeDownloads.keySet();
|
||||||
@ -176,6 +196,8 @@ public class KaZaGUI extends JFrame
|
|||||||
}
|
}
|
||||||
else if (e.getSource() == m_serverPeerConnectButton)
|
else if (e.getSource() == m_serverPeerConnectButton)
|
||||||
{
|
{
|
||||||
|
/* instruct the MNH server (group leader) to connect to
|
||||||
|
* a peer group leader */
|
||||||
if (m_server != null)
|
if (m_server != null)
|
||||||
{
|
{
|
||||||
m_server.connectToPeerGroupLeader(
|
m_server.connectToPeerGroupLeader(
|
||||||
@ -187,6 +209,7 @@ public class KaZaGUI extends JFrame
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* client has initiated a keyword search */
|
||||||
private void performSearch(String query)
|
private void performSearch(String query)
|
||||||
{
|
{
|
||||||
Vector<KaZaClient.SearchResult> results =
|
Vector<KaZaClient.SearchResult> results =
|
||||||
@ -232,6 +255,8 @@ public class KaZaGUI extends JFrame
|
|||||||
repaint();
|
repaint();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* simple class to store a connection speed
|
||||||
|
* in kbps with a string caption */
|
||||||
private class ConnectionSpeed
|
private class ConnectionSpeed
|
||||||
{
|
{
|
||||||
private String m_caption;
|
private String m_caption;
|
||||||
@ -248,6 +273,7 @@ public class KaZaGUI extends JFrame
|
|||||||
public int getKbps() { return m_kbps; }
|
public int getKbps() { return m_kbps; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* construct the panel for the client tab of the GUI */
|
||||||
private JPanel getClientPanel()
|
private JPanel getClientPanel()
|
||||||
{
|
{
|
||||||
m_shareFolderField = new JTextField();
|
m_shareFolderField = new JTextField();
|
||||||
@ -351,6 +377,7 @@ public class KaZaGUI extends JFrame
|
|||||||
return clientPanel;
|
return clientPanel;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* construct the GUI elements for the server tab of the GUI */
|
||||||
private JPanel getServerPanel()
|
private JPanel getServerPanel()
|
||||||
{
|
{
|
||||||
m_serverStatusLabel = new JLabel();
|
m_serverStatusLabel = new JLabel();
|
||||||
|
@ -1,8 +1,20 @@
|
|||||||
|
|
||||||
|
/* Author: Josh Holtrop
|
||||||
|
* GVSU, CS654, Project 1
|
||||||
|
* Date: 2008-03-11
|
||||||
|
*/
|
||||||
|
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
import java.net.*;
|
import java.net.*;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
|
/* KaZaServer implements a "Mini Napster Hub" group leader peer
|
||||||
|
* for the KaZa file sharing system. The listening server runs
|
||||||
|
* as a thread, and each incoming connection to it is also handled
|
||||||
|
* by a thread so that multple clients can be connected and upload
|
||||||
|
* their file list and descriptions as well as search for files
|
||||||
|
* simultaneously.
|
||||||
|
*/
|
||||||
public class KaZaServer implements Runnable
|
public class KaZaServer implements Runnable
|
||||||
{
|
{
|
||||||
public static final int LISTEN_PORT = 3442;
|
public static final int LISTEN_PORT = 3442;
|
||||||
@ -11,6 +23,7 @@ public class KaZaServer implements Runnable
|
|||||||
private Vector<Socket> m_peerGroupLeaders;
|
private Vector<Socket> m_peerGroupLeaders;
|
||||||
private HashMap<String, Integer> m_currentSearches;
|
private HashMap<String, Integer> m_currentSearches;
|
||||||
|
|
||||||
|
/* create a KaZaServer */
|
||||||
public KaZaServer()
|
public KaZaServer()
|
||||||
{
|
{
|
||||||
m_clientData = new HashMap<String, ClientInfo>();
|
m_clientData = new HashMap<String, ClientInfo>();
|
||||||
@ -18,6 +31,7 @@ public class KaZaServer implements Runnable
|
|||||||
m_currentSearches = new HashMap<String, Integer>();
|
m_currentSearches = new HashMap<String, Integer>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* begin listening for incoming connections */
|
||||||
public void run()
|
public void run()
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
@ -38,6 +52,10 @@ public class KaZaServer implements Runnable
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* the MNH server administrator invokes this method to instruct
|
||||||
|
* the server to connect to a peer group leader. This peer group
|
||||||
|
* leader is then used to forward searches to aggregate search
|
||||||
|
* results for peers connected to linked-to group leaders */
|
||||||
public void connectToPeerGroupLeader(String peerName,
|
public void connectToPeerGroupLeader(String peerName,
|
||||||
boolean sendReverseConnectMsg)
|
boolean sendReverseConnectMsg)
|
||||||
{
|
{
|
||||||
@ -76,6 +94,7 @@ public class KaZaServer implements Runnable
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* return a list of the currently connected clients */
|
||||||
public Object[] getClientList()
|
public Object[] getClientList()
|
||||||
{
|
{
|
||||||
Set<String> s;
|
Set<String> s;
|
||||||
@ -86,6 +105,7 @@ public class KaZaServer implements Runnable
|
|||||||
return s.toArray();
|
return s.toArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* return a list of the linked-to peer group leaders */
|
||||||
public Object[] getPeerGroupLeaderList()
|
public Object[] getPeerGroupLeaderList()
|
||||||
{
|
{
|
||||||
Vector<String> peers = new Vector<String>();
|
Vector<String> peers = new Vector<String>();
|
||||||
@ -99,6 +119,7 @@ public class KaZaServer implements Runnable
|
|||||||
return peers.toArray();
|
return peers.toArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* simple class to store information about a connected KaZaClient */
|
||||||
private class ClientInfo
|
private class ClientInfo
|
||||||
{
|
{
|
||||||
String userName = "Anonymous";
|
String userName = "Anonymous";
|
||||||
@ -106,6 +127,8 @@ public class KaZaServer implements Runnable
|
|||||||
HashMap<String, String> files = new HashMap<String, String>();
|
HashMap<String, String> files = new HashMap<String, String>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* this class can be run in a thread and handles communication
|
||||||
|
* with a single client */
|
||||||
private class ClientHandler implements Runnable
|
private class ClientHandler implements Runnable
|
||||||
{
|
{
|
||||||
private Socket m_socket;
|
private Socket m_socket;
|
||||||
@ -227,13 +250,15 @@ public class KaZaServer implements Runnable
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* this method is called when a client is asking our server to
|
||||||
|
* perform a keyword search on its file database */
|
||||||
private String performSearch(int depth, String query, Socket clientSocket)
|
private String performSearch(int depth, String query, Socket clientSocket)
|
||||||
{
|
{
|
||||||
String results = "";
|
String results = "";
|
||||||
String querylc = query.toLowerCase();
|
String querylc = query.toLowerCase();
|
||||||
|
|
||||||
/* don't perform a search that we are already performing
|
/* don't perform a search that we are already performing
|
||||||
* (avoid duplicate results */
|
* (avoid duplicate results) */
|
||||||
synchronized (m_currentSearches)
|
synchronized (m_currentSearches)
|
||||||
{
|
{
|
||||||
if (m_currentSearches.containsKey(querylc))
|
if (m_currentSearches.containsKey(querylc))
|
||||||
@ -241,6 +266,8 @@ public class KaZaServer implements Runnable
|
|||||||
m_currentSearches.put(querylc, 1);
|
m_currentSearches.put(querylc, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* if the depth > 0, then we can forward this search to our
|
||||||
|
* peer group leaders to aggregate their results with ours */
|
||||||
if (depth > 0)
|
if (depth > 0)
|
||||||
{
|
{
|
||||||
synchronized (m_peerGroupLeaders)
|
synchronized (m_peerGroupLeaders)
|
||||||
@ -306,6 +333,7 @@ public class KaZaServer implements Runnable
|
|||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* helper method invoked to forward keyword search to peer group leader */
|
||||||
private String getSearchResultsFromPeerGroupLeader(Socket s, int depth,
|
private String getSearchResultsFromPeerGroupLeader(Socket s, int depth,
|
||||||
String query)
|
String query)
|
||||||
{
|
{
|
||||||
|
Loading…
x
Reference in New Issue
Block a user