探索Java中的網絡編程技術

前言

感謝! 承蒙關照~

探索Java中的網絡編程技術

網絡編程就是io技術和網絡技術的結合,網絡模型的定義,只要共用網絡模型就可以兩者連接.網絡模型參考.

圖片說明

圖片說明

一座塔有七層,我們需要闖關.

第一層物理層->第二層數據鏈路層->第三層網絡層->第四層傳輸層->第五層會話層->第六層表示層->第七層應用層.

物理層是主要定義物理設備標準,數據鏈路層是主要講從物理層接收的數據進行MAC地址(網卡的地址)的封裝與解封裝.這層的數據較幀.

網絡層是將從下層接收到的數據進行IP地址的封裝和解封裝.傳輸層是定義一些傳輸數據的協議和端口號.

會話層是將通過傳輸層建立數據傳輸的通路.表示層是進行對接收的數據進行解釋,加密與解密.

應用層主要是一些終端的應用.

應用層 --> 傳輸層 --> 網絡層 --> 主機至網絡層

圖片說明

圖片說明

電腦通訊要點:
一需要IP地址:InetAddress(互聯網協議即是規則)
二需要端口號
三需要傳輸協議

IP地址,網絡中設備的標識,不容易記住,可以用主機名,本地迴環地址: 127.0.0.1 主機名就是 localhost了.所謂局域網就是局部範圍內的,互聯網就是全球的.

端口號是用來標識進程的邏輯地址,不同進行的標識,有效的端口爲0到65535,其中0到1024系統使用或保留的端口.

傳輸協議即是通訊的規則,常見的協議爲TCPUDP.

java.net

類 InetAddress

java.lang.Object
-> java.net.InetAddress

所有已實現的接口有:

Serializable

直接已知子類:

Inet4Address, Inet6Address
public class InetAddress extends Object implements Serializable

這個類表示互聯網協議已地址.

圖片說明

圖片說明

Class Inet6Address

java.lang.Object
java.net.InetAddress
java.net.Inet6Address
public final class Inet6Address extends InetAddress

圖片說明

獲取ip地址:

public class IPDemo {
 public static void main(String[] args) throws UnknownHostException {
  //獲取本地主機地址對象
  InetAddress ip = InetAddress.getLocalHost();
  System.out.println(ip.getHostAddress() + ":" + ip.getHostName());
 }
}

域名解析

C:\WINDOWS\system32\drivers\etc

InetAddress方法

類型方法說明
booleanequals(Object obj)將此對象與指定對象進行比較
byte[]getAddress()返回此InetAddress對象的原始ip地址.
static InetAddress[]getAllByName(String host)給定主機的名稱,根據系統上配置的名稱服務返回其ip地址數組.
static InetAddressgetByAddress(byte[] addr)給出原始IP地址的InetAddress對象
static InetAddressgetByAddress(String host, byte[] addr)根據提供的主機名和ip地址創建InetAddress
static InetAddressgetByName(String host)確定主機名稱的ip地址
StringgetCanonicalHostName()獲取此ip地址的完全限定域名
StringgetHostAddress()返回文本顯示中的ip地址字符串
StringgetHostName()獲取此ip地址的主機名

網絡編程:

1,網絡模型:7層--->4層

端口

  1. 用於標識進程的邏輯地址,不同進程的標識

  2. 有效端口:0到65535,而0到1024系統使用或保留端口

傳輸協議

常見協議TCP``UDP

TCP和UDP的區別:

TCP: 面向連接,通過三次握手完成,速度慢,可靠。
UDP: 面向無連接,速度快,不可靠。

UDP是將數據及其源和目的封裝成數據包中,不需要建立連接,每個數據報的大小在限制在64k內,因無連接,是不可靠的協議,不需要連接,但是速度快.

TCP是需要進行連接的,形成傳輸數據的通道,在連接中進行大數據量傳輸,通過三次握手完成連接,是可靠的協議,效率低即是速度慢一點.

網絡編程-Socket

網絡通訊的要素:

  1. ip

  2. 端口

  3. 傳輸協議

ip是用於標識網絡中主機的數字標識,而端口是用於標識應用程序的數字,還有傳輸協議是用於進行數據傳輸的規則.

