Java網絡編程


網絡編程


一、網絡編程的目的:直接或間接地通過網絡協議與其他計算機實現數據交換,進行通訊。

二、網絡編程中兩個主要的問題:

  1.如何准確地定位網絡上一台或多台主機;定位主機上的特定的應用

  2.找到主機后如何可靠高效的進行數據傳輸。

三、網絡通信的要素:IP 和端口號

          網絡通信協議

 

 

 

通信要素一:IP與端口號


一、IP地址:InetAddress

1. IP地址:唯一的標識 Internet 上的計算機(通信實體)

2. 本地回環地址(hostAddress):127.0.0.1 主機名(hostName):localhost

3. IP 分類:IPV4 和 IPV6 ;(公網地址)萬維網與(私有地址)局域網

4. 域名:www.mi.com等

5.本地回路地址:127.0.0.1  對應着: localhost

6.如何實例化InetAddress:兩個方法:getByName(String host)、getLocalHost()

   兩個常用方法:getHostName()、getHostAddress()

public class InetAddressTest {

    public static void main(String[] args) {

        try {
            InetAddress inet1 = InetAddress.getByName("192.168.0.1");

            System.out.println(inet1);

            InetAddress inet2 = InetAddress.getByName("www.baidu.com");
            System.out.println(inet2);

            InetAddress inet3 = InetAddress.getByName("127.0.0.1");
            System.out.println(inet3);

            //獲取本地ip
            InetAddress inet4 = InetAddress.getLocalHost();
            System.out.println(inet4);

            //getHostName()
            System.out.println(inet2.getHostName());
            //getHostAddress()
            System.out.println(inet2.getHostAddress());

        } catch (UnknownHostException e) {
            e.printStackTrace();
        }
     }

    }
IP方法的使用

 

二、端口號:標識正在計算機上運行的程序。

1. 不同的進程有不同的端口號。

2. 端口分類:公認端口(0~1023) 、注冊端口(1024~49151) 、動態/私有端口:49152~65535。

3. 范圍:被規定為一個16位的整數 0~65535

4. 端口號與IP地址的組合得出一個網絡套接字:Socket

 

 

三、InetAddress類

1.  Internet上的主機有兩種方式表示地址:域名(hostName)、IP 地址(hostAddress)

2.  InetAddress類主要表示IP地址,兩個子類:Inet4Address、Inet6Address。

 

//InetAddress類沒有提供公共的構造器,而是提供了如下幾個靜態方法來獲取
//InetAddress實例
    public static InetAddress getLocalHost()
    public static InetAddress getByName(String host)
    
//InetAddress提供了如下幾個常用的方法
    public String getHostAddress():返回 IP 地址字符串(以文本表現形式)。
    public String getHostName():獲取此 IP 地址的主機名
    public boolean isReachable(int timeout):測試是否可以達到該地址

 

 

 

 

通信要素2:網絡通信協議


計算機網絡中實現通信必須有一些約定,即通信協議,對速率、傳輸代碼、代碼結構、傳輸控制步驟、出錯控制等制定標准。

 

一、傳輸層協議中有兩個非常重要的協議:傳輸控制協議TCP(Transmission Control Protocol)

                    用戶數據報協議UDP(User Datagram Protocol)。
 
二、TCP/IP 以其兩個主要協議:傳輸控制協議(TCP)和網絡互聯協議(IP)而得名,實際上是一組協議,包括多個具有不同功能且互為關聯的協議。
 
三、IP(Internet Protocol)協議是網絡層的主要協議,支持網間互連的數據通信。
 
四、TCP/IP協議模型從更實用的角度出發,形成了高效的四層體系結構,即物理鏈路層、IP層、傳輸層和應用層。

 

 

TCP和UDP


 

TCP協議:
  1. 使用TCP協議前,須先建立TCP連接,形成傳輸數據通道
  2. 傳輸前,采用“三次握手”方式,點對點通信,是可靠的
  3. TCP協議進行通信的兩個應用進程:客戶端、服務端。
  4. 在連接中可進行大數據量的傳輸
  5. 傳輸完畢,需釋放已建立的連接,效率低

 TCP三次握手:

 

 

TCP四次揮手:1.傳輸斷開連接信息

        2.發送斷開信息

           3.斷開連接

        4.驗證是否斷開

 

 

