0

我正在尝试使用Java SocketServerSocket库编写一个简单的文件传输程序。我以前曾经成功地使用过这些库,但在这种情况下,一旦建立连接以便客户端发出请求,我似乎很难让服务器端放慢足够长的时间。问题似乎正在发生,因为服务器端的 main 方法进入第二个 while 循环,调用handleRequest(),并且一旦进入handleRequest(),抛出一个SocketExeption尝试读取客户端请求时出错。程序没有暂停足够长的时间以允许客户端的用户发送请求。我尝试在 main 的第二个 while 循环中移动代码,但无济于事。任何有助于让服务器端放慢速度并收听的帮助将不胜感激。谢谢!

编辑: 这是抛出的异常:

Exception in thread "main" java.net.SocketException: Connection reset
    at java.net.SocketInputStream.read(Unknown Source)
    at java.net.SocketInputStream.read(Unknown Source)
    at sun.nio.cs.StreamDecoder.readBytes(Unknown Source)
    at sun.nio.cs.StreamDecoder.implRead(Unknown Source)
    at sun.nio.cs.StreamDecoder.read(Unknown Source)
    at java.io.InputStreamReader.read(Unknown Source)
    at java.io.BufferedReader.fill(Unknown Source)
    at java.io.BufferedReader.readLine(Unknown Source)
    at java.io.BufferedReader.readLine(Unknown Source)
    at FTServe.handleRequest(FTServe.java:92)
    at FTServe.main(FTServe.java:218)

结束编辑

这是我的代码:

服务器端

import java.net.*;
import java.io.*;


public class FTServe {
    BufferedReader stdIn;
    static BufferedReader in = null;
    static PrintWriter out = null;
    static ServerSocket serverSocket;

    FTServe() {
    }

    /**********************************************************
     * Desc: starts on host A, validates the parameter, and waits on port 
     * 30021 for client request
     * Parameters:
     * Returns:
     * @param portNum 
     **********************************************************
     */
    private Socket startUp(int portNum) throws IOException {
        serverSocket = null;
        Socket clientSocket = null;

        //server to listen on port 30021
        //ftserve starts on host A, and validates the command-line parameters.

        try {
            serverSocket = new ServerSocket(portNum);
            System.out.println("Waiting for client....");
        } catch (IOException e) {
            System.err.println("Could not listen on port: " + portNum);
            System.exit(1);
        }

        //waits for client message and accepts connection (client IP address and port)
        try {
            clientSocket = serverSocket.accept();
        } catch (IOException e) {
            System.err.println("Accept failed.");
            System.exit(1);
        }
        return clientSocket;
    }

    /**********************************************************
     * Desc: accepts, interprets and handles client requests
     * Parameters:
     * Returns:
     * @param server 
     * @param server 
     * @throws IOException 
     **********************************************************
     */
    public static void handleRequest(FTServe server) throws IOException {

        Socket dataSocket = null;
        String message = in.readLine();
        if (message != null) {
            if (message.equalsIgnoreCase("list")) {
                int portNum = 30020;
                dataSocket = server.startUp(portNum);
                sendDirectory();
            }
            else if (message.contains("get <")) {
                int j = 0;
                String requestedFile = null;
                char letter;
                String prefix = "get <";
                requestedFile = message.substring(message.indexOf(prefix + prefix.length(), message.length()-2));
                //open port 30020 to send data to client
                dataSocket = server.startUp(30020);
                sendFile(dataSocket, requestedFile);    
            }
            else {
                out.println("Invalid command. Please enter 'list' or 'get <filename>:  ");
            }

            dataSocket.close();
        }
    }

    /**********************************************************
     * Desc: sends list of files in directory to client
     * Parameter: String requestedFile, Socket dataSocket
     * Returns: 
     * @param dataSocket 
     * @param requestedFile 
     * @throws IOException 
     **********************************************************
     */
    private static void sendDirectory() {
        String path = new File(".").getAbsolutePath();
        File dir = new File(path);
        File[] listFiles = dir.listFiles();

        for (int i = 0; i < listFiles.length; i++) {
            if (listFiles[i].isFile()) {
                String fileName = listFiles[i].getName();
                out.print(fileName + "     ");
            }
        }
    }