實現UDP的通信,TCP傳輸:客戶端,服務端.

Socket是網絡服務提供的一種機制,是通信兩端必備的,都要有Socket,網絡通信其實就是Socket間的通信,數據在兩個Socket間通過io傳輸.

兩端發送端和接收端-UDP

UDP發送端Demo

public class UDPSend{
 public static void main(String[] args){
  System.out.println("udp發送端");
 }
}

DatagramSocket

public class DatagramSocket extends Object

此類表示用來發送和接收數據報包的套接字.

數據報套接字是包投遞服務的發送或接收點.每個在數據報套接字上發送或接收的包都是單獨編址和路由的.從一臺機器發送到另一臺機器的多個包可能選擇不同的路由,也可能按不同的順序到達.

DatagramSocket上總是啓動UDP廣播發送.爲了接收廣播包,將DatagramSocket綁定到通配符地址.

圖片說明

void receive(DatagramPacket p)
從此套接字接收數據報包
send(DatagramPacket p)
從此套接字發送數據報包
public class UDPSend{
 public static void main(String[] args) throws IOException{
  System.out.println("udp發送端");
  DatagramSocket ds = new DatagramSocket();
  String text = "hello";
  byte[] buf = text.getBytes();
  // 將數據轉成字節數組
  DatagramPacket dp = new DatagramPacket(buf, buf.length, InetAddress.getByName("123.23232.323.2"),10000);
  ds.send(dp);
  ds.close();
 }
}
// 建立upd的socket,具備發送或接收功能
// 將數據封裝到數據包中,數據包對象是DatagramPacket.
// 使用socket對象的send方法將數據包發出去.
// 關閉資源

udp接收端

public class updDemo {
 public static void main(String[] args) throws IOException {
  System.out.println("udp 接收端");
  // 先有udpsocket服務
  // 接收數據
  DatagramSocket ds = new DatagramSocket();
  byte[] buf = new byte[1024];
  DatagramPacket dp = new DatagramPacket(buf, buf.length);
  ds.receive(dp);
  String ip = dp.getAddress().getHostAddress();
  int port = dp.getPort():
  String text = new String(dp.getData(),0,dp.getLength());
  // 關閉資源。
  ds.close();
 }
}

receive

public void receive(DatagramPacket p) throws IOException
此套接字接收數據報包

實現UDP的通信,udp傳輸涉及的兩個對象,即可以發送,又可以接收.TCP傳輸:客戶端,服務端.

UDP鍵盤輸入

public class UDPSend {
    public static void main(String[] args) throws IOException {
        System.out.println("udp 發送端 run");
//      1,建立udp的socket它具備者發送或者接收功能。
        DatagramSocket ds = new DatagramSocket(9999);
//      2,將數據封裝到數據包中。數據包對象是DatagramPacket。數據來自於鍵盤錄入。
        BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in));
        String line = null;
        while((line=bufr.readLine())!=null){
            if("over".equals(line)){
                break;
            }
            byte[] buf = line.getBytes();//將數據轉成字節數組。
//          將字節數組封裝到數據包中。
            DatagramPacket dp = new DatagramPacket(buf, buf.length, InetAddress.getByName("192.168.1.223"), 10001);
//          3,使用socket對象的send方法將數據包發送出去。
            ds.send(dp);
        }
//      4,關閉資源。
        ds.close();
    }
}
public class UDPRece {
    public static void main(String[] args) throws IOException {
        System.out.println("udp2 接收端 run");
        DatagramSocket ds = new DatagramSocket(10001);
        while (true) {
            // 2,接收數據。
            // 3,先定義數據包。
            byte[] buf = new byte[1024];
            DatagramPacket dp = new DatagramPacket(buf, buf.length);
            ds.receive(dp);
            // 4,通過數據包對象獲取數據包的內容,發送端的ip。發送端的端口,發送過來的數據。
            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();
    }
}

案例:

public class UDPChatTest {
    public static void main(String[] args) throws IOException {
        //發送端的socket 接收端的socket
        DatagramSocket sendSocket = new DatagramSocket();
        DatagramSocket receSocket = new DatagramSocket(10002);
        
        //創建任務對象。
        Send send = new Send(sendSocket);
        Rece rece = new Rece(receSocket);
        
        //創建線程並開啓。
        Thread t1 = new Thread(send);
        Thread t2 = new Thread(rece);
        t1.start();
        t2.start();
    }

}

// 發送任務
class Send implements Runnable {

