天天看點

終于把 TCP 與 UDP 協定整明白了!

網絡程式設計有三個要素,分别是IP位址、端口号和通信協定,那本文主要講述的是TCP與UDP這兩種通信協定,以及程式設計的實作。

首先,我們需要了解一下IP位址、端口号、通信協定的相關知識。

一、IP位址

網絡中的計算機使用IP位址來進行唯一辨別,IP位址有IPv4和IPv6兩種類型。IPv4采用十進制或二進制表示形式,十進制是一種比較常用的表示形式,如192.168.1.131,IPv6采用十六進制表示形式,一般不常用。

如何檢視IP位址相關資訊:

在Windows系統下,打開cmd,輸入指令ipconfig,按回車即可檢視。在Linux或Mac系統下,打開終端,使用ifconfig指令,按回車即可檢視。

二、端口号

端口号是計算機中的應用程式的一個整數數字标号,用來區分不同的應用程式。

0 ~ 1024 為被系統使用或保留的端口号,0 ~ 65535為有效的端口号,也就是說我們要對一些程式定義端口号的時候,要選擇1024 ~ 65535範圍内的整數數字。

比如,以前學過的MySQL的端口号是3306,SQLServer的端口号是1433,查了一下Oracle的端口号是1521。

一定要把這些資料庫對應的端口号,藏在深深的腦海裡,以後在連接配接資料庫的時候,會使用到端口号。

三、通信協定

說的通俗一點,通信協定就是網絡通信中的規則,分為TCP協定和UDP協定兩種。

第一種:TCP協定

英文名:Transmission Control Protocol 中文名:傳輸控制協定 協定說明:TCP是一種面向連接配接的、可靠的、基于位元組流的傳輸層通信協定。

舉例:打電話,需要雙方都接通,才能進行對話

特點:效率低,資料傳輸比較安全

第二種:UDP協定

英文名:User Datagram Protocol 中文名:資料報協定 協定說明:UDP是一種面向無連接配接的傳輸層通信協定。

舉例:發短信,不需要雙方建立連接配接,But,資料報的大小應限制在64k以内

特點:效率高,資料傳輸不安全,容易丢包

四、三要素關系圖與網絡模型圖

1、網絡程式設計三要素關系圖

終于把 TCP 與 UDP 協定整明白了!

注:圖中端口号、IP位址為示範,并非真實

2、OSI參考模型與TCP/IP參考模型

終于把 TCP 與 UDP 協定整明白了!

五、TCP程式設計

TCP是基于位元組流的傳輸層通信協定,是以TCP程式設計是基于IO流程式設計。

對于用戶端,我們需要使用Socket類來建立對象。對于伺服器端,我們需要使用ServerSocket來建立對象,通過對象調用accept()方法來進行監聽是否有用戶端通路。

用戶端與伺服器端圖解:

終于把 TCP 與 UDP 協定整明白了!

用戶端與伺服器端實作步驟:

前提:建立一個項目,在項目中建立兩個子產品(model),一個子產品用來放用戶端相關代碼,一個子產品用來放伺服器端相關代碼。

目錄結構如下圖

終于把 TCP 與 UDP 協定整明白了!

用戶端:

1、建立Socket對象,并指定伺服器端應用程式的端口号和伺服器端主機的IP位址。

2、使用Socket的對象調用getOutputStream()方法來擷取位元組輸出流對象。

3、調用位元組輸出流的write(byte[] buf)或者write(int b)向伺服器發送指定資料。

4、記得關閉流。

伺服器端:

1、建立ServerSocket對象,并指定該應用程式的端口号,端口号必須和用戶端指定的端口号一樣。

2、使用ServerSocket對象的accept()方法來監聽用戶端發送過來的請求,傳回值為Socket對象。

3、調用Socket對象的getInputStream()方法擷取位元組輸入流對象

4、調用位元組輸入流對象的read(byte[] buf)或read()方法擷取資料。

5、記得關閉流。

執行個體:

用戶端向伺服器端發送資訊,并顯示在伺服器端。

Client類(用戶端)

package cn.tkrnet.client;

import java.io.IOException;
import java.io.OutputStream;
import java.net.Socket;

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

        //建立Socket對象,指定要發送到伺服器端的IP位址,以及伺服器端應用程式接收的端口号
        //localhost代表本機IP位址
        Socket client = new Socket("localhost",9000);

        //擷取輸出流,用于向伺服器端發送資料
        OutputStream os = client.getOutputStream();

        os.write("Java is my friend !".getBytes());
        System.out.println("資訊已發送");

        //關閉流
        os.close();
        client.close();
    }
}      

Server類(伺服器端)

