2013-01-06 77 views
0

我为服务器和客户端编写了一些代码,用于将文件从服务器传输到客户端,并且它像一个魅力一样工作;但我有几个问题。我想在GUI下创建这些代码,并且我想列出文件夹中的所有文件,但是如何让客户端在看到提供的文件列表后选择他想要的文件(如何将字符串发送给服务器为了选择文件)?向服务器发送请求java

服务器代码

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 
       } 
      } 

     } 
    } 
} 

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

class TCPClient { 

    public static void main(String args[]) { 
     Scanner s = new Scanner(System.in); 
     byte[] aByte = new byte[1]; 
     int bytesRead; 

     Socket clientSocket = null; 
     InputStream is = null; 

     try { 
      clientSocket = new Socket("127.0.0.1", 3248); 
      is = clientSocket.getInputStream(); 
     } catch (IOException ex) { 
      // Do exception handling 
     } 
     ByteArrayOutputStream baos = new ByteArrayOutputStream(); 

     if (is != null) { 

      FileOutputStream fos = null; 
      BufferedOutputStream bos = null; 
      try { 
       fos = new FileOutputStream("E:\\sss.java"); 
       bos = new BufferedOutputStream(fos); 
       bytesRead = is.read(aByte, 0, aByte.length); 

       do { 
         baos.write(aByte); 
         bytesRead = is.read(aByte); 
       } while (bytesRead != -1); 

       bos.write(baos.toByteArray()); 
       bos.flush(); 
       bos.close(); 
       clientSocket.close(); 
      } catch (IOException ex) { 
       // Do exception handling 
      } 
     } 
    } 
} 
+0

顺便说一句,你应该[引用你的来源](http://stackoverflow.com/a/4687706/116249),如果你只是复制别人的代码。 – Patrick

回答

0

您是否尝试过创建一个数组,所以每个文件都有它自己的索引...客户端代码当客户选择他想要的文件,然后你返回某个数组索引上的文件。

〜btw你可以序列化你的数组并发送给客户端。

+0

它可以工作,但我想显示的文件列表和客户端通过输入他想要的文件来回复我怎么能创建该功能 –

+0

@RaymondBouChaaya据我了解,你问如何创建这样的GUI形式,其中你可以选择一个文件的名称? –

+0

当程序运行时,我希望客户端能够从可用文件列表中选择一个文件 –

1

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

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

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

+0

你能解释明智的编码吗? –

0

您可以使用ObjectOutputStream通过writeObject发送字符串或任何其他种类Object

2

要完成你以后需要改变的事情。

您可以假设一个特定的协议顺序,意思是客户端需要发送一个请求到服务器以便服务器做任何事情,所以服务器在建立连接时总是处于监听状态。

你也应该

  1. 介绍发送请求和接收响应
  2. 图如何发送一个字符串对象的循环
  3. 分手的文件发送一部分,所以你不分配更多的字节阵列比操作系统可以交给你(例如考虑一个文件为4GB,为整个文件分配一个字节数组可能会很麻烦)

所以,考虑到这一点,我们可以得到布莱恩G。关于第1步,这可以使用while循环来完成。如果我们假设服务器总是监听请求,那么服务器“请求循环”可以看起来像这样。

ClientRequest request; 
while (request.getType() != RequestType.Complete) { 
    // receive new request 
    // depending on type, send response 
} 

我们只是在这里添加两个班,一个ClientRequest从客户端封装的消息,以及定义客户端感兴趣的请求的类型,例如文件列表或文件内容的枚举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); 
} 

ResponseTypeRequestType类似的那些值的枚举,因此客户端可以处理响应的服务器发送类型。

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

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

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

+0

我在第一步失去了你,你能否尝试将它添加到原始代码中,因为我失去了将它放在一边,我会非常感谢。 –

+0

第一步呢?你的意思是循环代码?连接建立后应该添加它。 – Patrick