前言
感謝! 承蒙關照~
探索Java中的網絡編程技術
網絡編程就是io
技術和網絡技術的結合,網絡模型的定義,只要共用網絡模型就可以兩者連接.網絡模型參考.
圖片說明
圖片說明
一座塔有七層,我們需要闖關.
第一層物理層->第二層數據鏈路層->第三層網絡層->第四層傳輸層->第五層會話層->第六層表示層->第七層應用層.
物理層是主要定義物理設備標準,數據鏈路層是主要講從物理層接收的數據進行MAC
地址(網卡的地址)的封裝與解封裝.這層的數據較幀.
網絡層是將從下層接收到的數據進行IP
地址的封裝和解封裝.傳輸層是定義一些傳輸數據的協議和端口號.
會話層是將通過傳輸層建立數據傳輸的通路.表示層是進行對接收的數據進行解釋,加密與解密.
應用層主要是一些終端的應用.
應用層 --> 傳輸層 --> 網絡層 --> 主機至網絡層
圖片說明
圖片說明
電腦通訊要點:
一需要IP
地址:InetAddress
(互聯網協議即是規則)
二需要端口號
三需要傳輸協議
IP
地址,網絡中設備的標識,不容易記住,可以用主機名,本地迴環地址: 127.0.0.1
主機名就是 localhost
了.所謂局域網就是局部範圍內的,互聯網就是全球的.
端口號是用來標識進程的邏輯地址,不同進行的標識,有效的端口爲0到65535
,其中0到1024
系統使用或保留的端口.
傳輸協議即是通訊的規則,常見的協議爲TCP
, UDP
.
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
方法
類型 | 方法 | 說明 |
---|---|---|
boolean | equals(Object obj) | 將此對象與指定對象進行比較 |
byte[] | getAddress() | 返回此InetAddress 對象的原始ip 地址. |
static InetAddress[] | getAllByName(String host) | 給定主機的名稱,根據系統上配置的名稱服務返回其ip 地址數組. |
static InetAddress | getByAddress(byte[] addr) | 給出原始IP 地址的InetAddress 對象 |
static InetAddress | getByAddress(String host, byte[] addr) | 根據提供的主機名和ip 地址創建InetAddress |
static InetAddress | getByName(String host) | 確定主機名稱的ip 地址 |
String | getCanonicalHostName() | 獲取此ip 地址的完全限定域名 |
String | getHostAddress() | 返回文本顯示中的ip 地址字符串 |
String | getHostName() | 獲取此ip 地址的主機名 |
網絡編程:
1,網絡模型:7層--->4層
端口
用於標識進程的邏輯地址,不同進程的標識
有效端口:0到65535,而0到1024系統使用或保留端口
傳輸協議
常見協議TCP``UDP
TCP和UDP的區別:
TCP: 面向連接,通過三次握手完成,速度慢,可靠。
UDP: 面向無連接,速度快,不可靠。
UDP
是將數據及其源和目的封裝成數據包中,不需要建立連接,每個數據報的大小在限制在64k
內,因無連接,是不可靠的協議,不需要連接,但是速度快.
TCP
是需要進行連接的,形成傳輸數據的通道,在連接中進行大數據量傳輸,通過三次握手完成連接,是可靠的協議,效率低即是速度慢一點.
網絡編程-Socket
網絡通訊的要素:
ip
端口
傳輸協議
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 點贊
這是一個有質量,有態度的公衆號
喜歡本文的朋友們
歡迎長按下圖關注訂閱號
收看更多精彩內容