package cn.tkrnet.server;

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) throws IOException {
        System.out.println("--伺服器端已開啟--");

        //建立ServerSocket對象,這裡的端口号必須與用戶端的端口号相同
        ServerSocket server = new ServerSocket(9000);

        //調用方法accept(),用來監聽用戶端發來的請求
        Socket socket = server.accept();

        //擷取輸入流對象
        InputStream is = socket.getInputStream();

        //讀取輸入流中的資料
        int b = 0;
        while ((b =is.read()) != -1){
            System.out.print((char)b);
        }
        //關閉流
        is.close();
        socket.close();
        server.close();
    }
}      

提示:在運作程式時,一定要先運作伺服器端的程式代碼,再運作用戶端的程式代碼。因為用戶端要向伺服器發送請求,前提是伺服器端要處于開啟狀态。

Server類(伺服器端)運作結果:

--伺服器端已開啟--

Client類(用戶端)運作結果:

資訊已發送

Client類(用戶端)運作後,Server類(伺服器端)收到資訊,運作結果:

Java is my friend !

1

執行個體分析:

伺服器端啟動後,伺服器端的accept()方法一直處于監聽狀态,直到用戶端連接配接了伺服器,伺服器端再從流中讀取用戶端發來的資料。

恕我直言,這是一個超級無敵簡單的單向通信執行個體。

六、UDP程式設計

UDP使用資料報進行資料傳輸,沒有用戶端與伺服器端之分,隻有發送方與接收方,兩者哪個先啟動都不會報錯,但是會出現資料丢包現象。發送的内容有字數限制,大小必須限制在64k以内。

發送方與接收方實作步驟:

前提:建立一個項目,在項目中建立兩個子產品(model),一個子產品用來放發送方相關代碼,一個子產品用來放接收方相關代碼。

終于把 TCP 與 UDP 協定整明白了!

發送方:

1、建立DatagramSocket對象,可以指定應用程式的端口号,也可以不指定。

2、準備需要發送的資料

3、建立DatagramPacket對象,用來對發送的資料進行打包,需要指定發送内容、發送多少、發送到哪裡和接收方的端口号四個參數。

4、調用DatagramSocket對象的send()方法發送資料。

接收方:

1、建立DatagramSocket對象,指定接收方的端口号,這個必須指定。

2、建立一個byte類型數組,用來接收發送方發送過來的資料。

3、建立DatagramPacket對象,準備接收資料。

4、調用DatagramSocket對象的receive()方法用于接收資料。

5、使用String類的構造方法将byte類型的數組中的資料轉化成String類型并顯示。

6、記得關閉流。

發送方發送資訊,接收方接收資訊,并顯示。

Sender類(發送方)

package cn.tkrnet.Sender;

import java.io.IOException;
import java.net.*;

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

        //建立接受或發送的資料報套接字,并指定發送方的端口号為7770
        DatagramSocket ds = new DatagramSocket(7770);   //端口号也可以不指定
        System.out.println("---發送方---");

        //建立資料報對象,用來發送資料
        byte[] b = "Java is my friend !".getBytes();

        //8800為接收方的端口号,netAddress.getByName("localhost")是擷取主機的IP位址
        DatagramPacket dp = new DatagramPacket(b,b.length, InetAddress.getByName("localhost"),7788);

        ds.send(dp);    //發送資料報
        System.out.println("資料已發送");
        //關閉流
        ds.close();
    }
}      

Receiver類(接收方)

package cn.tkrnet.receiver;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;

public class Receiver {
    public static void main(String[] args) throws IOException {
        System.out.println("---接收方---");

        //建立資料報套接字對象,指定的端口号要和發送方發送資料的端口号相同
        // (不是發送方的端口号7770,是發送方發送資料的端口号7788)
        DatagramSocket ds = new DatagramSocket(7788);

        //建立接收資料報的對象
        byte[] b = new byte[1024];
        DatagramPacket dp = new DatagramPacket(b,b.length);

        //接收資料
        ds.receive(dp);
        System.out.println(new String(b,0,dp.getLength()));
        //關閉流
        ds.close();
    }
}      

提示:在運作程式時,先運作發送方程式,還是先運作接收方程式都不會報錯,但是有可能會出現資料丢包,一般我們都先運作接收方的程式代碼,再運作發送方的程式代碼。

Receiver類(接收方)運作結果:

---接收方---

Sender類(發送方)運作結果:

---發送方---

資料已發送

Sender類(發送方)運作後,Receiver類(接收方)接收到資訊,運作結果:

   ---接收方---

   Java is my friend !

隻有接收方先啟動運作,才會存在端口号為7788的程式,發送方才能發送資料到指定端口号7788,接收方才能接收資料。

不瞞你說,這也是個超級無敵簡單的單向通信執行個體。

七、總結

以上是我分享給大家的關于網絡通信TCP協定與UDP協定的一些總結。

如果覺得還不錯的話,就點個贊和在看吧!

原文連結:

https://blog.csdn.net/m0_47890251/article/details/107121432

版權聲明:本文為CSDN部落客「酷酷的猿」的原創文章,遵循CC 4.0 BY-SA版權協定,轉載請附上原文出處連結及本聲明。