使用socket編程實現一個簡單的文件服務器


使用 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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM