1. 程式人生 > >Java網路程式設計——基本網路支援

Java網路程式設計——基本網路支援

使用InetAddress

Jav使用InetAddress類來代表Ip地址,還有兩個子類:Inet4Address,Inet6Address分別代表IPv4和IPv6。

獲取例項

這個類沒有構造器

  • getByName(String host):根據主機獲取對應的InetAddress物件;
  • getByAddress(byte[] addr):根據原始Ip地址來獲取對應的InetAddress物件;

還提供以下三個方法來獲取InetAddress物件對應的IP和主機名:

  • String getCanonicalHostName():獲取IP地址的全限定域名;
  • String getHostAddress():返回該InetAddress例項對應的IP地址字串;
  • String getHostName():獲取此IP地址的主機名;

除此之外該類還提供了一個isReachable方法,用於測試是否可以達到該地址。

package demo1;

import java.io.IOException;
import java.net.InetAddress;


public class InetAddressTest {
    public static void main(String[] args) throws IOException {
        //根據主機名獲取對應InetAddress例項
        InetAddress ip = InetAddress.getByName("www.crazyit.org");

        //判斷是否可達
        System.out.println("crazyit是否可達:"+ip.isReachable(2000));
        //crazyit是否可達:true

        //獲取該InetAddress例項的IP字串
        System.out.println(ip.getHostAddress());
        //101.1.19.65

        //根據原始IP地址來獲取對應的例項
        //127, 0, 0, 1為本機
        InetAddress local = InetAddress.getByAddress(new byte[]{127, 0, 0, 1});

        System.out.println("本級是否可達:"+local.isReachable(2000));
        
        //獲取全限域名
        System.out.println(local.getCanonicalHostName());
        //www.xmind.com
    }
}

URL、URLConnection和URLPermission

URL物件代表統一資源定位器,它是指向網際網路資源的指標。通常情況下可以由協議名、主機、埠和資源組成。
URL類提供了多個構造器用於建立URL物件,一旦獲得了物件,就可以呼叫如下方法來訪問URL對應的資源:

  • String getFile():獲取該URL的資源名;
  • String getHost():獲取該URL的主機名;
  • String getPath():獲取URL的路徑部分;
  • int getPort():獲取埠號;
  • String getProtocol():獲取協議名稱;
  • String getQuery()
    :獲取查詢字串部分;
  • URLConnection openConnection():返回一個URLConnection物件,代表了與URL所引用的遠端物件連線;
  • InputStream openStream():開啟與此URL的連線,並返回一個用於讀取該資源的InputStream。

例項:實現一個多執行緒下載工具類

package demo1;

import java.io.IOException;
import java.io.InputStream;
import java.io.RandomAccessFile;
import java.net.*;

public class DownUtil {
    //定義下載資源的路徑
    private String path;
    //指定所下載檔案的儲存位置
    private String targetFile;
    //定義需要使用多少個執行緒下載資源
    private int threadNum;
    //定義下載的執行緒物件
    private DownThread[] threads;
    //定義下載的檔案的總大小
    private int fileSize;

    public DownUtil(String path, String targetFile, int threadNum) {
        this.path = path;
        this.targetFile = targetFile;
        this.threadNum = threadNum;
        //初始化Thread陣列
        threads=new DownThread[threadNum];
    }

    public void download() throws IOException {
        URL url = new URL(path);
        //獲取連線物件
        HttpURLConnection conn =(HttpURLConnection) url.openConnection();
        //得到檔案大小
        fileSize= conn.getContentLength();
        conn.disconnect();
        //平均分給每個執行緒多少位元組,如果除不盡給每個執行緒多讀一個位元組
        int currentPartSize=fileSize/threadNum+1;
        RandomAccessFile file = new RandomAccessFile(targetFile, "rw");
        //設定本地檔案大小
        System.out.println(fileSize);
        file.close();
        for (int i = 0; i < threadNum; i++) {
            //計算每個執行緒下載的開始位置
            int startPos=i*currentPartSize;
            System.out.println(startPos);
            //每個執行緒使用一個RandomAccessFile(進行下載
            RandomAccessFile currentPart = new RandomAccessFile(targetFile, "rw");
            //定位該執行緒的下載位置
            currentPart.seek(startPos);
            //建立下載執行緒
            threads[i] = new DownThread(startPos, currentPartSize, currentPart);
            threads[i].start();
        }
    }
    //獲取下載的百分比
    public double getCompleteRate(){
        //統計多個執行緒已經下載的總大小
        int sumSize=0;
        for (int i = 0; i < threadNum; i++) {
            sumSize+=threads[i].length;
        }
        //返回已經完成的百分比
        return sumSize*1.0/fileSize;
    }
    private class DownThread extends Thread{
        //當前執行緒的下載位置
        private int startPos;
        //定義當前執行緒負責下載的檔案大小
        private int currentPartSize;
        //當前執行緒需要下載的檔案塊
        private RandomAccessFile currentPart;
        //該執行緒已下載的位元組數
        public int length;

        public DownThread(int startPos, int currentPartSize, RandomAccessFile currentPart) {
            this.startPos = startPos;
            this.currentPartSize = currentPartSize;
            this.currentPart = currentPart;
        }

        @Override
        public void run() {
            try {
                handle();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        private void handle() throws IOException {
            URL url = new URL(path);
            //獲取連線物件
            HttpURLConnection conn =(HttpURLConnection) url.openConnection();
            InputStream in = conn.getInputStream();
            //跳過startPos個位元組
            in.skip(this.startPos);
             currentPart.seek(this.startPos);
            byte[] buff = new byte[1024 * 8];
            int hasRead=0;
            while (length<currentPartSize&&(hasRead=in.read(buff))>0){
                currentPart.write(buff,0,hasRead);
                //累計下載總大小
                length+=hasRead;
            }
            currentPart.close();
            in.close();
        }
    }
}

測試

package demo1;

import java.io.IOException;
public class MultThreadDown {
    public static void main(String[] args) throws IOException {
        DownUtil downUtil = new DownUtil("http://a.hiphotos.baidu.com/"
                +"image/pic/item/d009b3de9c82d158ec9917f38d0a19d8bc3e425c.jpg"
                , "ios.jpg", 4);

        //開始下載
        downUtil.download();
        System.out.println("hello");
        new Thread(()->{
            while (downUtil.getCompleteRate()<1){
                System.out.println("已完成:"+downUtil.getCompleteRate());
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            //每隔0.1秒查詢一次任務完成的進度
        }).start();
    }
}

如果要斷點賦值則需要一個配置檔案來存放每個執行緒每次斷點時正在讀取的位置,以便下一次從此位置開始讀取。