Java基礎進階_day17_(網絡編程)

Java基礎進階_day17_(網絡編程)

1. 網絡編程

1.1 網絡編程三要素

網絡編程三要素:
    A:IP地址
    B:端口
    C:協議
IP地址:
    網絡中計算機的唯一標識。
    計算機只能識別二進制的數據,所以我們的IP地址應該是一個二進制的數據。
    但是呢,我們配置的IP地址確不是二進制的,爲什麼呢?
        IP:192.168.1.100
        換算:11000000 10101000 00000001 01100100
    假如真是:11000000 10101000 00000001 01100100的話。
    我們如果每次再上課的時候要配置該IP地址,記憶起來就比較的麻煩。
    所以,爲了方便表示IP地址,我們就把IP地址的每一個字節上的數據換算成十進制,然後用.分開來表示:
        "點分十進制"
    IP地址的組成:網絡號段+主機號段
        A類:第一號段爲網絡號段+後三段的主機號段
            一個網絡號:256*256*256 = 16777216
        B類:前二號段爲網絡號段+後二段的主機號段
            一個網絡號:256*256 = 65536
        C類:前三號段爲網絡號段+後一段的主機號段
            一個網絡號:256
    IP地址的分類:
        A類  1.0.0.1---127.255.255.254   (1)10.X.X.X是私有地址(私有地址就是在互聯網上不使用,而被用在局域網絡中的地址)                           (2)127.X.X.X是保留地址,用做循環測試用的。
        B類  128.0.0.1---191.255.255.254 172.16.0.0---172.31.255.255是私有地址。169.254.X.X是保留地址。
        C類  192.0.0.1---223.255.255.254 192.168.X.X是私有地址
        D類  224.0.0.1---239.255.255.254     
        E類  240.0.0.1---247.255.255.254
    兩個DOS命令:
        ipconfig 查看本機ip地址
        ping 後面跟ip地址。測試本機與指定的ip地址間的通信是否有問題
    特殊的IP地址:
        127.0.0.1 迴環地址(表示本機)
        x.x.x.255 廣播地址
        x.x.x.0 網絡地址
端口號:
    正在運行的程序的標識。
    有效端口:0~65535,其中0~1024系統使用或保留端口。
協議:
    通信的規則
    UDP:
        把數據打包
        數據有限制
        不建立連接
        速度快
        不可靠
    TCP:
        建立連接通道
        數據無限制
        速度慢
        可靠
    舉例:
        UDP:發短信
        TCP:打電話

1.2 UDP通信編程

 * UDP通信:
 *      將數據源和目的封裝成數據包中,不需要建立連接;
 *      每個數據報的大小在限制在64k;
 *      因無連接,是不可靠協議;
 *      不需要建立連接,速度快.
 * Socket套接字:
 *      網絡上具有唯一標識的IP地址和端口號組合在一起才能構成唯一能識別的標識符套接字.
 * Socket原理機制:
 *      通信的兩端都有Socket;
 *      網絡通信其實就是Socket間的通信;
 *      數據在兩個Socket間通過IO傳輸.
 * UDP通信的步驟:
 *      A:創建DatagramSocket與DatagramPacket類
 *      B:建立發送端,接收端;
 *      C:建立數據包;
 *      D:調用Socket的發送接收方法;
 *      E:關閉Socket;
 *      F:發送端與接收端是兩個獨立的運行程序.
 * DatagramSocket類:此類表示用來發送和接收數據報包的套接字.

案例代碼

/*
 * 使用線程,不斷髮送數據
 */
public class SendData {
    public static void main(String[] args) throws IOException,
            UnknownHostException {
        // 創建發送端對象,綁定到本地的12310端口,不指定端口時,默認使用的本機上可用的端口號
        final DatagramSocket ds = new DatagramSocket(12311);
        // 創建發送數據包
        byte[] bys = new byte[1024];
        // 設定發送到對方的數據,長度,地址,IP地址,端口
        final DatagramPacket dp = new DatagramPacket(bys, bys.length,
                InetAddress.getLocalHost(), 12309);
        new Thread() {
            @Override
            public void run() {
                // 設置數據併發送
                Scanner sc = new Scanner(System.in);
                while(true) {
                    String line = sc.nextLine();
                    if(line.equals("somnus")) {
                        break;
                    }
                    dp.setData(line.getBytes());
                    try {
                        ds.send(dp);
                    } catch (IOException e) {
                        e.printStackTrace();
                    }finally {
                        // 釋放資源
                        // ds.close();
                    }
                }
            }
        }.start();
    }
}

/*
 * 使用線程,不斷接收數據
 */
