關于Java網路編程
計算機網路將地理位置不同的計算機通過通信線路連接起來,實作資源的共享和資訊的傳遞,網路中的計算機通常稱之為主機,而網路編程就是通程序式來實作兩臺以上主機之間的通信,
實際的通信網路內容較多,但是Java語言提供了許多網路類,屏蔽了底層的復雜細節,是程式員可以很容易地撰寫出網路程式,
計算機網路知識基礎
在進行Java網路編程之前,需要對關于計算機網路的總體知識有一個大致的理解,
分層結構模型
眾所周知,計算機網路傳輸實際上是一個很復雜的模型,為了更方便程式開發,我們一般會簡歷網路傳輸模型,將各個不同的層次分隔開,由不同的人來設計不同的層次,這樣設計各個層次的人就不用管其他層面的具體實作,每一層都呼叫它的下一層所提供的網路來完成自己的需求,只需要呼叫別人的服務就可以了,大大提高了作業效率,除此之外,因為各層之間是獨立的,結構上可分割開,所以靈活性好,易于實作和維護,能促進標準化作業:差錯控制,流量控制,分段和重裝,復用和分用,連接建立和釋放,
常見的模型由三種:
1.OSI七層體系

2.五層體系
5層只是OSI和TCP/IP的綜合,是業界產生出來的非官方協議模型,但是很多具體的應用,實際應用還是TCP/IP的四層結構,

3.TCP/IP四層體系

該體系將資料鏈路層和物理層合并為網路介面層,
總結
OSI總結圖

TCP/IP協議與其的關系()

這是其中有關于協議的資料報文格式:

Java網路編程基礎
計算機在網路通信協議中必須遵守一定的規則,就好比車輛行駛要遵守交通規則一樣,在計算機網路協議中,這些連接和通信的規則被稱為網路通信協議,它對傳輸格式,傳輸速率,傳輸步驟做了統一的規定,通信雙方必須遵守這些協議才能進行資料交換;
網路通信協議有很多種,但是目前主要使用的還是TCP/IP、UDP、ICMP和一些其他協議;
IP地址與埠號
要想使計算機能夠通信,必須要為每臺計算機指定標識號,通過標識號來指定接識訓發送資料的計算機,在TCP/IP協議中,這個標識號就是IP地址,目前普遍使用的是4個位元組的IPV4,不過為了解決日漸枯竭的網路地址資源不足,現在16個位元組IPV6也應運而生;
IP地址一般由兩部分組成,是 網路號+主機號,網路號指定網路地址,主機號指定該網路中的主機地址,二者是主從關系;
通過IP地址可以連接到指定計算機,但是如果想要訪問計算機中某個應用程式,還需要指定埠號,在計算機中,不同的應用程式是通過埠號來區分的,埠號是用兩個位元組(16位的二進制數)來表示的,取值范圍為0到65533,但其中0到1023的埠號被系統的網路服務所占有,所以用戶的普通應用的埠號不能屬于這個范圍;
總得來說,一臺計算機可以通過IP地址來訪問到網路中的另一臺計算機,并通過埠號來訪問這個計算機中的某個應用程式;
InetAddress類
這是Java中提供的與IP地址相關的InetAddress類,該類用于封裝IP地址,并提供了一系列與IP地址相關的方法,該類的方法有以下幾個,例如:
InetAddress getByName(String host) 得到IP地址封裝為InetAddress類
InetAddress getLocalHost() 創建一個表示本地主機的InetAddress物件
String getHostName() 得到字串格式的原始IP地址
String getHostHome() 得到確定的IP地址的主機名
boolean isReachable(int timeout) 判斷在指定的時間內地址是否可以到達
TCP和UDP
TCP和UDP是兩個傳輸層的高級協議;
UDP是用戶資料報協議,TCP是傳輸控制協議;
UDP是無連接通信協議,在資料傳輸的時候,資料的發送端和接收端并不建立邏輯連接,簡單來說,當一臺計算機向另外一臺計算機發送資料時,并不好確認接收端是否存在,就直接發送資料,接收端在接受資料的時候,也不會向發送端反饋是否收到資料,
由于UDP消耗資源小,傳輸效率高,,所以通常用于音視頻和普通資料的傳輸,比如說直播視頻,但是由于UDP的無連接性,不能保證資料傳輸的完整性,所以在傳輸重要資料的時候不建議使用UDP,
TCP是面向連接的通信協議,即在傳輸資料的時候先在發送端和接收端建立邏輯連接,然后再傳輸資料;這提供了兩臺計算機之間可靠的,無差錯的資料傳輸;
由于TCP的面向連接的特性,它可以保證資料傳輸的安全性,所以是一個被廣泛采取的協議,比如在下載壓縮包檔案的時候,就非常適合使用TCP連接,
在TCP連接程序中,必須要明確客戶端和服務器端,由客戶端來向服務器端發出連接請求;
每次連接都需要經歷三次握手協議;
三次握手協議:
第一次握手,客戶端向服務器端發出連接請求,等待服務器端的確認;
第二次握手,服務器端向客戶端回復一個回應,通知客戶端收到了連接請求;
第三次握手,客戶端向服務器端發送確認資訊,確認連接;
而在TCP斷開鏈接的時候,就需要用到四次揮手協議
第一次揮手,若A認為資料發送完成,則它需要向B發送連接釋放請求,
第二次揮手,B收到連接釋放請求后,會通知相應的應用程式,告訴它A向B這個方向的連接已經釋放,
第三次揮手,當B向A發完所有資料后,向A發送連接釋放請求
第四次揮手,A收到釋放請求后,向B發送確認應答,
TCP協議作為一個可靠的面向流的傳輸協議,其可靠性和流量控制由滑動視窗協議保證,而擁塞控制則由控制視窗結合一系列的控制演算法實作,以及快重傳和快恢復,超時重傳來確保檔案完整性,
兩者所在層次:

