From Gossip@Openhome

Java Gossip: 檔案傳送

之前的幾個範例都是傳送文字指令或資訊給連線的另一端,適當的改寫一下,就可以作檔案傳送,主要是使用PrintStream的write()方法,它負責將位元或int傳送給連線的另一端。

程式分作兩個,一個伺服端與一個客戶端,伺服端會傾聽連線,而客戶端在連線傳送一個檔案之後就會結束程式,這是檔案傳送的一個簡單例子,首先是伺服端程式:
  • Server.java
package onlyfun.caterpillar;

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

public class Server {
public static void main(String[] args) {
try {
int port = Integer.parseInt(args[0]);
System.out.println("簡易檔案接收...");
System.out.printf("將接收檔案於連接埠: %d%n", port);

ServerSocket serverSkt = new ServerSocket(port);

while(true) {
System.out.println("傾聽中....");

Socket clientSkt = serverSkt.accept();

System.out.printf("與 %s 建立連線%n",
clientSkt.getInetAddress().toString());

// 取得檔案名稱
String fileName = new BufferedReader(
new InputStreamReader(
clientSkt.getInputStream())).readLine();

System.out.printf("接收檔案 %s ...", fileName);

BufferedInputStream inputStream =
new BufferedInputStream(clientSkt.getInputStream());
BufferedOutputStream outputStream =
new BufferedOutputStream(new FileOutputStream(fileName));

int readin;
while((readin = inputStream.read()) != -1) {
outputStream.write(readin);
Thread.yield();
}

outputStream.flush();
outputStream.close();
inputStream.close();

clientSkt.close();

System.out.println("\n檔案接收完畢!");
}
}
catch(Exception e) {
e.printStackTrace();
}
}
}

再來是客戶端程式:
  • Client.java
package onlyfun.caterpillar;

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

public class Client {
public static void main(String[] args) {
try {
System.out.println("簡易檔案傳送...");

String remoteHost = args[0];
int port = Integer.parseInt(args[1]);
File file = new File(args[2]);

System.out.printf("遠端主機: %s%n", remoteHost);
System.out.printf("遠端主機連接埠: %d%n", port);
System.out.printf("傳送檔案: %s%n", file.getName());

Socket skt = new Socket(remoteHost, port);

System.out.println("連線成功!嘗試傳送檔案....");

PrintStream printStream =
new PrintStream(skt.getOutputStream());
printStream.println(file.getName());

System.out.print("OK! 傳送檔案....");

BufferedInputStream inputStream =
new BufferedInputStream(
new FileInputStream(file));

int readin;
while((readin = inputStream.read()) != -1) {
printStream.write(readin);
Thread.yield();
}

printStream.flush();
printStream.close();
inputStream.close();

skt.close();

System.out.println("\n檔案傳送完畢!");
}
catch(Exception e) {
e.printStackTrace();
}
}
}

為簡化程式範例,程式是單一流程,不使用多執行緒,下面是伺服端的執行範例:
$ java onlyfun.caterpillar.Server 9393
簡易檔案接收...
將接收檔案於連接埠: 9393
傾聽中....
與 /127.0.0.1 建立連線
接收檔案 caterpillar.jpg ...
檔案接收完畢!
傾聽中....

下面是對應的客戶端執行範例:

$ java onlyfun.caterpillar.Client localhost 9393 e:\caterpillar.jpg
簡易檔案傳送...
遠端主機: localhost
遠端主機連接埠: 9393
傳送檔案: caterpillar.jpg
連線成功!嘗試傳送檔案....
OK! 傳送檔案....
檔案傳送完畢!