public class ReceiveData {
    public static void main(String[] args) throws IOException {
        // 創建接收端套接字,綁定到本地的12309端口上
        final DatagramSocket ds = new DatagramSocket(12309);
        // 創建接收數據的套接字
        byte[] bys = new byte[1024];
        final DatagramPacket dp = new DatagramPacket(bys, bys.length);
        // 接收數據並輸出
        new Thread() {
            @Override
            public void run() {
                try {
                    while(true) {
                        ds.receive(dp);
                        System.out.println(dp.getAddress().getHostAddress()+":"+new String(dp.getData(), 0, dp.getLength()));
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }finally {
                    // 釋放資源
                     ds.close();
                }
            }
        }.start();

    }
}

1.3 TCP通信編程

 * TCP通信:
 *      建立連接,形成傳輸數據的通道;
 *      在連接中進行大數據量傳輸;
 *      通過三次握手完成連接,是可靠協議;
 *      必須建立連接,效率會稍低.
 * TCP通信步驟:
 *      A:創建Socket客戶端和ServerSocket服務端對象;
 *      B:建立客戶端和服務器端;
 *      C:建立連接後,通過Socket中的IO流進行數據的傳輸;
 *      D:關閉socket;
 *      E:同樣,客戶端與服務器端是兩個獨立的應用程序.

案例代碼

/*
 * 將文件上傳到服務器,客戶端
 */
public class UpCilent {
    public static void main(String[] args) throws IOException {
        // 獲取文件路徑
        File file = getFile();
        // 將文件名上傳到服務器進行校驗是否存在
        Socket client = new Socket("127.0.0.1", 12306);
        // 創建輸出流對象
        BufferedOutputStream bos = new BufferedOutputStream(client.getOutputStream());
        // 向服務器發送文件名
        String fileName = file.getName();
        bos.write(fileName.getBytes());
        // 將緩衝區的數據刷出
        bos.flush();
        // 創建輸入流對象
        BufferedInputStream bis = new BufferedInputStream(client.getInputStream());
        // 獲取服務器對文件名校驗的結果
        byte[] bys = new  byte[1024];
        int len = bis.read(bys);
        String result = new String(bys, 0, len);
        if("存在".equals(result)) {
            System.out.println("您要上傳的文件已經存在,不能重複上傳!");
            client.close();
            return;
        }
        // 文件不存在,則上傳
        BufferedInputStream bis2 = new BufferedInputStream(new FileInputStream(file));
        while((len = bis2.read(bys)) != -1) {
            bos.write(bys, 0, len);
            bos.flush();
        }
        // 釋放資源
        bis2.close();
        client.close();
    }
    public static File getFile() {
        // 定義鍵盤錄入對象
        Scanner sc = new Scanner(System.in);
        System.out.println("請輸入一個文件的路徑名:");
        while(true) {
            File file = new File(sc.nextLine());
            if(!file.exists()) {
                System.out.println("您輸入的文件路徑不存在,請重新輸入:");
            } else if(file.isDirectory()) {
                System.out.println("您輸入的是文件夾路徑,請輸入文件路徑:");
            } else {
                return file;
            }
        }
    }
}

/*
 * 上傳文件到服務器,服務器端
 */
public class FileServer {
    public static void main(String[] args) throws IOException {
        // 創建服務器socket對象
        ServerSocket server = new ServerSocket(12306);
        // 創建存儲接收客戶端文件的文件夾
        final File update = new File("update");
        if(! update.exists()) {
            update.mkdir();
        }
        // 持續接收客戶端連接
        while(true) {
            final Socket s = server.accept();
            // 創建線程接收客戶端連接
            new Thread() {
                public void run() {
                    try {
                        BufferedInputStream bis = new BufferedInputStream(s.getInputStream());
                        BufferedOutputStream bos = new BufferedOutputStream(s.getOutputStream());
                        byte[] bys = new byte[1024];
                        int len = bis.read(bys);
                        String fileName = new String(bys, 0, len);
                        File file = new File(update, fileName);
                        if(file.exists()) {
                            bos.write("存在".getBytes());
                            bos.flush();
                            // 文件存在,結束程序
                            s.close();
                            return;
                        } else {
                            // 文件不存在則返回標識
                            bos.write("不存在".getBytes());
                            bos.flush();
                        }
                        // 如果文件不存在,則上傳
                        BufferedOutputStream bos2 = new BufferedOutputStream(new FileOutputStream(file));
                        while((len = bis.read(bys)) != -1) {
                            bos2.write(bys, 0, len);
                            bos2.flush();
                        }
                        // 釋放資源
                        bos2.close();
                        s.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }.start();
        }
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章