UDP協議
  1. 將數據、源、目的封裝成數據包,不需要建立連接
  2. 每個數據報的大小限制在64K內
  3. 發送不管對方是否准備好,接收方收到也不確認,故是不可靠的
  4. 可以廣播發送
  5. 發送數據結束時無需釋放資源,開銷小,速度快

 

 

Socket:網絡上具有唯一標識的IP地址和端口號組合在一起才能構成唯一能識別的標識符套接字。

  流套接字(stream socket):使用TCP提供可依賴的字節流服務
  數據報套接字(datagram socket):使用UDP提供“盡力而為”的數據報服務

 

 

TCP網絡編程


 

基於Socket的TCP編程
客戶端Socket的工作過程包含以下四個基本的步驟:
  1. 創建 Socket:根據指定服務端的 IP 地址或端口號構造 Socket 類對象。若服務器端響應,則建立客戶端到服務器的通信線路。若連接失敗,會出現異常。
  2. 打開連接到 Socket 的輸入/出流: 使用 getInputStream()方法獲得輸入流,使用getOutputStream()方法獲得輸出流,進行數據傳輸
  3. 按照一定的協議對 Socket 進行讀/寫操作:通過輸入流讀取服務器放入線路的信息(但不能讀取自己放入線路的信息),通過輸出流將信息寫入線程。
  4. 關閉 Socket:斷開客戶端到服務器的連接,釋放線路

 

服務器程序的工作過程包含以下四個基本的步驟:
  1. 調用 ServerSocket(int port) :創建一個服務器端套接字,並綁定到指定端口上。用於監聽客戶端的請求。
  2. 調用 accept():監聽連接請求,如果客戶端請求連接,則接受連接,返回通信套接字對象。
  3. 調用 該Socket類對象的 getOutputStream() 和 getInputStream ():獲取輸出流和輸入流,開始網絡數據的發送和接收。
  4. 關閉ServerSocket和Socket對象:客戶端訪問結束,關閉通信套接字。
 
/**
 * 實現TCP的網絡編程
 * 例子1:客戶端發送信息給服務端,服務端將數據顯示在控制台上
 *
 */
public class TCPTest1 {

