1. 程式人生 > 其它 >14. 網路程式設計

14. 網路程式設計

一、網路基礎

  計算機網路把分佈在不同地理區域的計算機與專門的外部裝置用通訊線路互聯成一個規模大、功能強的網路系統,從而使眾多的計算機可以方便的互相傳遞資訊、共享硬體、軟體、資料資訊等資源。網路程式設計直接或間接地通過網路協議與其它計算機實現資料交換,進行通訊。

OSI參考模型 TCP/IP參考模型 TCP/IP參考模型各層對應協議
應用層 應用層 HTTP、FTP、Telnet、DNS……
表示層
會話層
傳輸層 傳輸層 TCP、UDP……
網路層 網路層 IP、ICMP、ARP……
資料鏈路層 物理+資料鏈路層 Link
物理層

二、網路通訊要素

2.1、IP和埠號

  • IP地址:InetAddress
    • 唯一的標識Internet上的計算機(通訊實體)
    • 本地迴環地址(hosAddress):127.0.0.1 主機名(hostName):localLost
    • IP地址分類方式1:IPV4 和 IPV6
      • IPV4:4個位元組組成,4個0~255.大概42億,其中30億大概在北美,亞洲4億。2011年已經用盡。以點分十進位制表示
      • IPV6:128位(16個位元組),寫成8個無符號整數,每個整數用四個十六進位制位標識,數之間用冒號分開
    • IP地址分類方式2:公網地址(全球資訊網使用)和私有地址(區域網使用)
      • 192.168.開頭的就是私有地址,範圍即為192.168.0.0 ~ 192.168.255.255,專門位組織機構內部使用
  • 埠號:標識正在計算機上執行的程序(程式)
    • 不同的程序有不同的埠號
    • 被規定為 16 位的整數 0~65535
    • 埠分類:
      • 公認埠:0~1023。被預先定義的服務通訊佔用
      • 註冊埠:1024~49151。分配給使用者程序或應用程式
      • 動態/私有埠:49152~65535
  • 埠號與IP地址的組合得出一個網路套接字:Socket

2.2、網路協議

  計算機網路中實現通訊必須有一些規定,即通訊協議,對速率、傳輸程式碼、程式碼結構、傳輸控制步驟、出錯控制等指定標準。在指定協議時,把複雜成份分解成一些簡單的份,在將它們複合起來。最常用的複合方式是層次方式,即 同層間可以通訊、上一層可以呼叫下一層,而與下一層不發生關係。各層互不影響,利於系統的開發和擴充套件。

2.2.1、TCP/IP協議簇

  • 傳輸層協議中有兩個重要的協議:
    • 傳輸控制協議TCP(Transmission Control Protocol)
      • 使用TCP協議前,須建立TCP連線,形成傳輸資料通道
      • 傳輸前,採用“三次握手”的方式,點對點通訊、是可靠的
      • TCP協議進行通訊的兩個應用程序:客戶端、服務端
      • 在連線中可進行大資料量的傳輸
      • 傳輸完畢,需釋放已建立的連線,效率低
    • 使用者資料報協議UDP(User Datagram Protocol)
      • 將資料、源、目的封裝成資料包,不需要建立連線
      • 每個資料包的大小限制在64K內
      • 傳送不斷對方是否準備好,接收方收到也不確認,故是不可靠的
      • 可以廣播發送
      • 傳送資料結束時無需釋放資源,開銷小,速度快
  • 網路互聯協議IP(Internet Protocol)是網路層的組要協議,支援網間互聯的資料通訊
  • TCP/IP協議模型從更使用的角度出發,形成了高效的四層體系結構,即 物理鏈路層IP層傳輸層控制層

2.2.2、TCP網路程式設計例程

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;