    private DatagramSocket ds;

    public Send(DatagramSocket ds) {
        super();
        this.ds = ds;
    }

    @Override
    public void run() {
        try {
            BufferedReader bufr = new BufferedReader(new InputStreamReader(
                    System.in));
            String line = null;
            while ((line = bufr.readLine()) != null) {
                byte[] buf = line.getBytes();// 將數據轉成字節數組。
                DatagramPacket dp = new DatagramPacket(buf, buf.length,
                        InetAddress.getByName("1928.1.223"), 10002);
                ds.send(dp);
                if ("886".equals(line)) {
                    break;
                }
            }

            // 4,關閉資源。
            ds.close();
        } catch (IOException e) {

        }
    }
}

// 接收任務。
class Rece implements Runnable {

    private DatagramSocket ds;

    public Rece(DatagramSocket ds) {
        super();
        this.ds = ds;
    }

    @Override
    public void run() {
        while (true) {

            try {
                byte[] buf = new byte[1024];
                DatagramPacket dp = new DatagramPacket(buf, buf.length);
                ds.receive(dp);// 阻塞
                
                String ip = dp.getAddress().getHostAddress();
                int port = dp.getPort();
                String text = new String(dp.getData(), 0, dp.getLength());
                System.out.println(ip + ":" + port + ":" + text);
                if(text.equals("886")){
                    System.out.println(ip+"....離開聊天室");
                }
            } catch (IOException e) {

            }
        }

    }

}

tcp案例:

public class TCPClient {
    public static void main(String[] args) throws IOException {
        System.out.println("客戶端運行.......");
//      1,建立tcp的客戶端socket。明確服務端的地址和端口。
        Socket s = new Socket("192.1.223",10003);
//      2,如果通道建立成功就會出現socket io流。
//          客戶端需要做的就獲取socket流的中輸出流將數據發送目的地服務端。
        OutputStream out = s.getOutputStream();
//      3,通過socket輸出流將數據發送。
        out.write("hello tcp 來了!".getBytes());
//      4,關閉資源。
        s.close();
    }
}
public class TCPServer {
    public static void main(String[] args) throws IOException {
        System.out.println("服務端開啓.....");
        ServerSocket ss = new ServerSocket(10003);
        while (true) {
            Socket s = ss.accept();
            String ip = s.getInetAddress().getHostAddress();

            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);
            s.close();
        }
    }
}

案例:

public class TCPClient2 {
    public static void main(String[] args) throws UnknownHostException, IOException {
        System.out.println("客戶端2 啓動.......");
        Socket s = new Socket("192.1623", 10004);
        OutputStream out = s.getOutputStream();
        out.write("服務端,我來了".getBytes());
        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);
//      關閉資源。
        s.close();
    }
}
public class TCPSever2 {
    public static void main(String[] args) throws IOException {
        System.out.println("服務端2啓動.....");
        ServerSocket ss = new ServerSocket(10004);
        while (true) {
            // 獲取客戶端對象。
            Socket s = ss.accept();
            // 讀取客戶端的發送過來的數據
            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);
            // 給客戶端回饋數據。
            OutputStream out = s.getOutputStream();
            out.write("客戶端,我已到收到,哦耶!".getBytes());
            // 關閉客戶端
            s.close();
        }
        // 關閉服務端。如果不斷的獲取客戶端,不用關閉服務端。
//      ss.close();
    }
}

達叔小生:往後餘生,唯獨有你
You and me, we are family !
90後帥氣小夥,良好的開發習慣;獨立思考的能力;主動並且善於溝通
簡書博客: 達叔小生
https://www.jianshu.com/u/c785ece603d1

結語

  • 下面我將繼續對 其他知識 深入講解 ,有興趣可以繼續關注

  • 小禮物走一走 or 點贊

這是一個有質量,有態度的公衆號

喜歡本文的朋友們

歡迎長按下圖關注訂閱號

收看更多精彩內容

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章