    //客戶端
    @Test
    public void client()  {
        Socket socket = null;
        OutputStream os = null;
        try {
            //1.創建Socket對象,指明服務器端的ip和端口號
            InetAddress inet = InetAddress.getByName("192.168.14.100");
            socket = new Socket(inet,8899);
            //2.獲取一個輸出流,用於輸出數據
            os = socket.getOutputStream();
            //3.寫出數據的操作
            os.write("你好,我是客戶端mm".getBytes());
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //4.資源的關閉
            if(os != null){
                try {
                    os.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }

            }
            if(socket != null){
                try {
                    socket.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }

            }
        }



    }
    //服務端
    @Test
    public void server()  {

        ServerSocket ss = null;
        Socket socket = null;
        InputStream is = null;
        ByteArrayOutputStream baos = null;
        try {
            //1.創建服務器端的ServerSocket,指明自己的端口號
            ss = new ServerSocket(8899);
            //2.調用accept()表示接收來自於客戶端的socket
            socket = ss.accept();
            //3.獲取輸入流
            is = socket.getInputStream();

            //不建議這樣寫,可能會有亂碼
//        byte[] buffer = new byte[1024];
//        int len;
//        while((len = is.read(buffer)) != -1){
//            String str = new String(buffer,0,len);
//            System.out.print(str);
//        }
            //4.讀取輸入流中的數據
            baos = new ByteArrayOutputStream();
            byte[] buffer = new byte[5];
            int len;
            while((len = is.read(buffer)) != -1){
                baos.write(buffer,0,len);
            }

            System.out.println(baos.toString());

            System.out.println("收到了來自於:" + socket.getInetAddress().getHostAddress() + "的數據");

        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if(baos != null){
                //5.關閉資源
                try {
                    baos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if(is != null){
                try {
                    is.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if(socket != null){
                try {
                    socket.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if(ss != null){
                try {
                    ss.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

        }





    }

}
實現TCP的網絡編程,客戶端與服務端

 

/**
 *
 * 實現TCP的網絡編程
 * 例題2:客戶端發送文件給服務端,服務端將文件保存在本地。
 *
 */
public class TCPTest2 {

    /*
    這里涉及到的異常,應該使用try-catch-finally處理
     */
    @Test
    public void client() throws IOException {
        //1.
        Socket socket = new Socket(InetAddress.getByName("127.0.0.1"),9090);
        //2.
        OutputStream os = socket.getOutputStream();
        //3.
        FileInputStream fis = new FileInputStream(new File("beauty.jpg"));
        //4.
        byte[] buffer = new byte[1024];
        int len;
        while((len = fis.read(buffer)) != -1){
            os.write(buffer,0,len);
        }
        //5.
        fis.close();
        os.close();
        socket.close();
    }

    /*
    這里涉及到的異常,應該使用try-catch-finally處理
     */
    @Test
    public void server() throws IOException {
        //1.
        ServerSocket ss = new ServerSocket(9090);
        //2.
        Socket socket = ss.accept();
        //3.
        InputStream is = socket.getInputStream();
        //4.
        FileOutputStream fos = new FileOutputStream(new File("beauty1.jpg"));
        //5.
        byte[] buffer = new byte[1024];
        int len;
        while((len = is.read(buffer)) != -1){
            fos.write(buffer,0,len);
        }
        //6.
        fos.close();
        is.close();
        socket.close();
        ss.close();

    }
}
例題2:客戶端發送文件給服務端,服務端將文件保存在本地。

 

 

UDP網絡通信
  1. 類 DatagramSocket 和 DatagramPacket 實現了基於 UDP 協議網絡程序。
  2. UDP數據報通過數據報套接字 DatagramSocket 發送和接收,系統不保證UDP數據報一定能夠安全送到目的地,也不能確定什么時候可以抵達
  3. DatagramPacket 對象封裝了UDP數據報,在數據報中包含了發送端的IP地址和端口號以及接收端的IP地址和端口號。
  4. UDP協議中每個數據報都給出了完整的地址信息,因此無須建立發送方和接收方的連接。如同發快遞包裹一樣。

 

 

 

 

UDP網絡通信  流程:
1. DatagramSocket與DatagramPacket。
2. 建立發送端,接收端。
3. 建立數據包。
4. 調用Socket的發送、接收方法。
5. 關閉Socket。
發送端與接收端是 兩個獨立的運行程序。
 
/**
 * UDPd協議的網絡編程
 * @author shkstart
 */
public class UDPTest {

    //發送端
    @Test
    public void sender() throws IOException {

        DatagramSocket socket = new DatagramSocket();



        String str = "我是UDP方式發送的導彈";
        byte[] data = str.getBytes();
        InetAddress inet = InetAddress.getLocalHost();
        DatagramPacket packet = new DatagramPacket(data,0,data.length,inet,9090);

        socket.send(packet);

        socket.close();

    }
    //接收端
    @Test
    public void receiver() throws IOException {

        DatagramSocket socket = new DatagramSocket(9090);

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

        socket.receive(packet);

        System.out.println(new String(packet.getData(),0,packet.getLength()));

        socket.close();
    }
}
UDPd協議的網絡編程

 

 

URL類
URL(Uniform Resource Locator):統一資源定位符,它表示 Internet 上某一資源的地址
 
/**
 * URL網絡編程
 * 1.URL:統一資源定位符,對應着互聯網的某一資源地址
 * 2.格式:
 *  http://localhost:8080/examples/beauty.jpg?username=Tom
 *  協議   主機名    端口號  資源地址           參數列表
 */
public class URLTest {

    public static void main(String[] args) {

        try {

            URL url = new URL("http://localhost:8080/examples/beauty.jpg?username=Tom");

//            public String getProtocol(  )     獲取該URL的協議名
            System.out.println(url.getProtocol());
//            public String getHost(  )           獲取該URL的主機名
            System.out.println(url.getHost());
//            public String getPort(  )            獲取該URL的端口號
            System.out.println(url.getPort());
//            public String getPath(  )           獲取該URL的文件路徑
            System.out.println(url.getPath());
//            public String getFile(  )             獲取該URL的文件名
            System.out.println(url.getFile());
//            public String getQuery(   )        獲取該URL的查詢名
            System.out.println(url.getQuery());




        } catch (MalformedURLException e) {
            e.printStackTrace();
        }

    }


}
URL網絡編程常用方法

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

.

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM