2015-06-08 93 views
0

我正在制作一个程序,它接收一个文件,并通过套接字将其发送到客户端。客户端收到它并将其保存到文件中。这就是它应该做的。Java套接字接收字节数组,其中每个字节是0

但不知何故,客户端收到的字节数组只包含0个字节,所以我的输出文件是空的。这里是代码:

服务器:

try { 
     serverSocket=new ServerSocket(7575); 
     serverSocket.setSoTimeout(1000000); 
     System.out.println("serverSocket created."); 
    } catch (IOException ex) { 
     Logger.getLogger(Server.class.getName()).log(Level.SEVERE, null, ex); 
     System.out.println("Error in creating new serverSocket on port 7575"); 
    } 

    for(int i=0;i<array.length;i++) 
     System.out.println(array[i]); 

    Socket socket=null; 
    try { 
     System.out.println("Waiting for client..."); 
     socket=serverSocket.accept(); 
     System.out.println("Client accepted."); 
    } catch (IOException ex) { 
     Logger.getLogger(Server.class.getName()).log(Level.SEVERE, null, ex); 
    } 
    PrintWriter outWriter=null; 
    DataOutputStream outputStream=null; 
    OutputStream os=null; 
    BufferedOutputStream bos=null; 
    try { 
     os=socket.getOutputStream(); 
     outputStream=new DataOutputStream(os); 
     outWriter=new PrintWriter(socket.getOutputStream()); 
     bos=new BufferedOutputStream(socket.getOutputStream()); 
     System.out.println("Server streams created."); 
    } catch (IOException ex) { 
     Logger.getLogger(Server.class.getName()).log(Level.SEVERE, null, ex); 
    } 
    System.out.println("sending name "+name); 
    outWriter.println(name); 
    outWriter.flush(); 

    outWriter.println(array.length); 
    outWriter.println("array.length"+array.length); 
    outWriter.flush(); 

    try { 
     os.write(array); 
     os.flush(); 
    } catch (IOException ex) { 
     Logger.getLogger(Server.class.getName()).log(Level.SEVERE, null, ex); 
     System.out.println("couldnt send array of bytes"); 
    } 



    try { 
     os.close(); 
     outputStream.close(); 

     socket.close(); 
    } catch (IOException ex) { 
     Logger.getLogger(Server.class.getName()).log(Level.SEVERE, null, ex); 
    } 

客户端:

public class Client implements Runnable { 
private Socket socket; 
private String folderPath; 

public Client(String p) 
{ 
    folderPath=p; 
} 

@Override 
public void run() 
{ 
    try { 
     System.out.println("Client connecting to localhost on 7575 port..."); 
     socket=new Socket("localhost", 7575); 
    } catch (IOException ex) { 
     Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex); 
    } 

    BufferedReader reader=null; 
    BufferedInputStream bis=null; 
    InputStream input=null; 
    DataInputStream in=null; 
    try { 
     System.out.println("creating streams"); 
     reader=new BufferedReader(new InputStreamReader(socket.getInputStream())); 
     input=socket.getInputStream(); 
     in=new DataInputStream(input); 
     bis=new BufferedInputStream(socket.getInputStream()); 
     System.out.println("streams created!"); 
    } catch (IOException ex) { 
     Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex); 
    } 
    String name=""; 
    int size=0; 
    String s="32"; 
    try { 
     name=reader.readLine(); 
     s=reader.readLine(); 
    } catch (IOException ex) { 
     Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex); 
    } 
    if(s!=null) 
    size=Integer.parseInt(s); 
    System.out.println("name: "+name); 
    System.out.println("size: "+size); 

    byte [] arr=new byte[size]; 
    try { 
     input.read(arr); 
    } catch (IOException ex) { 
     Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex); 
     System.out.println("couldnt read the byte array"); 
    } 

    for(int i=0;i<arr.length;i++) 
     System.out.println(arr[i]); 

    FileOutputStream fos=null; 
    try { 
     fos=new FileOutputStream(folderPath+"/"+name); 
     } catch (FileNotFoundException ex) { 
      System.out.println("Could write the file"); 
     Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex); 
    } 
    try { 

     fos.write(arr); 
     fos.flush(); 
     } catch (IOException ex) { 
      System.out.println("Could write the file2"); 
     Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex); 
    } 

    try { 
     fos.close(); 
     } catch (IOException ex) { 
     Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex); 
    } 


     try { 
     in.close(); 
     input.close(); 
     reader.close(); 
     socket.close(); 
     } catch (IOException ex) { 
     Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex); 
     } 



} 

}

+0

不要在同一套接字上使用多个阅读器,编写器和流。它不会工作。选择一种技术并坚持下去。 – EJP

回答

2

在同一个数据流上混合使用二进制和文本模式很棘手。你会被建议不要这样做。使用DataInputStream(用于名称,计数和文件内容)是一种可能的解决方案。 (这就是我会尝试的)。另一种方法是将文件内容编码为文本(例如使用Base64编码)。

您当前的“混合流:代码在客户端”的问题。当您从BufferedReader读取名称和大小时,将导致读取器从套接字读取并缓冲最多4096个字节。是一些字节是文件内容所以,当你再尝试读取从底层InputStream这里的内容:。

input.read(arr); 

,你可能会发现,有没有什么可以读取结果:一个空的或损坏的文件。


The也是另一个问题。您的代码假定input.read(arr)语句将读取流的其余部分,或者直到它填充字节数组。这个假设是不正确的。当您从套接字流中读取数据时,read只会返回当前可用的字节(位于客户端网络堆栈中)。

再次,结果可能是一个损坏的文件。 (在这种情况下截断。)

读取的代码应该是这个样子:

int count = 0; 
    while (count < size) { 
     int bytesRead = is.read(bytes, count, bytes.length - count); 
     if (bytesRead == -1) { 
      throw EOFException("didn't get a complete file"); 
     } 
     count += bytesRead; 
    } 

最后:

  • 读取文件内容为字节数组,在两端浪费内存,并且准备对于一个非常大的文件来说是有问题的。

  • 你真的应该使用“试用资源”来确保所有的流都被正确关闭。手工操作繁琐,可能会导致资源泄漏。

+0

谢谢。当我修改代码时,只有一个模式(另一端是DataInputStream和DataOutputStream)在服务器和客户端发送和接收文件,它工作。我使用另一端的DataOutputStream.writeUTF()和readUTF()来发送字符串。 – xpg94

1

可以使用DataOutputStream类直接写入使用writeUTF输出流的一些字符串(消息)( )功能。然后你可以使用readUTF()方法使用DataInputStream类的对象接收消息。

u能以下发送使用数据: -

String message="something"; 
DataOutputStream out=new DataOutputStream(socket.getOutputStream()); 
out.writeUTF(message); 

和U可以接收数据或消息使用以下内容: -

DataInputStream in=new DataInputStream(socket.getInputStream()); 
String message=in.readUTF(); 

我基本上使用这些方法来读取从输入流数据和写数据输出流多次,它每次都工作,所以你也应该检查这种方式。

1

我想提出一个程序,它需要一个文件,并通过插座将其发送给客户端。客户端收到它并将其保存到文件中。这就是它应该做的。

如果您有没有必要检查正通过,通过什么样的内容,那么直InputStreamOutputStream都去,在我看来的方式。代码简单快速,因为它避免了由检查内容进行编码等的高级流类型所带来的任何开销。这也减少了破坏信息的机会。

我与斯蒂芬C'S答案达成一致,除了

读取文件内容为字节数组,在两端浪费内存,并且将成为一个真正的大文件的问题。

由于只需将一个文件移动到另一个系统而无需查看这些值,因此如果您知道如何处理内容,则这不是问题。基本流程是

client: InputStream in = getFileInputStream(); 
     OutputStream out = socket.getOutputStream(); 
     byte[] bytes = new byte[BUFFER_SIZE]; // could be anything 
     int bytesRead; 
     while((bytesRead = in.read(bytes)) != -1){ 
      out.write(bytes,0,bytesRead); 
     } 
     in.close(); 
     out.close(); 

