網絡通信,UDP.TCP協定
網絡通信
計算機網絡
是指将地理位置不同的具有獨立功能的多台計算機及其外部裝置,通過通信線路連接配接起來,在網絡作業系統,網絡管理軟體及網絡通信協定的管理和協調下,實作資源共享和資訊傳遞的計算機系統。
網絡程式設計
就是用來實作網絡互連的不同計算機上運作的程式間可以進行資料交換。
[外鍊圖檔轉存失敗,源站可能有防盜鍊機制,建議将圖檔儲存下來直接上傳

網絡通信三要素
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
建立連接配接,形成傳輸資料的通道;在連接配接中進行大資料量傳輸;通過三次握手完成連接配接,是可靠協定;必須建立連接配接,效率會稍低
資料連接配接協定:資料的發送與接收建立在連接配接通道的基礎上,用戶端連接配接服務端後才可以發送接受請求資料
[外鍊圖檔轉存失敗,源站可能有防盜鍊機制,建議将圖檔儲存下來直接上傳
Socket
Socket套接字:
網絡上具有唯一辨別的IP位址和端口号組合在一起才能構成唯一能識别的辨別符套接字。
Socket原理機制:
通信的兩端都有Socket。
網絡通信其實就是Socket間的通信。
資料在兩個Socket間通過IO傳輸。
[外鍊圖檔轉存失敗,源站可能有防盜鍊機制,建議将圖檔儲存下來直接上傳
使用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();
}
}