網路通信,UDP.TCP協議
網路通信
計算機網路
是指將地理位置不同的具有獨立功能的多臺計算機及其外部設備,通過通信線路連接起來,在網路作業系統,網路管理軟體及網路通信協議的管理和協調下,實作資源共享和資訊傳遞的計算機系統,
網路編程
就是用來實作網路互連的不同計算機上運行的程式間可以進行資料交換,
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳![(img-pOEq0xKZ-1605614790123)(img\image-20201105134910477.png)]](https://img.uj5u.com/2020/11/18/194827181641361.png)
網路通信三要素
IP地址:InetAddress
網路中設備的標識,不易記憶,可用主機名
埠號
用于標識行程的邏輯地址,不同行程的標識
傳輸協議
通訊的規則
常見協議:TCP,UDP
IP地址
要想讓網路中的計算機能夠互相通信,必須為每臺計算機指定一個標識號,通過這個標識號來指定要接受資料的計算機和識別發送的計算機,在TCP/IP協議中,這個標識號就是IP地址,
// ip地址物件
// 不能通過構造方法創建
// 根據名字回傳第一個所有符合要求的IP地址物件
InetAddress byName = InetAddress.getByName("PC201501241736");
//System.out.println(byName);
//這個方法也可以通過ip獲取(將ip當做name填入)
//如果通過這種方式獲取ip物件 那么不能獲取計算機名
InetAddress byName2 = InetAddress.getByName("4B5MYUK5PQ2WSNI");
//System.out.println(byName2);
//回傳指定ip物件代表 的計算機名
System.out.println(byName.getHostName());
//回傳指定ip物件代表 的計算機IP地址
System.out.println(byName.getHostAddress());
埠號
物理埠 網卡口
邏輯埠 我們指的就是邏輯埠
A:每個網路程式都會至少有一個邏輯埠
B:用于標識行程的邏輯地址,不同行程的標識
C:有效埠:065535,其中01024系統使用或保留埠,
通過dom命令 netstat -ano可以查看所有占用的埠
通信協議
UDP
? 將資料源和目的封裝成資料包中,不需要建立連接;每個資料報的大小在限制在64k;因無連接,是不可靠協議;不需要建立連接,速度快
資料報協議:將發送的資料分割為指定大小后發送,無需連接接受端,發送端只管發送資料,無論接收端是否接收都會發送
TCP
建立連接,形成傳輸資料的通道;在連接中進行大資料量傳輸;通過三次握手完成連接,是可靠協議;必須建立連接,效率會稍低
資料連接協議:資料的發送與接收建立在連接通道的基礎上,客戶端連接服務端后才可以發送接受請求資料
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳![(img-jLhEYSz9-1605614790127)(img\image-20201105103035599.png)]](https://img.uj5u.com/2020/11/18/194827181641362.png)
Socket
Socket套接字:
網路上具有唯一標識的IP地址和埠號組合在一起才能構成唯一能識別的識別符號套接字,
Socket原理機制:
通信的兩端都有Socket,
網路通信其實就是Socket間的通信,
資料在兩個Socket間通過IO傳輸,
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳![(img-VaTvBtQc-1605614790130)(img\image-20201105104640517.png)]](https://img.uj5u.com/2020/11/18/194827181641363.png)
使用UDP協議完成資料的發送與接收
發送端思路
1:建立udp的socket服務(創建DatagramSocket物件,發送端無需指定埠)
2:將要發送的資料封裝成資料包(創建DatagramPacket物件,傳入資料位元組陣列,資料長度,ip地址物件,接收方接收埠號,將資料格式化)
3:通過udp的socket服務,將資料包發送出(使用DatagramSocket物件的send方法發送資料包)
4:關閉資源(DatagramSocket物件的close方法)
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
import java.net.UnknownHostException;
//使用socket 與udp協議實作發送代碼的書寫
public class UdpSend {
public static void main(String[] args) throws IOException {
// 1:建立udp的socket服務
DatagramSocket ds = new DatagramSocket();
// 創建使用udp發送資料的socket物件 發送資料使用隨機空閑埠
// DatagramSocket ds1 = new DatagramSocket(10000);
// 創建使用udp發送資料的socket物件 發送資料使用指定埠 若埠被占用會報錯
// 2:將要發送的資料封裝成資料包
// (1)準備要發送的資料(資料在網路傳輸本質位元組流)
byte[] bytes = "udp發送資料".getBytes();
// (2)創建資料包物件 將資料進行格式化
DatagramPacket dp = new DatagramPacket(bytes, bytes.length, InetAddress.getByName("localhost"), 10000);
// 分別傳入資料 資料長度 接受地址物件 接受埠號
// 3:通過udp的socket服務,將資料包發送出
ds.send(dp);
// 4:關閉資源
ds.close();
}
}
接收端思路
1:建立udp的socket服務(創建DatagramSocket物件,接收端需要根據發送端指定埠號)
2:創建接受資料包物件(創建Datagrampacket物件,傳入每次接受位元組陣列以及位元組陣列長度)
3:通過receive方法接收資料,將收到的資料存盤到資料包物件中(呼叫DatagramSocket物件receive阻塞方法傳入Datagrampacket物件)
4:通過資料包物件的功能來完成對接收到資料進行決議.(獲取發送方發送時傳在資料包中定義的資料資訊)
5:可以對資源進行關閉
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
//使用socket udp協議完成資料的接收
public class UdpReceipt {
public static void main(String[] args) throws IOException {
// 1:建立udp的socket服務
DatagramSocket ds = new DatagramSocket(10000);
// 2:通過receive方法接收資料
// (1)創建保存資料的資料包物件
byte[] b = new byte[1024];// 創建接受的位元組陣列
DatagramPacket dp = new DatagramPacket(b, b.length);
//使用位元組陣列接受資料并存盤至資料包中
//(2)使用資料包物件接受資料
ds.receive(dp);
//receive是阻塞方法,與scanner的獲取資料類似
//當程式執行到這個方法時會暫停運行,當接收到發送端發送的資料后繼續執行
// 3:將收到的資料存盤到資料包物件中
// 4:通過資料包物件的功能來完成對接收到資料進行決議.
InetAddress address = dp.getAddress();//獲取請求地址物件
int port = dp.getPort();//獲取請求埠
byte[] data = dp.getData();//獲取存盤資料的位元組陣列
int length = dp.getLength();//獲取資料實際長度
System.out.println(address);
System.out.println(port);
System.out.println(new String(data, 0, length));
// 5:可以對資源進行關閉
ds.close();
}
}
使用UDP完成一對一資訊的發送與接收
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
import java.util.Scanner;
//使用udp協議完成客戶端(既能發送也能接收)書寫
public class UdpClient {
public static void main(String[] args) {
// 創建多個執行緒分別執行發送與接收
// 接收端執行緒
new Thread(new Runnable() {
@Override
public void run() {
// 創建udp協議接收端socket物件
try {
DatagramSocket ds = new DatagramSocket(10000);
// 創建接受資料的資料包物件
byte[] b = new byte[1024];
DatagramPacket dp = new DatagramPacket(b, b.length);
// 呼叫阻塞方法獲取請求資料并使用資料包物件接收
while (true) {
ds.receive(dp);
// 從資料包物件中決議發送的資料
byte[] data = dp.getData();// 資料的位元組陣列
String hostAddress = dp.getAddress().getHostAddress();// 請求方ip
System.out.println(hostAddress + ":" + new String(data, 0, data.length));
}
} catch (Exception e) {
e.printStackTrace();
}
}
}).start();
// 發送到執行緒
new Thread(new Runnable() {
@Override
public void run() {
Scanner sc = new Scanner(System.in);
try {
// 創建發送端scocket物件
DatagramSocket ds = new DatagramSocket();
while (true) {
System.out.println("請輸入 接收端ip:發送內容");
String str = sc.nextLine();
String[] split = str.split(":");
// 創建資料包物件并將資料位元組陣列傳入
byte[] b = split[1].getBytes();
DatagramPacket dp = new DatagramPacket(b, b.length, InetAddress.getByName(split[0]), 10000);
// 將資料包物件發送至指定接收端
ds.send(dp);
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}).start();
}
}
使用TCP協議完成資料的發送與接收
接收端(服務器)思路
首先進行接收端的書寫,tcp協議建立在連接之上,如果發送端沒有連接到服務端則會報錯
1:建立服務器端的socket服務(new ServerSocket(埠))
2:服務端沒有直接流的操作,而是通過accept方法獲取客戶端物件,在通過獲取到的客戶端物件的流和客戶端進行通信(獲取連接服務器的客戶端socket物件)
3:通過客戶端的獲取流物件的方法,讀取資料或者寫入資料(使用getinputStream方法獲取輸入流讀取資料)
4:如果服務完成,需要關閉客戶端,然后關閉服務器,但是,一般會關閉客戶端,不會關閉服務器,因為服務端是一直提供服務的
import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;
//tcp服務器端(接收端)
public class TcpService {
public static void main(String[] args) throws Exception {
// 1:建立服務器端的socket服務,需要一個埠
ServerSocket ss = new ServerSocket(10000);
// 2:服務端沒有直接流的操作,而是通過accept方法獲取客戶端物件,在通過獲取到的客戶端物件的流和客戶端進行通信
Socket s = ss.accept();// 獲取當前連接服務端的客戶端物件
// 3:通過客戶端的獲取流物件的方法,讀取資料或者寫入資料
String hostAddress = s.getInetAddress().getHostAddress();
System.out.println(hostAddress + "連接服務器");
InputStream is = s.getInputStream();
byte[] b = new byte[1024];
int len = 0;
while ((len = is.read(b)) != -1) {
System.out.println(new String(b, 0, len));
}
// 4:如果服務完成,需要關閉客戶端,然后關閉服務器,但是,一般會關閉客戶端,不會關閉服務器,因為服務端是一直提供服務的
s.close();// 關閉客戶端
ss.close();// 關閉服務器端
}
}
發送端(客戶端)思路
發送端其實是將資料封裝至發送端socket物件中,然后將socket物件發送至接收端進行接收
1:建立客戶端的Socket服務,并明確要連接的服務器,(new)
2:如果連接建立成功,就表明,已經建立了資料傳輸的通道.就可以在該通道通過IO進行資料的讀取和寫入.該通道稱為Socket流,Socket流中既有讀取流,也有寫入流.
3:通過Socket物件的方法,可以獲取這兩個流
4:通過流的物件可以對資料進行傳輸
5:如果傳輸資料完畢,關閉資源
import java.io.IOException;
import java.io.OutputStream;
import java.net.Socket;
import java.net.UnknownHostException;
//tcp客戶端(發送端)
public class TcpClient {
public static void main(String[] args) throws Exception {
// 1:建立客戶端的Socket服務,并明確要連接的服務器,
Socket s = new Socket("172.16.1.100", 10000);
// 2:如果連接建立成功,就表明,已經建立了資料傳輸的通道.就可以在該通道通過IO進行資料的讀取和寫入.該通道稱為Socket流,Socket流中既有讀取流,也有寫入流.
// 3:通過Socket物件的方法,可以獲取這兩個流
OutputStream os = s.getOutputStream();
// 4:通過流的物件可以對資料進行傳輸
os.write("hello".getBytes());
// 5:如果傳輸資料完畢,關閉資源
os.flush();
os.close();
s.close();
}
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/224253.html
標籤:java
