1. 程式人生 > >JAVA網路程式設計(UDP入門篇)

JAVA網路程式設計(UDP入門篇)

網路程式設計:通過計算機語言實現資源的共享

網路程式設計模型資料一層層的封裝打包

應用層:eg:應用程式,qq
表示層:
會話層:
傳輸層:
網路層:資料傳輸
資料鏈路層:資料幀,使用交換機傳遞資料
物理層 : 將資料轉化為1,0資料

應用程式:網路程式設計+IO+多執行緒

此部落格的主角是網路層

java針對網路程式設計提供的類都在java.net下面

網路程式設計的要素

 A:IP地址  找到對應的應用程式 
 B:埠號  對應的應用程式的標識  
 C:協議    通過某個規則協議進行

IP地址:是每臺計算機在網路中的唯一標識

 eg:192.1668.32.80
 注意:
     計算機在網路中的唯一標識肯定不是這樣的:
     所以得轉化成二進位制的資料,計算機才能夠識別:
     11000000 10101000 00100000 01010000
那為什麼每次我們配置ip地址不配成二進位制的? 
     因為二進位制的資料我們並不常用,且不方便記憶,並推出了記憶ip地址的方案:“點分十進位制”

ip地址的組成:

網路號+主機端號

IP地址的分類:

A:0.0.0.0~127.255.255.255   
B:128.0.0.0~191.255.255.255
C:192.0.0.0~223.255.255.255
D:不常見
E:不常見

A類:第一段表示網路號段,後三段表示主機號碼

網路號碼:256*256*256  16777216(可以給這麼多的計算機使用)
稀少:一般是國家使用,eg 軍隊 電信

B類:前兩段表示網路號段,後兩端表示主機號碼

網路號碼:256*256  65536
eg:大學校園網

C類:前一段表示網路號段,後三段表示主機號碼

網路號碼:256
eg:家庭,

區域網IP地址的常見配置

192.168.x.x (常見)
10.x.x.x (一般公司開頭)

特殊地址:

x.x.x.0 網路號
x.x.x.255 廣播號

InetAddress

package com.net;

import java.net.InetAddress;
import java.net.UnknownHostException;

/**
 * 如果一個類沒有構造方法是什麼情況?
 * 1:單例模式
 * 2:類中的成員都是靜態的(Arrays,Math,Collections)
 * 3:通過一個靜態方法返回本身物件。
 * class Demo{
 *  private Demo();
 *  public static Demo getDemo(){
 *      return new Demo();
 *  }
 * }
 * @author yuliyang
 * @version $Id: InetAddressDemo.java, v 0.1 2016年11月21日 下午10:03:43 yuliyang Exp $
 */
public class InetAddressDemo {
    public static void main(String[] args) throws UnknownHostException {
        //根據主機名獲取到IP地址物件
        //InetAddress address = InetAddress.getByName("yly");
        InetAddress address = InetAddress.getByName("192.168.31.223");
        System.out.println(address);
        //獲取主機名
        String hostNam = address.getHostName();
        //獲取IP地址
        String ipAddress = address.getHostAddress();
        System.out.println(hostNam + "---" + ipAddress);

    }
}

埠號:每一個程序的邏輯地址,是一個標識號
一個程序是一個應用程式,,所以,我們說埠號也是一個應用程式的標識號

範圍

   0-65535之間
   0-1024之間不要隨意使用,因為它被保留或者被系統程序佔用,

協議

通訊的規則

UDP(效率):把資料打包,不建立連線,導致資料不可靠,且資料有限制,64k=32768個漢字,但是速度快效率高。

TCP(安全):建立連線通道,三次握手協議,只要通道沒有斷開,資料沒有限制,資料可靠,但是耗時速度慢,

一般的應用程式又有UDP(類似於群聊)又有TCP(類似於單聊)協議

1:簡單的UDP程式碼

send端


package com.net.udp;

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

/**
 * UDP傳送資料的步驟
 * A:建立傳送端的socket服務物件
 * B:建立資料,並將資料打包
 * C:通過socket物件的傳送功能傳送資料包
 * D:釋放資源
 * 
 */
public class SendDemo {
    public static void main(String[] args) throws IOException {
        //A:建立傳送端的socket服務物件
        DatagramSocket dSocket = new DatagramSocket();
        /**
         *  B:建立資料,並將資料打包
         *  buf:要傳送的資料資訊
         *  length:傳送的資料長度
         *  address:表示要發到哪裡去,對於的那個IP地址
         *  port:埠號
         * getBytes()使用平臺的預設字符集將此 String 編碼為 byte 序列,
         * 並將結果儲存到一個新的 byte 陣列中
         */
        byte[] buf = "hello test socket".getBytes();
        int length = buf.length;
        InetAddress address = InetAddress.getByName("192.168.31.222");
        int port = 10010;
        DatagramPacket p = new DatagramPacket(buf, length, address, port);
        //C:通過socket物件的傳送功能傳送資料包
        dSocket.send(p);
        //D:關閉
        dSocket.close();
    }
}