    /**********************************************************
     * Desc: sends file to client on port 30020
     * Parameter: String requestedFile, Socket dataSocket
     * Returns: 
     * @param dataSocket 
     * @param requestedFile 
     * @throws IOException 
     **********************************************************
     */
    private static void sendFile(Socket dataSocket, String requestedFile) throws IOException {
        File sendFile = new File(requestedFile);
        if (sendFile.isFile()){
            byte[] fileByteArray = new byte[(int) requestedFile.length()];

            FileInputStream fis = new FileInputStream(requestedFile);
            BufferedInputStream bis = new BufferedInputStream(fis);

            DataInputStream dis = new DataInputStream(bis);
            dis.readFully(fileByteArray, 0, fileByteArray.length);

            //opens output stream and sends file info and file to the client
            OutputStream os = dataSocket.getOutputStream(); 
            DataOutputStream dos = new DataOutputStream(os);
            dos.writeUTF(sendFile.getName());           
            dos.writeLong(fileByteArray.length);
            dos.write(fileByteArray, 0, fileByteArray.length);
            dos.flush();
        }
        else out.println("That is not a valid filename.");
    }

    /***********************************************************
     * Desc: closes server socket
     * Parameter: serverSocket
     **********************************************************
     */
    private void closeSocket(ServerSocket serverSocket) throws IOException {
        serverSocket.close();
    }

    /***********************************************************
     * Desc: Main method
     **********************************************************
     */
    public static void main(String[] args) throws IOException {
        int goodbye = 0; //if goodbye == 1, close client connection; if goodbye == -1, close server socket

        while (goodbye != -1) {
            goodbye = 0;
            FTServe server = new FTServe();
            Socket socket = null;
            int portNum = 30021;

            socket = server.startUp(portNum);

            String message;

            System.out.println("When you wish to disconnect from client, simply enter 'bye'. \nTo close socket, enter 'exit'.");
            BufferedReader stdIn = new BufferedReader(new InputStreamReader(System.in)); 

            System.out.println("Connection from " + socket.getLocalAddress().getHostName() + " successful.  \n\nWaiting on client...");

            //gets inputs and outputs from client
            out = new PrintWriter(socket.getOutputStream(), true);
            in = new BufferedReader(new InputStreamReader(socket.getInputStream()));

            while (goodbye == 0) {

                server.handleRequest(server);

                //close connection to client if goodbye == 1 because server entered bye
                if (goodbye == 1) {
                    System.out.println("Connection to client closing...");
                    out.println("Connection to client closing...Goodbye");
                    in.close();
                    out.close();
                    socket.close();
                    server.closeSocket(serverSocket);
                }
            }

            //server.startUp();
            System.out.println("Enter 'exit' to close, else enter 'go' to continue listening for client. When server is listening, Ctrl-C will end program");
            System.out.print("Server> ");
            if (stdIn.readLine().equals("exit")) {
                server.closeSocket(serverSocket); 
                goodbye = -1;
            }
        }

        System.out.println("The program is closing. Goodbye!");
    }
}

客户端

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.net.UnknownHostException;


public class FTClient {

    static BufferedReader stdIn = new BufferedReader(new InputStreamReader(System.in));
    static PrintWriter out = null;
    static BufferedReader in = null;
    FTClient() {
    }

    /**********************************************************
     * Desc: initiates contact with server
     * Parameter: iPadd == server IP address, portNum == server port
     * Returns: Client socket
     **********************************************************
     */
    private Socket initiateContact (String iPadd, int portNum) throws IOException {
        Socket clientSocket = null;
        //ftclient starts on host B, and validates the command-line parameters.
        try {
            //create connection between client and server           
            clientSocket = new Socket(iPadd, portNum);
        } catch (UnknownHostException e) {
            System.err.println("Don't know about host: " + iPadd + ".");
            System.exit(1);
        } catch (IOException e) {
            System.err.println("Couldn't get I/O for the connection to: " + iPadd + ".");             
            System.exit(1);
        } 
        return clientSocket;
    }

    /**********************************************************
     *Desc: sends client message to server
     *Parameter: String msg
     *Returns: Boolean true if client message == bye, else false
     **********************************************************
     */
    private boolean sendMessage(String fromUser) throws IOException {   

        if (fromUser.equals("bye")) {
            out.println("Client> " + fromUser);
            return true;
        }
        else if (fromUser != null) out.println("Client> " + fromUser);
        return false;
    }


