JAVA網路程式設計(UDP入門篇)
阿新 • • 發佈:2019-01-12
網路程式設計:通過計算機語言實現資源的共享
網路程式設計模型
資料一層層的封裝打包
應用層: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