receiver

package com.net.udp;

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

/**
 * UDP協議接收資料步驟
 * A:建立接收端的socket物件
 * B:建立一個數據包用於接收資料
 * C:接收資料
 * D:解析資料,並顯示在控制檯
 * E:釋放資源
 * 
 */
public class ReceiveDemo {
    public static void main(String[] args) throws IOException {
        //A:建立接收資料的socket物件,並指定埠號(埠號隨意只要與send端一致就行)
        DatagramSocket ds = new DatagramSocket(10086);
        /**
         * B:設定緩衝區
         * new String(byte[] buf,int index,int length);
         * 通過使用平臺預設的字符集解碼指定的byte陣列
         * buf;要解碼的陣列
         * index:要解碼的第一個buf的索引
         * length:要解碼的byte數(並不是buf的長度)
         * p.getLength:將要傳送或接收到的資料的長度。
         */
        byte[] buf = new byte[1024];
        int length = buf.length;
        DatagramPacket dp = new DatagramPacket(buf, length);
        //C接收資料
        ds.receive(dp); //阻塞式方式,所以會一直在執行
        //D:解析資料
        InetAddress address = dp.getAddress();
        String ip = address.getHostName();
        //返回緩衝區
        byte[] byss = dp.getData();
        //返回實際長度
        int len = dp.getLength();
        String s = new String(byss, 0, len);
        System.out.println(ip + "--" + s);
        //E:釋放資源
        ds.close();
    }
}

如果想要不同的電腦都看到結果的話,就將IP地址改為廣播地址X.X.X.255,就實現了不同電腦都可以看到你傳送的訊息了,

另外增強版:主要模擬qq傳送訊息實現,此處增加IO以及執行緒實現聊天功能

聊天控制端

package com.net.udp4;

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

/**
 * 多執行緒改進聊天
 */
public class ChatDemo {
    public static void main(String[] args) throws IOException {
        DatagramSocket sendSocket = new DatagramSocket();
        DatagramSocket receiveSocket = new DatagramSocket(12580);
        SendThread sendT = new SendThread(sendSocket);
        ReceiveThread receiveT = new ReceiveThread(receiveSocket);
        Thread send = new Thread(sendT);
        Thread receive = new Thread(receiveT);
        send.start();
        receive.start();
    }
}

增強版send端

package com.net.udp4;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;

public class SendThread implements Runnable {
    DatagramSocket sendSocket;

    public SendThread(DatagramSocket sendSocket) {
        this.sendSocket = sendSocket;
    }

    @Override
    public void run() {
        //封裝鍵盤錄入
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        String line = null;
        try {
            while ((line = br.readLine()) != null) {
                if ("88".equals(line)) {
                    break;
                }
                byte[] buf = line.getBytes();
                //改成廣播地址192.168.31.255
                DatagramPacket p = new DatagramPacket(buf, buf.length, InetAddress.getByName("192.168.31.255"), 12580);
                sendSocket.send(p);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        sendSocket.close();
    }
}

增強版接收端

package com.net.udp4;

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

public class ReceiveThread implements Runnable {
    DatagramSocket receiveSocket;
    public ReceiveThread(DatagramSocket receiveSocket) {
        this.receiveSocket = receiveSocket;
    }
    @Override
    public void run() {
        while (true) {
            byte[] buf = new byte[1024];
            /**
             * buf - 儲存傳入資料報的緩衝區。
             * len - 要讀取的位元組數。
             */
            DatagramPacket p = new DatagramPacket(buf, buf.length);
            try {
                receiveSocket.receive(p);
            } catch (IOException e) {
                e.printStackTrace();
            }
            String ip = p.getAddress().getHostAddress();
            String name = p.getAddress().getHostName();
            String parse = new String(p.getData(), 0, p.getLength());
            System.out.println("ip地址為:" + ip + ";計算機名為:" + name + ";發的訊息為  " + parse);
            //接收端相當於伺服器,所以不能一次執行之後就結束,且不需要關閉
            //receiveSocket.close();
        }
    }
}

大致實現的功能展示(很簡陋) 222是我自己,159 是另外一臺電腦:
這裡寫圖片描述
這樣,大概的功能就展現出來了,我就可以看到自己傳送的訊息,以及別人傳送的訊息了,只是樣式很醜啦。。。。哈哈哈哈哈哈。
–end