2017-03-31 20 views
1

TL; DR:どのように(1つの接続で)ファイル、そのサイズと名前を送信しますか。インターネットのすべての例では、ファイルを単独で送信します。ソケット経由でファイルを送信する - バッファサイズ

サーバー:

public class Server { 
    private static int PORT = 6667; 
    private ServerSocket serverSocket; 

    public void run() throws IOException { 
     System.out.println("Opening server"); 
     serverSocket = new ServerSocket(PORT); 

     while(true) { 
      try(Socket incomingSocket = serverSocket.accept()) { 
       System.out.println("Accepted connection: " + incomingSocket); 
       incomingSocket.setSoTimeout(2000); // Don't let scanner block the thread. 

       InputStream inputStream = incomingSocket.getInputStream(); 
       Scanner scanner = new Scanner(inputStream); 

       String command = ""; 
       if(scanner.hasNextLine()) 
        command = scanner.nextLine(); 

       if(command.equals("update")) { 
        File file = new File("abc.txt"); 
        sendFile(incomingSocket, file); 
       } 
       else { 
        // ... 
        System.out.println("Another command"); 
       } 
      } 
     } 
    } 

    private void sendFile(Socket socket, File file) throws IOException { 
     byte[] bytes = new byte[(int)file.length()]; 
     FileInputStream fileInputStream = new FileInputStream(file); 
     BufferedInputStream bufferedInputStream = new BufferedInputStream(fileInputStream); 
     bufferedInputStream.read(bytes, 0, bytes.length); 
     OutputStream outputStream = socket.getOutputStream(); 

     PrintWriter writer = new PrintWriter(outputStream, true); 
     writer.println(file.length()); 
     writer.println(file.getName()); 

     System.out.println("Sending " + file.getName() + "(" + bytes.length + " bytes) to " + socket); 
     outputStream.write(bytes, 0, bytes.length); 
     outputStream.flush(); 
     System.out.println("File sent"); 
    } 

    public void stopRunning() { 
     try { 
      serverSocket.close(); 
     } catch(IOException e) { 
      e.printStackTrace(); 
     } 
    } 
} 

クライアント:

public class Client { 
    private static String HOST = "localhost"; 
    private static int PORT = 6667; 

    public void run() throws IOException { 
     Socket socket = new Socket(HOST, PORT); 
     System.out.println("Connecting..."); 

     OutputStream outputStream = socket.getOutputStream(); 
     PrintWriter writer = new PrintWriter(outputStream, true); 
     writer.println("update");  // Example command which will determine what server sends back 

     receiveFile(socket); 

     socket.close(); 
    } 

    private void receiveFile(Socket socket) throws IOException { 
     InputStream inputStream = socket.getInputStream(); 

     int size = 16384; 
     String name = "example.txt"; 

     Scanner scanner = new Scanner(inputStream); 
     size = Integer.parseInt(scanner.next()); 
     name = scanner.next(); 

     FileOutputStream fileOutputStream = new FileOutputStream(name); 
     BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(fileOutputStream); 

     byte[] buffer = new byte[size]; 
     int bytesRead, totalRead = 0; 
     while ((bytesRead = inputStream.read(buffer, 0, buffer.length)) != -1) { 
      totalRead += bytesRead; 
      bufferedOutputStream.write(buffer, 0, bytesRead); 
     } 
     bufferedOutputStream.flush(); 

     System.out.println("File " + name + " received. " + totalRead + " bytes read"); 

     bufferedOutputStream.close(); 
     fileOutputStream.close(); 
    } 

は、私は私のサーバーがクライアントにファイルを送信したいです。また、ファイルの名前とサイズも含める必要があります。名前は非常に重要でサイズが大きいので、私は巨大なサイズのハードコードされたバッファを作りたくないからです。

上記のコードで試してみてください。クライアントの「スキャナ部」

Scanner scanner = new Scanner(inputStream); 
size = Integer.parseInt(scanner.next()); 
name = scanner.next(); 

は正常ですが、ファイルは受信されません。 inputStream.read(buffer、0、buffer.length)は、ストリームから残りのバイトを読み取ることはありません。

私はスキャナ部をコメントアウトした場合は、バイトがそう正しく

(サイズと名前の情報+ファイル自体を)読んでいる、問題は、私は、単一の接続でそれを送信しないか、でしょうか?または、2つの別々の接続を作成する必要があります。まず最初にサイズとファイル名を尋ね、2番目のファイルにファイルを送信しますか?

答えて

0

Scannerは、テキストベースの作業に適しています。

好きな方法は、DataInputStreamDataOutputStreamです。 1つの接続のみが必要です:

public void send(File file, OutputStream os) throws IOException { 
    DataOutputStream dos = new DataOutputStream(os); 

    // writing name 
    dos.writeUTF(file.getName()); 
    // writing length 
    dos.writeLong(file.length()); 

    // writing file content 
    ... your write loop, write to dos 

    dos.flush(); 
} 

public void receive(InputStream is) throws IOException { 
    DataInputStream dis = new DataInputStream(is); 

    String fileName = dis.readUTF(); 
    long fileSize = dis.readLong(); 

    // reading file content 
    ... your read loop, read from dis 
} 
+0

素晴らしい、ありがとう。ストリームを正しく処理する方法について少しお読みください:) – MrGrzyboo

関連する問題