commented classes and functions

git-svn-id: svn://anubis/gvsu@65 45c1a28c-8058-47b2-ae61-ca45b979098e
This commit is contained in:
josh 2008-03-09 23:41:34 +00:00
parent 111b16aecd
commit 32633264d5
5 changed files with 103 additions and 1 deletions

View File

@ -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;

View File

@ -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[])

View File

@ -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;

View File

@ -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();

View File

@ -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)
{ {