    /**********************************************************
     * Desc: sends client command: 'list or get <filename>'
     * Parameters:
     * Returns:
     * @param request 
     * @return 
     * @throws IOException 
     **********************************************************
     */
    private boolean makeRequest(String request) throws IOException {
        //ftclient sends a command (list  or get <filename>) on connection to port 30020.
        if (request.equals("bye")) {
            out.println(request);
            return true;
        }
        else if (request != null) out.println(request);
        return false;
    }

    /**********************************************************
     * Desc: saves the file in the current default directory (handling "duplicate file name" error if necessary), 
     * and displays a "transfer complete" message on-screen or sends an appropriate error message 
     * (“File not found”, etc.) to ftclient on connection P, and ftclient displays the message on-screen.
     * Parameters:
     * Returns:
     * @return 
     * @throws IOException 
     **********************************************************
     */
    private void receiveFile()
    {
        //code remains to be written
    }

    /**
     * @param args
     * @throws IOException 
     */
    public static void main(String[] args) throws IOException {
        FTClient client = new FTClient();
        boolean goodbye = false;
        Socket socket, datasocket;
        String iPadd = args[0];
        String port = args[1];
        int portNum = Integer.parseInt(port);

        //initate contact with server
        socket = client.initiateContact(iPadd, portNum);

        System.out.println("When you wish to exit, simply enter 'bye'.");

        out = new PrintWriter(socket.getOutputStream(), true);
        in = new BufferedReader(new InputStreamReader(socket.getInputStream()));

        //client sends request, then initiates contact with data socket to receive data
        while (!goodbye) {
            System.out.println("Server> Enter 'list' to display a directory of files. \nEnter 'get <filename>' to retrieve a file.  " +
                    "\nPlease enter a command: ");
            String request = stdIn.readLine();
            goodbye = client.makeRequest(request);
            int dataPort = 30020;
            Socket dataSocket = client.initiateContact(iPadd, dataPort);
            client.receiveFile();

        }

    }

}
4

1 回答 1

0

您每次都尝试创建一个服务器套接字。

您应该做的是在启动时创建一个线程来处理套接字接受。然后,处理接受的线程应将任何客户端移交给另一个线程。

就像是

public ServerSocketProcessor implements Runnable{

    private boolean execute;
    private int commandPortNumber;
    private int dataPortNumber;

    public ServerSocketProcessor(int commandPortNumber, int dataPortNumber, SocketHandler socketHandler){
        this.commandPortNumber= commandPortNumber;
        this.dataPortNumber= dataPortNumber;
        this.socketHandler = socketHandler;
    }

    public void run(){
        this.execute = true;
        try{
           // only ever want one server socket and keep it running for lifetime
           // of your program
           ServerSocket commandServerSocket = new ServerSocket(this.commandPortNumber);
           ServerSocket dataServerSocket = new ServerSocket(this.dataPortNumber);
           try {
               // keep running until another process says to stop
               while(this.execute){
                   // accept will cause the server socket to wait until
                   // a connection is made
                   Socket commandSocket = commandServerSocket .accept();
                   // handle new connection then go back to waiting for a new
                   // connection.
                   Socket dataSocket = dataServerSocket.accept();
                   socketHandler.handle(commandSocket, dataSocket);
               }
           } finally{
               serverSocket.close();
           }
        } catch (exception e){
            // do something
        }
    }

}

SocketHandler 只是创建线程来处理传入的连接

public class SocketHandler{

    public void handle(Socket commandSocket, Socket dataSocket){
         // create thread to handle socket
    }

}

客户端

public static void main(String[] args) throws IOException {
    FTClient client = new FTClient();
    boolean goodbye = false;
    Socket socket, datasocket;
    String iPadd = "127.0.0.1";
    String port = "30021";
    int portNum = Integer.parseInt(port);

    //initate contact with server
    socket = client.initiateContact(iPadd, portNum);

    System.out.println("When you wish to exit, simply enter 'bye'.");

    out = new PrintWriter(socket.getOutputStream(), true);
    in = new BufferedReader(new InputStreamReader(socket.getInputStream()));

    //client sends request, then initiates contact with data socket to receive data
    while (!goodbye) {
      System.out.println("Server> Enter 'list' to display a directory of files. \nEnter 'get <filename>' to retrieve a file.  " +
              "\nPlease enter a command: ");
      String request = stdIn.readLine();
      goodbye = client.makeRequest(request);
    }
    client.cleanUp(); // in this you should close any datastreams and close the socket

  }
于 2013-06-09T23:03:27.613 回答