Сетевое приложение Java Peer-to-Peer — домашнее задание

Я создаю приложение p2p на Java для обмена файлами. Каждый одноранговый узел будет работать на моей машине на другом порту и прослушивать запрос. но проблема, с которой я сталкиваюсь, заключается в том, что когда создается экземпляр PeerNode, мой код переходит в бесконечный цикл. Ниже приведен мой код для PeerNode. Это то, как я должен создавать каждый узел и заставлять их прослушивать входящие запросы?

Следующий код представляет один одноранговый узел:

public class PeerNode
{
    private int port;
    private ArrayList<PeerNode> contacts;
    PeerNode preNode;
    PeerNode postNode;
    private String directoryLocation = "";

    PeerNode(int port)
    {
        this.port = port;
        this.setDirectoryLocation( port+"");
        startClientServer( port );
    }

    private void sendRequest(String fileName, String host, int port) throws UnknownHostException, IOException
    {
        Socket socket = new Socket(host, port);//machine name, port number
        PrintWriter out = new PrintWriter( socket.getOutputStream(), true );
        out.println(fileName);

        out.close();
        socket.close();

    }

    private void startClientServer( int portNum )
    {
        try 
        {
            // Establish the listen socket.
            ServerSocket server = new ServerSocket( 0 );
            System.out.println("listening on port " + server.getLocalPort());

            while( true )
            {
                // Listen for a TCP connection request.
                Socket connection = server.accept();

                // Construct an object to process the HTTP request message.
                HttpRequestHandler request = new HttpRequestHandler( connection );

                // Create a new thread to process the request.
                Thread thread = new Thread(request);

                // Start the thread.
                thread.start();

                System.out.println("Thread started for "+ portNum);
            }

        } 
        catch (Exception e) 
        {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

    }
}

И следующий класс создает все узлы и соединяет их:

public class MasterClientServer 
{
    public static void main( String [] args )
    {
        int count = 10;
        ArrayList<PeerNode> arrayOfNodes = createNodes( count );
    }

    public static ArrayList<PeerNode> createNodes( int count)
    {
        System.out.println("Creating a network of "+ count + " nodes...");
        ArrayList< PeerNode > arrayOfNodes = new ArrayList<PeerNode>();

        for( int i =1 ; i<=count; i++)
        {
            arrayOfNodes.add( new PeerNode( 0 ) ); //providing 0, will take any free node
        }
        return arrayOfNodes;
    }
}



public class HttpRequestHandler implements Runnable 
{
    final static String CRLF = "\r\n";
    Socket socket;

    public HttpRequestHandler(Socket socket) throws Exception 
    {
        this.socket = socket;
    }

    @Override
    public void run() 
    {
        try 
        {
            processRequest();
        } 
        catch (Exception e) 
        {
            System.out.println(e);
        }

    }   

    /*
     * Gets a request from another node. 
     * Sends the file to the node if available.
     */
    private void processRequest() throws Exception 
    {
        /*DataOutputStream os = new DataOutputStream(socket.getOutputStream());

        InputStream is = socket.getInputStream();
        BufferedReader br = new BufferedReader(new InputStreamReader(is));

        // Get the request line of the HTTP request message.
        String requestLine = br.readLine();

        // Extract the filename from the request line.
        // In Get request, the second token is the fie name
        String[] tokens = requestLine.split(" ");
        String fileName = tokens[1];

        // Prepend a "." so that file request is within the current directory.
        fileName = "." + fileName;

        // Open the requested file.
        FileInputStream fis = null;
        boolean fileExists = true;

        try 
        {
            fis = new FileInputStream(fileName);
        } 
        catch (FileNotFoundException e) 
        {
            fileExists = false;
        }

        // construct the response Message
        // Construct the response message.
        String statusLine = null;
        String contentTypeLine = null;
        String entityBody = null;
        if (fileExists) 
        {
            statusLine = "HTTP/1.1 200 OK" + CRLF;
            contentTypeLine = "Content-Type: " + contentType(fileName) + CRLF;
        } 
        else 
        {
            statusLine = "HTTP/1.1 404 Not Found" + CRLF;
            contentTypeLine = "Content-Type: text/html" + CRLF;
            entityBody = "<HTML><HEAD><TITLE>404 Not Found</TITLE></HEAD><BODY>Error 404: Page Not Found</BODY></HTML>";
        }

        // Send the status line.
        os.writeBytes(statusLine);

        // Send the content type line.
        os.writeBytes(contentTypeLine);

        // Send a blank line to indicate the end of the header lines.
        os.writeBytes(CRLF);

        // Send the entity body.
        if (fileExists) {
            sendBytes(fis, os);
            fis.close();
        } else {
            os.writeBytes(entityBody);
        }
        // Close streams and socket.
        os.close();
        br.close();
        socket.close();

    }

    private static void sendBytes(FileInputStream fis, OutputStream os)
            throws Exception 
            {
        // Construct a 1K buffer to hold bytes on their way to the socket.
        byte[] buffer = new byte[1024];
        int bytes = 0;

        // Copy requested file into the socket's output stream.
        while ((bytes = fis.read(buffer)) != -1) {
            os.write(buffer, 0, bytes);
        }*/
    }

    private static String contentType(String fileName) 
    {
        if (fileName.endsWith(".htm") || fileName.endsWith(".html")) 
        {
            return "text/html";
        }
        if (fileName.endsWith(".jpg") || fileName.endsWith(".jpeg")) 
        {
            return "image/jpeg";
        }
        if (fileName.endsWith(".gif")) {
            return "image/gif";
        }
        if (fileName.endsWith(".ram") || fileName.endsWith(".ra")) 
        {
            return "audio/x-pn-realaudio";
        }
        return "application/octet-stream";
    }
 }

person user1998719    schedule 19.03.2013    source источник
comment
Пожалуйста, уточните бесконечный цикл. Где в коде зацикливается программный счетчик?   -  person uldall    schedule 20.03.2013
comment
он входит внутрь функции StartClientServer и входит в цикл while(), оттуда не выходит. и создается только один PeerNode. Когда я создаю PeerNode, должен ли я помещать прослушивание кода TCP-соединения и thread.start..etc в цикл while, чтобы он мог прослушивать больше запросов?   -  person user1998719    schedule 20.03.2013


Ответы (1)


Ваш конструктор PeerNode никогда не возвращается, поскольку он занят приемом новых подключений. Следовательно, ваш цикл в createNodes создает только первый экземпляр PeerNode. Вы можете решить эту проблему, вызвав startClientServer в новом потоке:

new Thread(new Runnable() {
   public void run() {
       startClientServer( port );
   }
}.start();
person uldall    schedule 19.03.2013
comment
Хорошо. Так что я должен поместить это в конструктор для PeerNode? Итак, я создаю новый поток, который запустит ClientServer на порту, и внутри функции startClientServer я снова создаю новый поток для обработки запроса. Я немного запутался... почему я создаю потоки внутри конструктора? - person user1998719; 20.03.2013
comment
Да, вы можете либо запустить поток для обработки accept() внутри конструктора, либо внутри самого метода startClientServer. В вашем случае вам нужен один поток для приема новых соединений через accept() и один поток для обработки связи при каждом новом соединении. Строго говоря, вам не нужен новый поток для каждого соединения, но если вы этого не сделаете, вы можете обрабатывать только одно соединение за раз. - person uldall; 20.03.2013