兩者特點比較:

TCP網路編程
ServerSocket
用于建立TCP連接,該類可以實作一個服務端的程式;
1、構造ServerSocket
ServerSocket()throws IOException //ServerSocket有一個不帶引數的默認構造方法,通過該方法創建的ServerSocket不與任何埠系結,接下來還需要通過bind()方法與特定埠系結,這個默認構造方法的用途是,允許服務器在系結到特定埠之前,先設定ServerSocket的一些選項,因為一旦服務器與特定埠系結,有些選項就不能再改變了,
ServerSocket(int port) throws IOException //使服務器與特定埠系結,該埠由引數port指定
ServerSocket(int port, int backlog) throws IOException //引數backlog指定客戶連接請求佇列的長度
ServerSocket(int port, int backlog, InetAddress bindAddr) throws IOException //引數bindAddr指定服務器要系結的IP地址
2.使用ServerSocket進行服務端編程
import java.io.*;
import java.net.*;
import java.util.*;
public class qwe {
public static void main(String[] args) {
ServerSocket server = null; //創建服務器Socket物件
Socket socket = null; //創建Socket物件,用于接收另一端socket的連接
DataInputStream in = null;
DataOutputStream out = null; //準備好IO流
int port = 5050;//設定埠號
try{
server = new ServerSocket(port);
}
catch (IOException e){
System.out.println(e);
}//創建ServerSocket物件,系結5050埠
try{
System.out.println("服務器啟動");
socket = server.accept();//準備監聽Socket連接并接收
in = new DataInputStream(socket.getInputStream());//回傳一個輸入流物件
out = new DataOutputStream(socket.getOutputStream());//回傳一個輸出流物件
//socket之間是通過IO流來互動資訊的
String str = in.readUTF();
System.out.println("收到資訊為:"+str);
out.writeUTF("你好");
}catch(Exception e){
System.out.println(e);
}
finally {
//準備關閉連接
try{
out.close();
in.close();
socket.close();//Socket物件的關閉連接方法
server.close();
}catch (Exception e){
System.out.println(e);
}
}
}
}
Socket(客戶端)
import java.io.*;
import java.net.*;
public class qwe {
public static void main(String[] args){
Socket client = null;
DataInputStream in = null;
DataOutputStream out = null;
String ip = "127.0.0.1";
int port = 5050;
try
{
client = new Socket(ip,port);//客戶端socket系結埠和ip地址
in = new DataInputStream(client.getInputStream());
out = new DataOutputStream(client.getOutputStream());
out.writeUTF("這里是客戶端");
String str = ((DataInputStream) in).readUTF();
System.out.println(str);
}catch (Exception e){
System.out.println(e);
}finally {
try{
in.close();
out.close();
client.close();
}catch (Exception e){
System.out.println(e);
}
}
}
}
UDP網路編程
UDP是一種無連接的不可靠傳輸協議,在使用UDP進行網路連接通信的時候,不需要建立連接,所以速度塊,發送的時候需要封裝成資料包,就像把信件裝入信封,
DatagramPacket
UDP通信程序中并不建立連接,就像是兩個貨運公司在兩個碼頭之間運送貨物一樣,在碼頭發送和接受貨物都需要使用集裝箱來裝載貨物,UDP通信也是一樣,我們需要使用DatagramPacket類,該類的實體物件就相當與一個集裝箱,也可以說是一個信封,我們就利用這個東西對我們需要發送的檔案進行打包發送,總之,這個類是用來發送的,
構造方法:
DatagramPacket(byte[] data, int length) //指定了封裝資訊的位元組陣列大小,以及陣列的長蘇
DatagramPacket(byte[] data, int offset, int length) //在上面的基礎上,增加了offset,用于指定資料的緩沖位置
DatagramPacket(byte[ ] data, int length, InetAddress address, int port) //增加了指定的目標IP地址address和目的埠號port
DatagramPacket(byte[] data, int offset, int length, InetAddress address, int port) //完整版
常用方法:
InetAddress getAddress() //回傳IP地址
int getPort() //回傳埠號
byte[] getData() //回傳打包的資料
int getLength() //回傳資料位元組陣列的長度
DatagramSocket
如果說DatagramPacket相當于一個集裝箱,然而,兩個貨運公司之間的傳輸僅僅使用集裝箱是不夠的,我們還需要一個碼頭進行接收集裝箱,在Java中,我們使用DatagramSocket來當作“碼頭”,使用該類的實體物件就可以接識訓發送DatagramPacket資料包,總之,這個類是用來接收的,
構造方法:
DatagramSocket() //用于創建一個DatagramSocket物件,如果沒有給埠號,系統會從其他應用自動分配一個
DatagramSocket(int port) //指定了埠號,這樣物件可以監聽指定的埠
DatagramSocket(int port,InetAddress addr) //指定了埠號和IP地址,該物件適用與計算機上有多塊網卡的情況,因為計算機針對不同的網卡會分配不同的IP地址,所以指定IP地址就可以確定你到底要使用哪塊網卡來通信
void receive(DatagramPacket p) //接收包
void send(DatagramPacket p) //發送包
void close //關閉
UDP編程實體
import java.io.*;
import java.net.*;
public class qwe {
public static void main(String[] args) {
DatagramSocket socket = null;//碼頭,利用其的send和receive方法來進行發送和接收
DatagramPacket packet_send = null;//集裝箱,用于發送
DatagramPacket packet_receive = null;//集裝箱,用于接收
int port = 5050;
String ipAddress = "127.0.0.1";
try{
socket = new DatagramSocket(port);//建立好連接
byte[] r = bew byte[1024];
packet_receive = new DatagramPacket(r,r.length);
socket.receive(packet_receive);//接受從另一端發送過來的資料
InetAddress address = InetAddress.getByName(ipAddress);//封裝好InetAddress
String str = "服務端發送資料";
byte[] r = str.getBytes();//開始打包
packet_send = new DatagramPacket(r,r.length,address,port);//打包好資料
socket.send(packet_send);//將資料包發送到另一端
}
catch (Exception e)
{
System.out.println(e);
}
finally {
socket.close();//關閉連接
}
}
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/161928.html
標籤:其他
下一篇:視頻編碼