//服務端
public class Server {
    public static void main(String[] args) {
        ServerSocket serverSocket = null;
        Socket socket = null;
        InputStream inputStream = null;
        ByteArrayOutputStream bArrayOutputStream = null;

        try {
            //1.建立伺服器端的ServerSocket,指明自己的埠號
            serverSocket = new ServerSocket(55530);
            //2.呼叫accept()表示接收來自於客戶端的socket
            socket = serverSocket.accept();
            //3.獲取輸入流
            inputStream = socket.getInputStream();

            //4.讀取輸入流中的資料
            bArrayOutputStream = new ByteArrayOutputStream();
            byte[] buffer = new byte[5];
            int len;
            while((len = inputStream.read(buffer)) != -1){
                bArrayOutputStream.write(buffer, 0, len);
            }
            System.out.println("收到來自於" + socket.getInetAddress().getHostAddress() + "的資料");
            System.out.println(bArrayOutputStream.toString());
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //5.關閉資源
            if(inputStream != null){
                try {
                    inputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if(bArrayOutputStream != null){
                try {
                    bArrayOutputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if(socket != null){
                try {
                    socket.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if(serverSocket != null){
                try {
                    serverSocket.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}
import java.io.IOException;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.Socket;

//客戶端
public class Client {
    public static void main(String[] args) {
        InetAddress inetAddress = null;
        Socket socket = null;
        OutputStream outputStream  = null;

        try {
            //1.建立Scoket物件,指明伺服器的ip和埠號
            inetAddress = InetAddress.getByName("127.0.0.1");
            socket = new Socket(inetAddress, 55530);

            //2.獲取一個輸出流,用於輸出資料
            outputStream = socket.getOutputStream();
            //3.寫出資料的操作
            outputStream.write("你好,我是客戶端".getBytes());
            //關閉資料的輸出
            socket.shutdownOutput();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //4.資源的關閉
            if(outputStream != null){
                try {
                    outputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if(socket != null){
                try {
                    socket.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

2.2.3、UDP網路程式設計例程

  • 類DatagramSocket和DatagramPacket實現了基於UDP協議的網路程式
  • UDP資料報通過資料套接字DatagramSocket傳送和接收,系統不保證UDP資料報一定能安全送到目的地,也不能確定什麼時候可與抵達
  • DatagramPacket物件封裝了UDP資料報,在資料報中包含了傳送端的IP地址和埠號以及接收端的IP地址和埠號
  • UDP協議中每個資料報都能給出了完整的地址資訊,因此無需建立傳送方和接收方的連線
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;

public class Receiver {
    public static void main(String[] args) {
        DatagramSocket datagramSocket = null;

        byte[] buffer = new byte[100];
        DatagramPacket datagramPacket = new DatagramPacket(buffer,0,buffer.length);

        try {
            datagramSocket = new DatagramSocket(9090);

            datagramSocket.receive(datagramPacket);
            System.out.println(new String(datagramPacket.getData(),0,datagramPacket.getLength()));
        } catch (SocketException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (datagramSocket != null){
                datagramSocket.close();
            }
        }
    }
}
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
import java.net.UnknownHostException;

public class Sender {
    public static void main(String[] args) {
        String string = "我是UDP方式傳送的資料";
        byte[] data = string.getBytes();

        DatagramSocket datagramSocket = null;
        DatagramPacket datagramPacket = null;
        InetAddress inetAddress = null;

        try {
            datagramSocket = new DatagramSocket();
            inetAddress = InetAddress.getLocalHost();
            datagramPacket = new DatagramPacket(data,0,data.length,inetAddress,9090);

            datagramSocket.send(datagramPacket);
        } catch (SocketException e) {
            e.printStackTrace();
        } catch (UnknownHostException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

2.2.4、URL網路程式設計

  URL(Uniform Resource Locator):統一資源定位符,它表示Internet上某一個資源的地址。它是一種具體的URI,即URL可以用來標識一個資源,而且還指明瞭如何locate這個資源。通過URL我們可以訪問Internet上的各種網路資源。瀏覽器通過解析給定的URL可以在網路上查詢相應的檔案或其它資源。

URL的基本結構由5部分組成:

  • <傳輸協議>://<主機名>:<埠號>/<檔名>#判斷名?引數列表
    • 判斷名:即錨點

    • 引數列表格式:引數名=引數值&引數名=引數值……