server: InputStream in = socket.getInputStream(); 
     OutputStream out = getFileOutputStream(); 
     // the rest is the exact same thing as the client 

这将处理任何大小的文件,只受服务器的磁盘大小的限制。

这是我鞭打的一个例子。无可否认,这是很冒险的(例如使用FILE_COUNTERSTOP_KEY),但我只是试图展示让用户输入文件然后在客户端和服务器之间发送的各个方面。

public class FileSenderDemo { 

    private static final int PORT = 7999; 
    private static final String STOP_KEY = "server.stop"; 

    private static final int[] FILE_COUNTER = {0}; 

    public static void main(String[] args) { 

     FileSenderDemo sender = new FileSenderDemo(); 

     Thread client = new Thread(sender.getClient()); 
     Thread server = new Thread(sender.getServer()); 

     server.start(); 
     client.start(); 
     try { 
      server.join(); 
      client.join(); 
     } catch (InterruptedException e) { 
      FILE_COUNTER[0] = 999 ; 
      System.setProperty(STOP_KEY,"stop"); 
      throw new IllegalStateException(e); 
     } 
    } 

    public void send(File f, OutputStream out) throws IOException{ 
     try(BufferedInputStream in = new BufferedInputStream(new FileInputStream(f),1<<11)){ 
      byte[] bytes = new byte[1<<11]; 
      int bytesRead; 
      while((bytesRead = in.read(bytes)) != -1){ 
       out.write(bytes,0,bytesRead); 
      } 
     } 
    } 

    public Runnable getClient() { 
     return() -> { 
      while(FILE_COUNTER[0] < 3 && System.getProperty(STOP_KEY) == null) { 
       Socket socket; 
       try { 
        socket = new Socket("localhost", PORT); 
       } catch (IOException e) { 
        throw new IllegalStateException("CLIENT: Can't create the client: " + e.getMessage(), e); 
       } 

       File f = getFile(); 

       try (BufferedOutputStream out = new BufferedOutputStream(socket.getOutputStream())) { 
        send(f, out); 
       } catch (IOException e) { 
        System.out.println("CLIENT: Failed to send file " + f.getAbsolutePath()+" due to: " + e.getMessage()); 
        e.printStackTrace(System.err); 
       } finally { 
        FILE_COUNTER[0]++; 
       } 
      } 
      System.setProperty(STOP_KEY,"stop"); 
     }; 
    } 

    public File getFile(){ 
     Scanner scanner = new Scanner(System.in); 
     System.out.println("CLIENT: Enter a file Name: "); 
     return new File(scanner.next()); 
    } 

    public Runnable getServer(){ 
     return() -> { 
      OutputStream out = null; 
      try{ 
       ServerSocket server = new ServerSocket(PORT); 
       server.setSoTimeout(20000); 
       while(System.getProperty(STOP_KEY) == null){ 
        Socket socket = null; 
        try { 
         socket = server.accept(); 
        }catch (SocketTimeoutException e){ 
         System.out.println("SERVER: Waited 20 seconds for an accept. Now checking if we need to stop."); 
         continue; 
        } 
        String fileName = "receivedFile_"+System.currentTimeMillis()+".content"; 
        File outFile = new File(fileName); 
        out = new BufferedOutputStream(new FileOutputStream(outFile)); 
        InputStream in = socket.getInputStream(); 
        int bytesRead; 
        byte[] bytes = new byte[1<<12]; 
        while((bytesRead = in.read(bytes)) != -1){ 
         out.write(bytes,0,bytesRead); 
        } 
        out.close(); 
        socket.close(); 
        System.out.println("SERVER: Just created a new file: " + outFile.getAbsolutePath()); 
       } 
       System.out.println("SERVER: " + STOP_KEY + " was not null, so quit."); 
      }catch (IOException e){ 
       throw new IllegalStateException("SERVER: failed to receive the file content",e); 
      }finally { 
       if(out != null){ 
        try{out.close();}catch (IOException e){} 
       } 
      } 
     }; 
    } 
} 
相关问题