使用
socket
編程實現一個簡單的文件服務器。客戶端程序實現
put
功能
(
將一個
文件從本地傳到文件服務器
)
和
get
功能
(
從文件服務器取一遠程文件存為本地
文件
)
。客戶端和文件服務器不在同一台機器上。
put [-h
hostname
] [-p
portname
]
local_filename
remote_filename
get [-h
hostname
] [-p
portname
]
remote_filename
local_filename
程序如下:
客戶端Client.java
package com.cn.gao; import java.net.*; import java.io.*; /** * * 用Socket實現文件服務器的客戶端 * 包含發送文件和接收文件功能 * */ public class Client { private Socket client; private boolean connected; //構造方法 public Client(String host,int port){ try { //創建Socket對象 client = new Socket(host,port); System.out.println("服務器連接成功!"); this.connected = true; } catch (UnknownHostException e) { System.out.println("無法解析的主機!"); this.connected = false; } catch (IOException e) { System.out.println("服務器連接失敗!"); this.connected = false; closeSocket(); } } //判斷是否連接成功 public boolean isConnected(){ return connected; } //設置連接狀態 public void setConnected(boolean connected){ this.connected = connected; } /** * 發送文件方法 * @param localFileName 本地文件的全路徑名 * @param remoteFileName 遠程文件的名稱 */ public void sendFile(String localFileName, String remoteFileName){ DataOutputStream dos = null; //寫Socket的輸出流 DataInputStream dis = null; //讀取本地文件的輸入流 if(client==null) return; File file = new File(localFileName); //檢查文件是否存在 if(!file.exists()){ System.out.println("本地文件不存在,請查看文件名是否寫錯!"); this.connected = false; this.closeSocket(); return; } try { //初始化本地文件讀取流 dis = new DataInputStream(new BufferedInputStream(new FileInputStream(file))); //將指令和文件發送到Socket的輸出流中 dos = new DataOutputStream(client.getOutputStream()); //將遠程文件名發送出去 // System.out.println(remoteFileName); dos.writeUTF("put "+remoteFileName); //清空緩存,將文件名發送出去 dos.flush(); //開始發送文件 int bufferSize = 10240; byte[] buf = new byte[bufferSize]; int num =0; while((num=dis.read(buf))!=-1){ dos.write(buf, 0, num); } dos.flush(); System.out.println("文件發送成功!"); } catch (IOException e) { System.out.println("文件傳輸錯誤!"); closeSocket(); } finally{ try { dis.close(); dos.close(); } catch (IOException e) { System.out.println("輸入輸出錯誤!"); } } } /** * 接收文件方法 * @param remoteFileName 本地文件的全路徑名 * @param localFileName 遠程文件的名稱 */ public void receiveFile(String remoteFileName, String localFileName){ DataOutputStream dos = null; //寫Scoket的輸出流 DataInputStream dis = null; //讀Socket的輸入流 DataOutputStream localdos = null; //寫本地文件的輸出流 if(client==null) return; try { localdos = new DataOutputStream(new BufferedOutputStream(new FileOutputStream(localFileName))); //將指令和文件名發送到Socket的輸出流中 dos = new DataOutputStream(client.getOutputStream()); //將遠程文件名發送出去 dos.writeUTF("get "+remoteFileName); dos.flush(); //開始接收文件 dis = new DataInputStream(new BufferedInputStream(client.getInputStream())); int bufferSize = 10240; byte[] buf = new byte[bufferSize]; int num = 0; while((num=dis.read(buf))!=-1){ localdos.write(buf, 0, num); } localdos.flush(); System.out.println("數據接收成功!"); } catch (FileNotFoundException e) { System.out.println("文件沒有找到!"); closeSocket(); } catch (IOException e) { System.out.println("文件傳輸錯誤!"); } finally { try { dos.close(); localdos.close(); dis.close(); } catch (IOException e) { e.printStackTrace(); } } } //關閉端口 public void closeSocket(){ if(client!=null){ try { client.close(); } catch (IOException e) { e.printStackTrace(); } } } /** * 主方法調用上述方法 * @param args * 將本地文件上傳到遠程服務器 * put[-h hostname][-p portname]local_filename remote_filename * 從遠程服務器上下載文件 * get[-h hostname][-p portname]remote_filename local_filename */ public static void main(String[] args){ //服務器默認端口為8888 if(args.length!=7){ System.out.println("參數數目不正確!"); return; } String hostName = args[2]; int port = 0; String localFileName = ""; String remoteFileName = ""; Client client = null; try { port = Integer.parseInt(args[4]); } catch (NumberFormatException e) { System.out.println("端口號輸出格式錯誤!"); return; } if(args[0].equals("put")){ //上傳文件 client = new Client(hostName,port); localFileName = args[5]; remoteFileName = args[6]; // System.out.println(remoteFileName); if(client.isConnected()){ client.sendFile(localFileName, remoteFileName); client.closeSocket(); } }else if(args[0].equals("get")){ //下載文件 client = new Client(hostName,port); localFileName = args[6]; remoteFileName = args[5]; if(client.isConnected()){ client.receiveFile(remoteFileName, localFileName); client.closeSocket(); } }else{ System.out.println("命令輸入不正確,正確命令格式如下:"); System.out.println("put -h hostname -p portname local_filename remote_filename"); System.out.println("get -h hostname -p portname remote_filename local_filename"); } } }
服務器端Server.java
package com.cn.gao; import java.io.*; import java.net.*; /** * 實現服務器端 * 用於接收上傳的數據和供客戶端下載數據 * @author DELL * */ public class Server { private int port; private String host; private String dirPath; private static ServerSocket server; public Server(int port,String dirPath){ this.port = port; this.dirPath = dirPath; this.server = null; } public void run(){ if(server==null){ try { server = new ServerSocket(port); } catch (IOException e) { e.printStackTrace(); } } System.out.println("服務已啟動..."); while(true){ try { //通過ServerSocket的accept方法建立連接,並獲取客戶端的Socket對象 Socket client = server.accept(); if(client==null) continue; new SocketConnection(client,this.dirPath).run(); } catch (IOException e) { e.printStackTrace(); } } } /** * 實現服務器端的數據傳輸 * @author DELL * */ public class SocketConnection extends Thread{ private Socket client; private String filePath; public SocketConnection(Socket client, String filePath){ this.client = client; this.filePath = filePath; } public void run(){ if(client==null) return; DataInputStream in= null; //讀取Socket的輸入流 DataOutputStream dos = null; //寫文件的輸出流 DataOutputStream out = null; //寫Socket的輸出流 DataInputStream dis = null; //讀文件的輸入流 try { //訪問Scoket對象的getInputStream方法取得客戶端發送過來的數據流 in = new DataInputStream(new BufferedInputStream(client.getInputStream())); String recvInfo = in.readUTF(); //取得附帶的指令及文件名 // System.out.println(recvInfo); String[] info = recvInfo.split(" "); String fileName = info[1]; //獲取文件名 // System.out.println(fileName); if(filePath.endsWith("/")==false&&filePath.endsWith("\\")==false){ filePath+="\\"; } filePath += fileName; if(info[0].equals("put")){ //從客戶端上傳到服務器 //開始接收文件 dos = new DataOutputStream(new BufferedOutputStream(new FileOutputStream(new File(filePath)))); int bufferSize = 10240; byte[] buf = new byte[bufferSize]; int num =0; while((num=in.read(buf))!=-1){ dos.write(buf, 0, num); } dos.flush(); System.out.println("數據接收完畢!"); }else if(info[0].equals("get")){ //從服務器下載文件到客戶端 dis = new DataInputStream(new BufferedInputStream(new FileInputStream(filePath))); //開始發送文件 int bufferSize = 10240; byte[] buf = new byte[bufferSize]; out = new DataOutputStream(client.getOutputStream()); int num =0; while((num=dis.read(buf))!=-1){ out.write(buf, 0, num); } out.flush(); System.out.println("發送成功!"); } } catch (IOException e) { e.printStackTrace(); } finally{ try { if(out!=null) out.close(); if(in!=null) in.close(); if(dos!=null) dos.close(); if(dis!=null) dis.close(); client.close(); } catch (IOException e) { e.printStackTrace(); } } } } public static void main(String[] args){ //設置服務器端口 int port = 8888; //設置服務器文件存放位置 String dirPath = "D:\\FTPService\\"; new Server(port,dirPath).run(); } }
參數輸入方式示例
put -h 127.0.0.1 -p 8888 D:\\data.xls data.xls
get -h 127.0.0.1 -p 8888 data.xls D:\\data.xls