向java服务器发送请求

向java服务器发送请求,java,Java,我为服务器和客户机编写了一些代码,将文件从服务器传输到客户机,这就像一个符咒;然而,我有几个问题。我想在GUI下构建这段代码,我想列出文件夹中的所有文件,但是在看到提供的文件列表后,如何让客户机选择他想要的文件(如何向服务器发送字符串以选择文件) 服务器代码 import java.io.*; import java.net.*; class TCPServer { public static void listfile(){ File folder = new Fil

我为服务器和客户机编写了一些代码,将文件从服务器传输到客户机,这就像一个符咒;然而,我有几个问题。我想在GUI下构建这段代码,我想列出文件夹中的所有文件,但是在看到提供的文件列表后,如何让客户机选择他想要的文件(如何向服务器发送字符串以选择文件)

服务器代码

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



class TCPServer {

    public static void listfile(){

    File folder = new File("c:/");
    File[] listOfFiles = folder.listFiles();

    for (int i = 0; i < listOfFiles.length; i++) {
      if (listOfFiles[i].isFile()) {
        System.out.println("File " + listOfFiles[i].getName());
      } else if (listOfFiles[i].isDirectory()) {
        System.out.println("Directory " + listOfFiles[i].getName());
      }
    }
  }


    public static void main(String args[]) {

        listfile();

        while (true) {
            ServerSocket welcomeSocket = null;
            Socket connectionSocket = null;
            BufferedOutputStream outToClient = null;

            try {
                welcomeSocket = new ServerSocket(3248);
                connectionSocket = welcomeSocket.accept();
                outToClient = new BufferedOutputStream(connectionSocket.getOutputStream());
            } catch (IOException ex) {
                // Do exception handling
            }


            if (outToClient != null) {

                String FileName = "carexception.java";

                File myFile = new File("C:\\"+FileName);

                byte[] mybytearray = new byte[(int) myFile.length()];

                FileInputStream fis = null;

                try {
                    fis = new FileInputStream(myFile);
                } catch (FileNotFoundException ex) {
                    // Do exception handling
                }
                BufferedInputStream bis = new BufferedInputStream(fis);

                try {
                    bis.read(mybytearray, 0, mybytearray.length);
                    outToClient.write(mybytearray, 0, mybytearray.length);
                    outToClient.flush();
                    outToClient.close();
                    connectionSocket.close();

                    // File sent, exit the main method
                    return;
                } catch (IOException ex) {
                    // Do exception handling
                }
            }

        }
    }
}

您是否尝试过创建数组,以便每个文件都有自己的索引。。。当客户机选择他想要的文件时,您将返回特定数组索引上的文件


~btw您可以序列化阵列并将其发送到客户端。

如何询问文件?按姓名我认为服务器接受命令并响应。您可以使用命令到服务器的格式:CMD_NAME,arg1,arg2。。。参数可以是二进制的,具体取决于命令。通过CMD_名称,您的服务器将区分您想要的内容(接受文件或提供文件)

您有一个问题,即您只接受一种类型的请求。您需要一个命令机制来向服务器请求不同的请求。服务器需要解析这些请求,而不是立即给出硬编码的答案。这将使它具有灵活性


我相信还有很多其他类似的例子。Java套接字是可靠的,不会有问题。刚开始学习基础知识,如何在客户端和服务器之间传递不同的消息。但是,您的问题根本与套接字无关。假设您通过文件进行通信:从一个文件读取请求,然后将响应写入另一个文件。那么你写了哪些信息?这称为协议。你需要设计一个简单的

您可以使用
ObjectOutputStream
通过
writeObject
发送字符串或任何其他类型的
Object
,来完成您需要更改的内容

您可以假定一个特定的协议顺序,即客户端需要向服务器发送请求,以便服务器执行任何操作,因此在建立连接时,服务器始终处于侦听状态

你应该

  • 引入发送请求和接收响应的循环
  • 了解如何发送字符串对象
  • 分解文件发送部分,这样您就不会分配比操作系统所能提供的更大的字节数组(例如,考虑一个4GB的文件,为整个文件分配一个字节数组可能会很麻烦)
  • 所以,记住这一点,我们可以开始了。关于步骤1,这可以使用while循环来完成。如果我们假设服务器总是侦听请求,那么服务器“请求循环”可能看起来像这样

    ClientRequest request;
    while (request.getType() != RequestType.Complete) {
        // receive new request
        // depending on type, send response
    }
    
    我们只是在这里添加了两个类,一个是封装客户端消息的
    ClientRequest
    ,另一个是定义客户端感兴趣的请求类型的enum
    RequestType
    ,例如文件列表或文件内容

    public enum RequestType {
       None, Complete, RequestFileList, RequestFileContent
    }
    
    public class ClientRequest {
       private RequestType type;
       public ClientRequest() {
           type = RequestType.None;
       }
    
       public RequestType getType() {
           return type;
       }
    }
    
    现在我们需要以某种方式将其附加到套接字,因此我们添加了一个接收请求的方法,并将该请求分配给当前请求实例

    ClientRequest request = new ClientRequest();
    while (request.getType() != RequestType.Complete) {
        // receive new request
        receiveRequest(clientSocket.getInputStream(), request);
        if (request.getType() != RequestType.Complete) {
            // pick a response
        }
    }
    
    private void receiveRequest(DataInputStream socketStream, ClientRequest request) {
        // get a type of request
        byte type = socketStream.readByte();
        request.setType(RequestType.from(type));
        // get parameters for request, depending on type
        if (request.getType() == RequestType.RequestFileContent) {
            // receive file id (file name for instance, or some other id that you prefer)
            String argument = readString(socketStream);
            request.setArgument(argument);
        }
    }
    
    这将在RequestType中添加一个
    from
    方法,将字节转换为请求;
    ClientRequest
    中添加一个
    setType
    方法,以及一个
    readString
    方法。我们还在ClientRequest中添加了一个新字段以及相应的get和set方法

    public enum RequestType {
        // types as before
        ;
        public static RequestType from(byte b) {
            switch (b) {
                case 1: return RequestType.Complete;
                case 2: return RequestType.RequestFileList;
                case 3: return RequestType.RequestFileContent;
                default: return RequestType.None;
             }
        }
    }
    
    public class ClientRequest {
        private String argument;
        public void setType(RequestType value) {
            type = value;
        }
    
        public String getArgument() {
            return argument;
        }
    
        public void setArgument(String value) {
            this.argument = value;
        }
    }
    
    private String readString(DataInputStream socketStream) {
        int length = socketStream.readInt();
        byte[] stringBytes = new byte[length];
        socketStream.read(stringBytes);
        return new String(stringBytes, "UTF-8");
    }
    
    现在我们进入下一步,响应请求。只需添加一个开关盒并处理请求类型

    {
        // depending on type, send response
        handleRequest(clientSocket.getOutputStream(), request);
    }
    
    private void handleRequest(DataOutputStream socketStream, ClientRequest request) {
        switch (request.getType()) {
            case RequestType.RequestFileList: {
                String[] fileList = getFileList(getCurrentDirectory());
                // send response type
                socketStream.write(ResponseType.ResponseFileList.getByte());
                // send number of files
                socketStream.writeInt(fileList.length);
                // send each string
                for (String fileName : fileList) {
                    sendString(socketStream, fileName);
                }
            }
            break;
            case RequestType.RequestFileContent: {
                // send response type ResponseType.ResponseFileContent
                // send length of file so other party can determine number of bytes to receive
                // send file contents in chunks of a fixed byte array length
                // send last part of file contents, if length of file is not evenly divided by array chunk size
            }
            break;
        }
    }
    
    sendString方法只是readString方法的“相反顺序”

    private void sendString(DataOutputStream socketStream, String value) {
        int length = value.length();
        socketStream.writeInt(length);
        byte[] stringBytes = value.getBytes("UTF-8");
        socketStream.write(stringBytes);
    }
    
    ResponseType
    是一个类似于
    RequestType
    中的值的枚举,因此客户端可以处理服务器发送的响应类型

    通过这些更改,您将能够请求文件列表并显示服务器发送的文件响应。当用户选择要接收的文件时,客户端可以向服务器发送新请求,服务器可以向客户端发送适当的文件内容

    客户端应用程序必须定义一个类似的
    ClientRequest
    类(可能名称为
    ServerResponse
    ),以及服务器指定用于读取和写入套接字流的相应方法。这可以通过在类中封装套接字来进一步抽象,在收到请求或响应时使用侦听器模式,GUI可以订阅这些请求或响应,……尽管这超出了我的示例


    如果您觉得我需要澄清任何事情,请留下评论,我会尽力回答。

    可以,但我想显示文件列表,让客户通过键入他想要的文件来回复。我如何创建该文件feature@RaymondBouChaaya据我所知,您询问如何创建这样的GUI表单,您可以在其中选择一个文件名?当程序运行时,我希望客户端能够从可用文件列表中选择一个文件并解释编码方式?顺便说一句,如果您只是复制其他人的代码,您应该这样做。我在第一步就失去了您,你能试着把它添加到原始代码中吗?因为我不知道该怎么放,我会非常感激的。第一步呢?你是说循环码吗?您应该在建立连接后添加它。
    private void sendString(DataOutputStream socketStream, String value) {
        int length = value.length();
        socketStream.writeInt(length);
        byte[] stringBytes = value.getBytes("UTF-8");
        socketStream.write(stringBytes);
    }