简体   繁体   English

Java套接字请求处理

[英]Java Socket request handling

I'm attempting to write a simple file transfer program using the Java Socket and ServerSocket libraries. 我正在尝试使用Java SocketServerSocket库编写一个简单的文件传输程序。 I've used these libraries successfully once before, but in this case I seem to have a problem getting the server side to slow down long enough once the connection is made in order for the client side to make a request. 我以前曾经成功使用过这些库,但是在这种情况下,一旦建立连接以使客户端发出请求,服务器端就必须放慢足够长的时间,我似乎遇到了问题。 The problem appears to be happening as the main method on the server side enters the second while loop, calls handleRequest() , and once in handleRequest() , throws a SocketExeption error when it tries to read in the client's request. 由于服务器端的主要方法进入第二个while循环,调用handleRequest() ,并且一旦进入handleRequest() ,尝试读取客户端的请求时将引发SocketExeption错误,从而出现问题。 The program does not pause long enough to allow the user on the client side to send a request. 该程序的暂停时间不足以允许客户端的用户发送请求。 I've tried moving code around within the main's second while loop to no avail. 我尝试在主程序的第二个while循环内移动代码,但无济于事。 Any help in getting the server side to slow down and listen would be greatly appreciated. 我们将不胜感激服务器方面的任何帮助。 Thanks! 谢谢!

Edit: Here's the exceptions thrown: 编辑:这是抛出的异常:

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)

End Edit 结束编辑

Here's my code: 这是我的代码:

Server side 服务器端

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!");
    }
}

Client side 客户端

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

        }

    }

}

You are trying to create a serversocket everytime. 您正在尝试每次创建一个serverocket。

What you should be doing is on start up create a thread to handle socket acceptances. 您应该做的是在启动时创建一个线程来处理套接字接收。 The thread that handles acceptances should then hand off any client to another thread. 然后,处理接受的线程应将任何客户端移交给另一个线程。

something like 就像是

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 just creates threads to handle the incoming connection SocketHandler只是创建线程来处理传入的连接

public class SocketHandler{

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

}

client side 客户端

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

  }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM