天天看點

Java學習記錄 Day20(網絡程式設計)

文章目錄

  • ​​Day 20​​
  • ​​計算機網絡​​
  • ​​網絡程式設計​​

Day 20

2019年5月26日。

這是我學習Java的第二十天。

這一天,我學到了以下的知識。

計算機網絡

計算機網絡,就是把分布在不同地理區域的計算機與專門的外部裝置用通信線路互連成一個規模大,功能強的網絡系統,進而使衆多的計算機可以友善的互相傳遞資訊,共享硬體,軟體,資料資訊等資源。

其中,具有以下重要概念:

  • 計算機網絡的主要功能:

    - 資源共享

    - 資訊傳輸與集中處理

    - 均衡負荷與分布處理

    - 綜合資訊服務(www / ISDN絡 ISDN)

  • 網絡通信協定:​ 計算機網絡中實作通信必須有一些約定,即通信協定;對速率,傳輸代碼,代碼結構,傳輸控制步驟,出錯控制等制定标準。
  • 網絡通信接口:​ ​ 為了使兩個節點之間能進行對話,必須在他們之間建立通信工具(即接口),使彼此之間,能進行資訊交換。接口包括兩個部分:

    - 硬體裝置:實作結點之間的資訊傳送

    - 軟體裝置:規定雙方進行通信的約定協定

  • 分層思想:​ ​ 由于結點之間聯系很複雜,在制定協定時,把複雜成份分解成一些簡單的成份,再将它們複合起來。最常用的複合方式就是層次方式,及同層間可以通信,上一層可以調用下一層,而與再下一層不發生關系。各層互不影響,利于系統的開發和擴充。
  • 參考模型:分為OSI參考模型和TCP/IP參考模型,原理圖如下所示:
  • Java學習記錄 Day20(網絡程式設計)
  • IP協定: 每個人的電腦都有一個獨一無二的IP位址,這樣互相通信時就不會傳錯資訊了。​IP位址是用一個點來分成四段的,在計算機内部IP位址是用四個位元組來表示的,一個位元組代表一段,每一個位元組代表的數最大隻能到達255,原理圖如下所示:
  • Java學習記錄 Day20(網絡程式設計)
  • 通信方式:TCP和UDP位于同一層,都是建立在IP層的基礎之上。由于兩台電腦之間有不同的IP位址,是以兩台電腦就可以區分開來,也就可以互相通話了。通話一般有兩種通話方式:第一種是TCP,第二種是UDP。

    - TCP(Transmission Control Protocol 傳輸控制協定):TCP就像打電話,需要先打通對方電話,等待對方有回應後才會跟對方繼續說話,也就是一定要确認可以發資訊以後才會把資訊發出去。TCP上傳任何東西都是可靠的,隻要兩台機器上建立起了連接配接,在本機上發送的資料就一定能傳到對方的機器上。

    - UDP(User Datagram Protocol 使用者資料報協定):UDP就好比發電報,發出去就完事了,對方有沒有接收到它都不管,是以UDP是不可靠的。

    TCP傳送資料雖然可靠,但傳送得比較慢,UDP傳送資料不可靠,但是傳送得快。

  • Socket:兩台電腦都安裝上一個插座,然後使用一根線的兩端插到兩台電腦的插座上,這樣兩台電腦就建立好了連接配接。這個插座就是Socket。
  • Server(伺服器端)和Client(用戶端): 因為互相之間都能互相通信,我說你是我的Server隻是從邏輯意義上來講,我應該把東西先發到你那裡去,然後由你來處理,轉發。是以你叫Server。但從技術意義上來講,隻有TCP才會分Server和Client。對于UDP來說,從嚴格意義上來講,并沒有所謂的Server和Client。TCP的Server的插座就叫ServerSocket,Client的插座就叫Socket。原理圖如下所示:
  • Java學習記錄 Day20(網絡程式設計)
  • 端口号:兩台計算機互相連接配接,那麼首先必須得知道它們的IP位址,但是隻提供IP位址是不夠的,還必須要有連接配接的端口号,也就是要連接配接到哪個應用程式上。端口号是用來區分一台機器上不同的應用程式的。端口号在計算機内部是占2個位元組。一台機器上最多有65536個端口号。一個應用程式可以占用多個端口号。端口号如果被一個應用程式占用了,那麼其他的應用程式就無法再使用這個端口号了。記住一點,我們編寫的程式要占用端口号的話占用1024以上的端口号,1024以下的端口号不要去占用,因為系統有可能會随時征用。端口号本身又分為TCP端口和UDP端口,TCP的8888端口和UDP的8888端口是完全不同的兩個端口。TCP端口和UDP端口都有65536個。

網絡程式設計

網絡程式設計,在Java中根據通信方式分為兩種:

  • UDP程式設計

    核心類為DatagramSocket和DatagramPacket,原理圖如下所示:

  • Java學習記錄 Day20(網絡程式設計)
  • 代碼範例如下:

    1.用戶端

public class Client {
public static void main(String[] args) throws IOException {
    //1 指定端口 DatagramSocket
    DatagramSocket socket = new DatagramSocket();

    //2 指定一個IP
    InetAddress addr = InetAddress.getByName("127.0.0.1");
    int port = 5051;

    //3 準備一個容器
    byte[] sendBuf = new byte[1024];
    while (true){
        Scanner scanner = new Scanner(System.in);
        System.out.println("發送什麼?");
        String s = scanner.nextLine();
        //4 加入要放的資料
        sendBuf = s.getBytes();

        //5 資料打包
        DatagramPacket packet = new DatagramPacket(sendBuf,sendBuf.length,addr,port);

        //6 發送包
        socket.send(packet);

        if (s.equals("exit")){
            break;
        }
    }

    //7.釋放資源
    socket.close();
}
}      

2.伺服器端

public class Server {
    public static void main(String[] args) throws IOException {
        //1 指定端口 DatagramSocket
        DatagramSocket socket = new DatagramSocket(5051);

        //2 準備一個容器,封包 DatagramPacket
        byte[] receiveBuf = new byte[1024];

        //3 等待接收包 receive()
        DatagramPacket packet = new DatagramPacket(receiveBuf,receiveBuf.length);
        System.out.println("等待包......");
        while (true){
            //4 接收包
            socket.receive(packet);

            //5.解析包
            String receStr = new String(packet.getData(),0,packet.getLength());
            System.out.println("我收到的資料:" + receStr);
            if (receStr.equals("exit")){
                break;
            }
        }

        //6 釋放資源
        socket.close();
    }
}      
  • TCP程式設計

    核心類為ServerSocket和Socket,原理圖如下所示:

  • 代碼範例如下:

    1.用戶端

public class Client{
public static void main(String args[]) throws Exception{
    Socket s = new Socket("127.0.0.1",6666);
    /*Client申請連接配接到Server端上*/
    /*連接配接上伺服器端以後,就可以向伺服器端輸出資訊和接收從伺服器端傳回的資訊
    輸出資訊和接收傳回資訊都要使用流式的輸入輸出原理進行資訊的處理*/
    /*這裡是使用輸出流OutputStream向伺服器端輸出資訊*/
    OutputStream os = s.getOutputStream();
    DataOutputStream dos = new DataOutputStream(os);
    Thread.sleep(30000);/*用戶端睡眠30秒後再向伺服器端發送資訊*/
    dos.writeUTF("Hello Server!");
}
}      
public class Server{
    public static void main(String args[]) throws Exception{
        ServerSocket ss = new ServerSocket(6666);
        /*建立一個ServerSocket對象時往往會給它指定一個端口号
                指定端口号的意思是這個new出來的ServerSocket對象要使用的
                是哪一個端口号,通過哪一個端口号來監聽用戶端的連接配接
                是以指定一個端口号的意義就是為了告訴計算機ServerSocket對象
                在哪個地方監聽用戶端的連接配接*/
        /*伺服器端接收用戶端連接配接的請求是不間斷地接收的,是以伺服器端的
                程式設計一般都是死循環,永不休止地運作着。*/
        while(true){
            Socket s = ss.accept();
            /*在伺服器端調用accept()方法接受用戶端的連接配接對象,accept()方法是
                            一個阻塞式方法,一直在傻傻地等待着是否有用戶端申請連接配接上來
                            然後伺服器端的Socket插座就和用戶端的Socket插座建立了連接配接了*/
            /*用戶端能否連接配接上伺服器端,取決于伺服器端是否接受用戶端的連接配接請求
                            如果接受了用戶端的連接配接請求,那麼在伺服器端就安裝上一個Socket插座
                            通過這個插座與連接配接上的用戶端就可以建立連接配接,互相通信了*/
            System.out.println("A Client Connected!");
            /*使用InputStream流接收從用戶端發送過來的資訊,使用DataInputStream資料流處理接收到的資訊*/
            DataInputStream dis = new DataInputStream(s.getInputStream());
            /*使用readUTF(方法将接收到的資訊全部讀取出來,存儲到變量str裡面
                            readUTF()方法也是一個阻塞式方法,會傻傻地等待用戶端發送資訊過來,然後将接收到的資訊讀取出來
                            如果用戶端不寫東西過來,它就一直在伺服器端傻傻地等待着,直到用戶端寫東西過來為止
                            堵塞式的方法效率往往是不高的,比如說一個用戶端連接配接上來了,但是它遲遲不發送資訊,
                            那麼伺服器端的程式就阻塞住了,這樣另外一個用戶端就連接配接不上來了,因為另外一個用戶端要想連接配接
                            上伺服器端,就必須得在伺服器端調用accept()方法,可accept()方法必須得在下一次循環時才能夠被
                            調用,現在伺服器端的程式運作到調用readUTF()這個方法時就阻塞住了,它要等待着已經連接配接上來的
                            那個用戶端發送資訊過來後将資訊讀取出來,如果用戶端一直不發資訊到伺服器端,那麼readUTF()方法
                            就一直無法讀取到資訊,那麼伺服器端的程式會阻塞在這裡,無法進行下次循環,這樣其他的用戶端就
                            無法連接配接到伺服器端了*/
            String str = dis.readUTF();
            System.out.println(str);
        }
    }
}