7.網絡編程

1.網絡模型:
OSI(Open System Interconnection)(開放系統)參考模型
TCP/IP參考模型

網絡參考模型

描述

封包拆包:
這裏寫圖片描述

2.網絡通訊要素L:
IP地址
端口號
傳輸協議

3.IP地址:
網絡中設備的標識
不易記憶,可用主機名
本地迴環地址:127.0.0.1,用來訪問本機測試網卡。
主機默認名:localhost

4.端口:
用於有效標識進程的邏輯地址,不同進程的標識不同。
有效端口:0~65535,其中0~1024系統使用或保留端口。

這裏寫圖片描述

5.傳輸協議:
通訊的規則
常見協議:
TCP(傳輸控制協議):打電話,下載文件,QQ文件在線發送
UDP(數據報文協議):對講機,QQ文件離線發送

這裏寫圖片描述

6.IP對象:InetAddress

public class IPDemo {

    public static void main(String[] args) throws UnknownHostException {

        //獲取本地主機ip的地址對象
        InetAddress ip = InetAddress.getLocalHost();


        //獲取其他主機的ip地址對象
//      ip = InetAddress.getByName("coy");
//      ip = InetAddress.getByName("100.64.172.141");
        ip = InetAddress.getByName("www.baidu.com");


        //獲取本地主機的ip地址和主機名
        System.out.println(ip.getHostAddress());
        System.out.println(ip.getHostName());
    }


/*
180.97.33.107
www.baidu.com
*/

7.域名解析:
DNS:域名解析器(互聯網公共主機服務器)

這裏寫圖片描述

配置本地域名解析列表:
C:\Windows\System32\drivers\etc

系統域名解析 先找的是 本地域名解析文件。
(可以把一些遊戲廣告網站域名在本地解析成本機迴環地址127.0.0.1,不進行訪問,過濾垃圾網站)

8.Socket :

1.Socket就通訊的兩端,爲網絡服務提供的一種機制(兩個港口)
2.通信的兩端都有Socket
3.網絡編程就是Socket編程
4.網絡通信其實就是Socket間的通信
5.數據在兩個Socket間通過IO傳輸

9.UDP協議

1.DatagramSocket,DatagramPacket
2.建立發送端,接收端
3.建立數據包
4.調用Socket的發生接收方法
5.關閉Socket
發送端和接收端是兩個獨立的運行程序。

發送端:

public class UDPSendDemo {

    public static void main(String[] args) throws IOException {

        /*
                創建UDP傳輸的發送端。
                思路:
                1.建立UDP的socket服務
                2.將要發送的數據封裝到數據包中。
                3.通過UDP的socket服務將數據包發送出去。
                4.關閉socket服務。
         */
        System.out.println("發送端啓動...");
        //1.UDPsocket服務。使用DatagramSocket對象
        DatagramSocket ds = new DatagramSocket();

        //2.將要發送的數據封裝到數據包中。
        String str = "udp傳輸演示:哈哈";
        byte[] buf = str.getBytes();
        DatagramPacket dp = new DatagramPacket(buf,buf.length,InetAddress.getByName("coy"),10000);

        //3.通過UDP的socket服務將數據包發送出去。使用send方法。
        ds.send(dp);

        //4.關閉資源。
        ds.close();
    }

}

接收端:

public class UDPReceDemo {

    public static void main(String[] args) throws IOException {

        /*
                建立UDP接收端的思路
                1.建立UDP的socket服務
                2.創建數據包。用於存儲接收到的數據。方便用數據包對象的方法解析這些數據。
                3.使用Socket服務的receive方法將接收的數據存儲到數據包中。
                4.通過數據包的方法解析數據包中的數據。
                5.關閉資源。
         */
        System.out.println("接收端啓動...");

        //1.建立UDP的socket服務
        DatagramSocket ds = new DatagramSocket(10000);

        //2.創建數據包
        byte[] buf  = new byte[1024];
        DatagramPacket dp = new DatagramPacket(buf,buf.length);

        //3.使用接收方法將數據存儲到數據包中。
        ds.receive(dp);    //阻塞式的

        //4.通過數據包對象的方法,解析其中的數據,比如,地址,端口,數據內容。
        String ip = dp.getAddress().getHostAddress();
        int port = dp.getPort();
        String text = new String(dp.getData(),0,dp.getLength());

        System.out.println(ip+ ":" + port + ":" + text);

        //5.關閉資源
        ds.close();


    }

}

10.TCP傳輸:

1.Socket,ServerSocket
2.建立客戶端和服務端
3.建立連接後,通過Socket中的IO流進行數據的傳輸。
4.關閉socket

同樣,客戶端和服務端是兩個獨立的應用程序。

這裏寫圖片描述

客戶端:

public class TCPClientDemo {

    public static void main(String[] args) throws UnknownHostException, IOException {

        //客戶端發數據到服務端
        /*
                TCP傳輸:客戶端建立的過程
                1.創建tcp客戶端socket服務。使用的是Socket對象。
                    建議該對象一創建就明確目的地。要連接的主機。
                2.  如果連接建立成功,說明數據傳輸通道已建立。
                    該通道就是socket流,是底層建立好的。既然是流,說明這裏既有輸入,也有輸出。
                    通過Socket來獲取輸入或輸出流對象。
                    可以通過getOutputStream(),和getInputStream()來獲取兩個字節流。
                3.使用輸出流,將數據寫出。
                4.關閉資源。


         */

        //創建客戶端socket服務
        Socket socket = new Socket("coy",10002);

        //獲取socket流中的輸出流
        OutputStream out = socket.getOutputStream();

        //使用輸出流將指定的數據寫出去
        out.write("哈哈".getBytes());

        //讀取服務端返回的數據,使用socket讀取流。
        InputStream in = socket.getInputStream();
        byte[] buf = new byte[1024];

        int len = in.read(buf);

        String text = new String(buf,0,len);
        System.out.println(text);

        //關閉資源
        socket.close();

    }

}

服務端:

public class TCPServerDemo {

    public static void main(String[] args) throws IOException {

        //服務端接收客戶端發送過來的數據,並打印在控制檯上。
        /*
                    建立TCP服務端的思路:
                1.創建服務端的socket服務。通過ServerSocket對象。
                    服務端必須對外提供一個端口,否者客戶端無法連接。
                2.獲取連接過來的客戶端對象
                3.通過客戶端對象獲取socket流讀取客戶端發來的數據
                並打印在控制檯上。
                4.關閉資源。關客戶端,服務端。


         */

        //1.創建服務器對象
        ServerSocket ss = new ServerSocket(10002);

        //2.獲取連接過來的客戶端對象。
        Socket s = ss.accept();//阻塞式
        String ip = s.getInetAddress().getHostAddress();

        //3.通過socket對象獲取輸入流,要讀取客戶端發來的數據
            InputStream in = s.getInputStream();

            byte[] buf = new byte[1024];
            int len = in.read(buf);
            String text = new String(buf,0,len);

            System.out.println(ip+": "+ text);
                //使用客戶端的socket對象的輸出流給給客戶端返回數據。
            OutputStream out = s.getOutputStream();

            out.write("收到".getBytes());

            s.close();
            ss.close();   //服務端一般不關


    }

}

示例:大寫轉換服務器:

public class TransClient {

    public static void main(String[] args) throws UnknownHostException, IOException {

        /*
                思路:
                客戶端:
                1.現有socket端點
                2.客戶端的數據源:鍵盤
                3.客戶端的目的:socket
                4.接收服務端的數據,源:socket
                5.將數據打印出來:目的:控制檯
                6.在這些流中操作的數據都是文本數據。

                轉換客戶端:
                1.創建socket客戶端對象
                2.獲取鍵盤錄入
                3.將錄入的信息發送給socket輸出流
                4.socket輸入流讀取服務端返回的大寫數據
                5.將接收到的服務端數據打印到控制檯
         */

        //1.創建socket客戶端對象
        Socket s = new Socket("100.64.190.224",10001);

        //2.獲取鍵盤錄入
        BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in));

        //3.socket輸出流
//      BufferedWriter bufw = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
        PrintWriter out = new PrintWriter(s.getOutputStream(),true);  //自動刷新

        //4.socket輸入流:讀取服務端返回的大寫數據
        BufferedReader bufIn = new BufferedReader(new InputStreamReader(s.getInputStream()));

        String line = null;

        while((line = bufr.readLine())!=null){
            if("over".equals(line))
                break;

            out.println(line);

            //4.讀取服務端返回的一行大寫數據
            String upperStr = bufIn.readLine();      
            System.out.println(upperStr);       
        }


         s.close();

    }

}



public class TransServer {

    public static void main(String[] args) throws IOException {

        /*
                轉換服務端:

                分析:
                1.serversocket服務
                2.獲取socket對象
                3.讀取客戶端發過來的需要轉換的數據,源:socket
                4.目的:顯示在控制檯上
                5.將數據轉成大寫發給客戶端。目的:socket

         */

        //1.
        ServerSocket ss = new ServerSocket(10001);      
        //2.
        Socket s = ss.accept();  //阻塞
        //3.獲取socket讀取流,並裝飾
        BufferedReader bufr = new BufferedReader(new InputStreamReader(s.getInputStream()));

        //獲取ip:
            String ip = s.getInetAddress().getHostAddress();
            System.out.println(ip+".......connected");

        //4.獲取socket輸出流,並裝飾。將大寫數據返回給客戶端
        PrintWriter out = new PrintWriter(s.getOutputStream(),true);  //自動刷新

        String line = null;
        while((line = bufr.readLine())!= null)
        {
            System.out.println("收到信息:" + line); 


            //將大寫數據返回給客戶端
            out.println(line.toUpperCase());
        }

        s.close();
        ss.close();



    }

}

示例:上傳文本文件。

//客戶端
public class TransClient {

    public static void main(String[] args) throws UnknownHostException, IOException {


        //1.創建socket客戶端對象
        Socket s = new Socket("100.64.190.224",10001);
        System.out.println("成功連接服務器: 100.64.190.224    端口號:10001");
        //2.獲取文件讀取流。並裝飾
        File file = new File("上傳文件.txt");
        if(!file.exists()){
            System.out.println("文件不存在,無法上傳!");
            s.close();
            System.exit(0);
        }
        BufferedReader bufr = new BufferedReader(new FileReader(file));
        System.out.println("正在上傳文本文件"+file.getName());
        //3.socket輸出流
//      BufferedWriter bufw = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
        PrintWriter out = new PrintWriter(s.getOutputStream(),true);  //自動刷新

        //4.socket輸入流:讀取服務端返回的上傳標誌
        BufferedReader bufIn = new BufferedReader(new InputStreamReader(s.getInputStream()));

        String line = null;

        while((line = bufr.readLine())!=null){          

            out.println(line);

        }
        //告訴服務端:客戶端寫完了
            s.shutdownOutput();
        //4.讀取服務端返回的上傳成功標誌
        System.out.println(bufIn.readLine());       

        bufr.close();
         s.close();

    }

}




//服務端
public class TransServer {

    public static void main(String[] args) throws IOException {



        //1.
        ServerSocket ss = new ServerSocket(10001);      
        //2.
        Socket s = ss.accept();  //阻塞
        //3.獲取socket讀取流,並裝飾
        BufferedReader bufr = new BufferedReader(new InputStreamReader(s.getInputStream()));
        //獲取ip:
        String ip = s.getInetAddress().getHostAddress();
        System.out.println(ip+".......connected");


        //獲取文件輸入流,並裝飾
        File file = new File("服務端接收文件.txt");
        BufferedWriter bufw = new BufferedWriter(new FileWriter(file));
            System.out.println("正在接收 "+ip+"發來的文本文件...");

        //4.獲取socket輸出流,並裝飾。將上傳標誌返回給客戶端
        PrintWriter out = new PrintWriter(s.getOutputStream(),true);  //自動刷新

        String line = null;
        while((line = bufr.readLine())!= null)
        {           
            bufw.write(line);
            bufw.newLine();
            bufw.flush();
        }
        //將上傳標誌返回給客戶端
        System.out.println("接收成功!保存至"+file.getAbsolutePath());
        out.println("上傳成功!");

        bufw.close();
        s.close();
        ss.close();



    }

}

示例:上傳圖片

public class TransClient {

    public static void main(String[] args) throws UnknownHostException, IOException {
//客戶端

        //1.創建socket客戶端對象
        Socket s = new Socket("100.64.190.224",10001);
        System.out.println("成功連接服務器: 100.64.190.224    端口號:10001");

        //2.讀取客戶端要上傳的圖片。
        File file = new File("動畫短片《某人的目光》新海誠.flv");     
        FileInputStream fis =  new FileInputStream(file);
        System.out.println("正在上傳圖片"+file.getName());

        //3.獲取socket輸出流,將讀到的圖片數據發送給服務端      
        OutputStream out = s.getOutputStream();  

        int len = 0;
        byte[] buf = new byte[1024];
        while((len = fis.read(buf))!=-1){                       
            out.write(buf,0,len);           
        }
        //告訴服務端:這邊的數據發送完畢。讓服務端停止讀取
            s.shutdownOutput();

    //4.socket輸入流:讀取服務端返回的上傳標誌
        BufferedReader bufIn = new BufferedReader(new InputStreamReader(s.getInputStream()));           
        System.out.println(bufIn.readLine());       

        fis.close();
         s.close();

    }

}


public class TransServer {

    public static void main(String[] args) throws IOException {
//服務端
        //1.創建tcp的socket服務端
        ServerSocket ss = new ServerSocket(10001);      

        //2.獲取客戶端
        Socket s = ss.accept();  //阻塞

        //3.讀取客戶端發來的數據
        InputStream ins = s.getInputStream();

            //獲取ip:
        String ip = s.getInetAddress().getHostAddress();
        System.out.println(ip+".......connected");

        System.out.println("正在接收 "+ip+"發來的文本文件...");

        //4.將讀取到的數據存儲到一個文件中
        File file = new File("服務端接收動畫短片《某人的目光》新海誠.flv");
        FileOutputStream fos =new FileOutputStream(file);

        int len = 0;
        byte[] buf =new byte[1024];

        while((len = ins.read(buf))!= -1)
        {           
            fos.write(buf, 0, len);         
        }

        System.out.println("接收成功!保存至"+file.getAbsolutePath());

        //5.獲取socket輸出流。將上傳標誌返回給客戶端
        PrintWriter out = new PrintWriter(s.getOutputStream(),true);  
        out.println("上傳成功!");

        fos.close();
        s.close();
        ss.close();



    }

}

11.服務端多線程:

public class TransClient {

    public static void main(String[] args) throws UnknownHostException, IOException {
//客戶端




            //1.創建socket客戶端對象
            Socket s = new Socket("100.64.190.224",10001);
            System.out.println("成功連接服務器: 100.64.190.224    端口號:10001");
        //2.讀取客戶端要上傳的圖片。
        File file = new File("秒速五釐米(Av4433361,P1).flv");        
        FileInputStream fis =  new FileInputStream(file);
        System.out.println("正在上傳:"+file.getName());

        //3.獲取socket輸出流,將讀到的圖片數據發送給服務端      
        OutputStream out = s.getOutputStream();  

        int len = 0;
        byte[] buf = new byte[1024];
        while((len = fis.read(buf))!=-1){                       
            out.write(buf,0,len);           
        }
        //告訴服務端:這邊的數據發送完畢。讓服務端停止讀取
            s.shutdownOutput();

    //4.socket輸入流:讀取服務端返回的上傳標誌
        BufferedReader bufIn = new BufferedReader(new InputStreamReader(s.getInputStream()));           
        System.out.println(bufIn.readLine());       

        fis.close();
        s.close();



    }

}




public class TransServer {

    public static void main(String[] args) throws IOException {
//服務端多線程
        //1.創建tcp的socket服務端
        ServerSocket ss = new ServerSocket(10001);      


        while(true){

        //2.獲取客戶端
        Socket s = ss.accept();  //阻塞   

        new Thread(new Task(s)).start();

            }

    }

}



public class Task implements Runnable {
    private Socket s;
    public Task(Socket s){
        this.s = s;
    }
    @Override
    public void run() {
        int count = 0;


        try{        

        //3.讀取客戶端發來的數據
                InputStream ins = s.getInputStream();

                    //獲取ip:
                String ip = s.getInetAddress().getHostAddress();
                System.out.println(ip+".......connected");

                //4.將讀取到的數據存儲到一個文件中
                File file = new File(ip+".jpg");
                while(file.exists()){
                    file = new File(ip+"("+(++count)+")"+".jpg");
                }

                FileOutputStream fos =new FileOutputStream(file);

                int len = 0;
                byte[] buf =new byte[1024];

                while((len = ins.read(buf))!= -1)
                {           
                    fos.write(buf, 0, len);         
                }

                System.out.println(file.getName()+"接收成功!");

                //5.獲取socket輸出流。將上傳標誌返回給客戶端
                PrintWriter out = new PrintWriter(s.getOutputStream(),true);  
                out.println(file.getName()+"上傳成功!");

                fos.close();
                s.close();
        }catch(IOException e){

        }

    }

}

12.常見客戶端和服務端

最常見的客戶端:
    瀏覽器:IE
最常見的服務端:
    web服務器:Tomcat

ip 網際層規則
TCP/UDP 傳輸層規則
http:// 應用層規則

這裏寫圖片描述

13.客戶端和服務端(瀏覽器)原理:

1.自定義服務端
使用已有的客戶端IE,瞭解一下客戶端給服務端發了說明請求。

public class IEServer {

    public static void main(String[] args) throws IOException {

        ServerSocket ss = new ServerSocket(9090);

        Socket s = ss.accept();
        System.out.println(s.getInetAddress().getHostAddress()+"......connected");

        InputStream in = s.getInputStream();   //接收客戶端的請求

        byte[] buf = new byte[1024];
        int len = in.read(buf);
        String text = new String(buf,0,len);        
        System.out.println(text);

        //客戶端一個返回信息
        PrintWriter out = new PrintWriter(s.getOutputStream(),true);

        out.println("<font color='red' size='7'>歡迎光臨</font>");
        s.close();
        ss.close();

    }

}

服務端接收到 客戶端的請求顯示:
請求行(請求方式(GET,POST)/請求的資源路徑(這裏沒有請求資源)   http協議版本/1.01.1)
GET / HTTP/1.1 

請求消息頭:屬性名:屬性值 (就是一些規則,告訴服務端,客戶端能處理解析的內容,語言,)
Accept: text/html, application/xhtml+xml, image/jxr, */*   //支持的解析內容  
Accept-Language: zh-CN   //支持的語言
Accept-Encoding: gzip, deflate  //支持的解壓縮方式(服務端將數據壓縮發送過來)
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; rv:11.0) like Gecko//瀏覽器版本信息(QQ空間ie版本過低提示)
Host: 100.64.190.224:9090//客戶端的主機(因爲ip是不變的,但是主機名是可修改的,爲了確定哪一個主機)
//Host: www.houyouni.com:9090  
Connection: Keep-Alive  //保持存活,close保持關閉

請求頭和請求體之間必須有個空行
//請求體:自定義的信息。

客戶端發出請求後得到的反饋:
這裏寫圖片描述

2.模擬一個瀏覽器獲取信息:
瀏覽器請求過程:
這裏寫圖片描述

public class IEClient {

    public static void main(String[] args) throws UnknownHostException, IOException {
        Socket s = new Socket("100.64.190.224",8080);

        //模擬瀏覽器,給tomcat服務端發送符合http協議的請求消息。

        PrintWriter out  = new PrintWriter(s.getOutputStream(),true);
        out.println("GET /myweb/1.html HTTP/1.1");
        out.println("Accept: */*");
        out.println("Host: 100.64.190.224:8080");
        out.println("Connection:close");
        out.println();


        InputStream in = s.getInputStream();

        byte[] buf = new byte[1024];
        int len = in.read(buf);

        String str = new String(buf,0,len);
        System.out.println(str);


        s.close();

    }

}


顯示:

//服務器發回的應答消息。
應答行:http的協議版本 應答狀態碼 應答狀態描述信息   200:成功  404:找不到頁面
HTTP/1.1 200 OK   

//應答消息頭(屬性信息): 屬性名:屬性值(因爲自定義的瀏覽器沒有http解析器,所以應答行和消息頭也打印出來了。可以用URL類的openStream()方法直接獲得該URL連接的讀入流InputStream。然後直接讀入消息體。)
Accept-Ranges: bytes    
ETag: W/"42-1509883856548"
Last-Modified: Sun, 05 Nov 2017 12:10:56 GMT  //最後一次修改的事件
Content-Type: text/html  //數據類型
Content-Length: 42  //字節數
Date: Sun, 05 Nov 2017 12:14:16 GMT
Connection: close   //連接關閉
//空行
//應答消息體
<font color='red' size='7'>歡迎光臨</font>

14.URL解析

1.獲取url的信息。
String str_url = "http://100.64.190.224:8080/myweb/1.html?name=lisi";
URL url = new URL(str_url);

syso("Protocol:"url.getProtocol()); //協議
syso("getHost:"url.getHost());  //主機ip
syso("getPort:"url.getPort());  //端口
syso("getFile:"url.getFile());  //文件信息(路徑+參數信息)
syso("getPath:"url.getPath());  //路經
syso("getQuery:"url.getQuery());  //參數信息

2.
InputStream openStream() 
          打開到此 URL 的連接並返回一個用於從該連接讀入的 InputStream。 
    此方法是下面方法的縮寫: 
       openConnection().getInputStream()

//只打印消息體:
InputStream in = url.openStream();
//原理:
//URLConnection conn = url.openConnection();
//InputStream in = conn.getInputStream();

    獲得url連接器對象,解析具體的協議,可獲取連接器對象的socket輸入輸出流:
    //獲取url對象的url連接器對象。將連接封裝成了對象:java中內置的可以解析的具體協議的對象+socket
    //URLConnection conn = url.openConnection();
    //syso(conn);
    //sun.net.www.protocol.http.HttpURLConnection:http://100.64.190.224:8080/myweb/1.htm
l?name=lisi
    //conn.getHeaderField("Content-Type");  // text/html

byte[] buf = new byte[1024];
int len = in.read(buf);

String text = new String(buf,0,len);

syso(text);

in.close();

URL解析代替Socket連接服務端:

public class IEClient {

    public static void main(String[] args) throws UnknownHostException, IOException {
        String str_url = "http://100.64.190.224:8080/myweb/1.html";
        URL url = new URL(str_url);

        URLConnection conn = url.openConnection();



        //模擬瀏覽器,給tomcat服務端發送符合http協議的請求消息。

        PrintWriter out  = new PrintWriter(conn.getOutputStream(),true);
        out.println("GET /myweb/1.html HTTP/1.1");
        out.println("Accept: */*");
        out.println("Host: 100.64.190.224:8080");
        out.println("Connection:close");
        out.println();

        InputStream in = conn.getInputStream();

        byte[] buf = new byte[1024];
        int len = in.read(buf);

        String str = new String(buf,0,len);
        System.out.println(str);

        in.close();

    }

}

15.常見網絡結構:

1.C/S: client/server
    優點:
        該結構的軟件,客戶端和服務端都需要編寫。
        開發成本較高,維護較爲麻煩。
    好處:
        客戶端在本地可以分擔一部分運算。    


2.B/S: browser/server(javaweb)
    優點:
        該結構的軟件,只開發服務器端,不開發客戶端,因爲客戶端直接由瀏覽器取代。
        開發成本相對低,維護更爲簡單。
    缺點:所有運算都在服務器端完成。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章