12、網路程式設計
12、網路程式設計
概述:
網路程式設計中的兩個主要問題:
-
如何準確定位網路上的主機,定位主機上的應用:
- IP + 埠號
-
找到主機後如何可靠高效的進行資料傳輸:
-
網路通訊協議 TCP/IP參考模型:
-
通訊要素一:IP和埠號:
IP:唯一標識Internet上的計算機 (127.0.0.1本地迴環地址)
IP分類:IPv4 與 IPv6 ;全球資訊網 與 區域網
Java中 InetAddress類 代表IP,
//例項化InetAddress getByName(String host)//ip 或 域名 getLocalhost() //獲取本機地址 //兩個常用方法 .getHostName() .getHostAddress()
埠號: 標識正在計算機上執行的程序(程式) 0~65535。
公認埠 0~1023 ,註冊埠 1024~49151,動態/私有埠 49152~65535 埠號與IP 地址的組合得出一個網路套接字:Socket。
通訊要素二:網路通訊協議:
TCP 協議:(傳輸控制協議)
使用TCP協議前,須先建立TCP連線,形成傳輸資料通道
傳輸前,採用“ 三次握手”方式,點對點通訊,是可靠的
TCP協議進行通訊的兩個應用程序:客戶端、服務端。
在連線中可進行大資料量的傳輸
傳輸完畢,需釋放已建立的連線,效率低
UDP 協議:(使用者資料報協議)
將資料、源、目的封裝成資料包,不需要建立連線
每個資料報的大小限制在64K內
傳送不管對方是否準備好,接收方收到也不確認,故是不可靠的
可以廣播發送
傳送資料結束時無需釋放資源,開銷小,速度快Socket:
把網路連線當成一個流,資料在兩個Socket間通過IO傳輸
流套接字(stream socket):使用TCP提供可依賴的位元組流服務
資料報套接字(datagram socket):使用UDP提供“盡力而為”的資料報服務
TCP網路程式設計
客戶端:
- 建立Socket物件,指明伺服器端的 ip 和 埠號
- 獲取一個輸出流,用於輸出資料
- 寫出資料操作
- 關閉資源
客戶端:
- 建立伺服器端的 ServerSocke,指明自己的埠號
- 呼叫accept( ) 表示接收來自客戶端的socke
- 讀取輸入流中的資料
- 關閉資源
傳輸檔案:
public void client() throws Exception {
//1.建立socket物件,指明伺服器端的 ip+埠
Socket socket = new Socket(InetAddress.getLocalHost(), 4545);
//2.獲取輸出流 ,寫出資料
OutputStream os = socket.getOutputStream();
FileInputStream fis = new FileInputStream("1.jpg"); //獲取圖片資料
int len;
byte[] buffer = new byte[1024];
while ( (len=fis.read(buffer))!=-1 ){
os.write(buffer,0,len); //寫入輸出流
}
//3.關閉資源
fis.close();
os.close();
socket.close();
}
public void server() throws Exception {
//1.建立伺服器端的 ServerSocket,指明自己的埠號
ServerSocket ss = new ServerSocket(4545);
//2.呼叫accept() 表示接收來自客戶端的socket
Socket socket = ss.accept();
//3.獲取輸出流中的資料
InputStream is = socket.getInputStream();
FileOutputStream fos = new FileOutputStream("2.jpg");
int len;
byte[] buffer = new byte[1024];
while ( (len=is.read(buffer))!=-1 ){
fos.write(buffer,0,len);
}
//4.關閉資源
fos.close();
is.close();
socket.close();
ss.close();
}
伺服器接收完檔案後,給客戶端返回資訊:
public void client() throws Exception {
//1.建立socket物件,指明伺服器端的 ip+埠
Socket socket = new Socket(InetAddress.getLocalHost(), 4545);
//2.獲取輸出流 ,寫出資料
OutputStream os = socket.getOutputStream();
FileInputStream fis = new FileInputStream("1.jpg"); //獲取圖片資料
int len;
byte[] buffer = new byte[1024];
while ( (len=fis.read(buffer))!=-1 ){
os.write(buffer,0,len); //寫入輸出流
}
//通知伺服器,傳輸完畢
socket.shutdownOutput(); //表示客戶端傳輸完畢,不再輸出資料,服務端可以傳送資料
//接收伺服器返回的資訊 並列印
InputStream is = socket.getInputStream();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
while ( (len=is.read(buffer))!=-1 ){
baos.write(buffer,0,len);
}
System.out.println(baos.toString());
//3.關閉資源
fis.close();
os.close();
socket.close();
baos.close();is.close();
}
public void server() throws Exception {
//1.建立伺服器端的 ServerSocket,指明自己的埠號
ServerSocket ss = new ServerSocket(4545);
//2.呼叫accept() 表示接收來自客戶端的socket
Socket socket = ss.accept();
//3.獲取輸出流中的資料
InputStream is = socket.getInputStream();
FileOutputStream fos = new FileOutputStream("2.jpg");
int len;
byte[] buffer = new byte[1024];
while ( (len=is.read(buffer))!=-1 ){ //read是一個阻塞式方法,需要標識是否傳輸完畢
fos.write(buffer,0,len);
}
//接收完成後,給客戶端傳送資訊
OutputStream os = socket.getOutputStream();
os.write("照片接收已完成~".getBytes());
//4.關閉資源
fos.close();
is.close();
socket.close();
ss.close();
os.close();
}
UDP網路程式設計
- DatagramSocket與DatagramPacket
- 建立傳送端,接收端
- 建立資料包
- 呼叫Socket的傳送、接收方法
- 關閉Socket
傳送端與接收端是兩個獨立的執行程式
public void sender() throws Exception {
//1.建立一個Socket
DatagramSocket socket = new DatagramSocket();
//2.建包,封裝資料
byte[] data = "我是UDP連線方式~".getBytes();
InetAddress ip = InetAddress.getLocalHost();
//封裝資料報 DatePacket(位元組資料,資料開始,資料結束,ip,埠)
DatagramPacket packet = new DatagramPacket(data,0,data.length,ip,5454);
//3.傳送包
socket.send(packet);
//4.關閉資源
socket.close();
}
public void receiver() throws IOException {
//1.建立socket物件,指明埠號
DatagramSocket socket = new DatagramSocket(5454);
//2.建包,準備接收資料
byte[] buffer = new byte[1024];
DatagramPacket packet = new DatagramPacket(buffer,0,buffer.length);
//3.接收資料
socket.receive(packet); //此時資料已經存在 buffer中了
// System.out.println(new String(packet.getData(),0,packet.getLength()));
System.out.println(new String(buffer,0,buffer.length));
//4.關閉資源
socket.close();
}
URL網路程式設計
URL(Uniform Resource Locator):統一資源定位符,定位 Internet 上某一資源的地址。
URL由五部分組成:
傳輸協議://主機名: 埠號/檔名 #片段名 ?引數列表
常用方法:
public String getProtocol( ) 獲取該URL的協議名
public String getHost( ) 獲取該URL的主機名
public String getPort( ) 獲取該URL的埠號
public String getPath( ) 獲取該URL的檔案路徑
public String getFile( ) 獲取該URL的檔名
public String getQuery( ) 獲取該URL的查詢名
下載網站資源
public void URL_download() throws Exception{
//1.建立URL物件,獲取連線物件
String ur = "http://m10.music.126.net/20220407201631/edf99a1e630704529b26cfb1cadddab5/ymusic/560e/5352/0f5b/ad656bf54ad8b8b421b4811622f27cb7.mp3";
URL url = new java.net.URL(ur);
HttpURLConnection urlConnection = (HttpURLConnection)url.openConnection();
urlConnection.connect();
//2.獲取網站資源
InputStream is = urlConnection.getInputStream();
FileOutputStream fos = new FileOutputStream("url.jpg");
byte[] buffer = new byte[1024];
int len;
while ( (len=is.read(buffer))!=-1 ){
fos.write(buffer,0,len);
}
//3.關閉資源,關閉連線
fos.close();
is.close();
urlConnection.disconnect();
}
PS: 附:忽略網站信任證書 工具類:HttpsURLValidator
點選檢視程式碼
/** 忽略證書信任問題
* 一個信任 https證書的工具類,
在urlConnection請求前 加入一條語句 : HttpsURLValidator.httpsRequestTrue(url); //url為https請求地址
*/
//import lombok.extern.slf4j.Slf4j;
import sun.net.www.protocol.https.HttpsURLConnectionImpl;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLSession;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
//@Slf4j
public class HttpsURLValidator {
HostnameVerifier hv = new HostnameVerifier() {
public boolean verify(String urlHostName, SSLSession session) {
System.out.println("Warning: URL Host: " + urlHostName + " vs. "
+ session.getPeerHost());
return true;
}
};
/**
* https忽略SSL的方法
* @param url
*/
public static void httpsRequestTrue(String url){//訪問https地址直接呼叫這個方法
try {
//忽略https證書的再請求
HttpsURLValidator.trustAllHttpsCertificates();
HostnameVerifier hv = new HostnameVerifier() {
public boolean verify(String urlHostName, SSLSession session) {
return true;
}
};
URL u = new URL(url);
HttpsURLConnection.setDefaultHostnameVerifier(hv);
URLConnection urlConnection = (HttpsURLConnectionImpl)u.openConnection();
}catch (Exception e){
e.printStackTrace();
// log.error(e.getMessage());
}
}
protected final String retrieveResponseFromServer(final URL validationUrl,
final String ticket) {
HttpURLConnection connection = null;
try {
connection = (HttpURLConnection) validationUrl.openConnection();
final BufferedReader in = new BufferedReader(new InputStreamReader(
connection.getInputStream()));
String line;
final StringBuffer stringBuffer = new StringBuffer(255);
synchronized (stringBuffer) {
while ((line = in.readLine()) != null) {
stringBuffer.append(line);
stringBuffer.append("\n");
}
return stringBuffer.toString();
}
} catch (final IOException e) {
// log.error(e.getMessage());
e.printStackTrace();
return null;
} catch (final Exception e1){
// log.error(e1.getMessage());
e1.printStackTrace();
return null;
}finally {
if (connection != null) {
connection.disconnect();
}
}
}
protected static void trustAllHttpsCertificates() throws Exception {
javax.net.ssl.TrustManager[] trustAllCerts = new javax.net.ssl.TrustManager[1];
javax.net.ssl.TrustManager tm = new miTM();
trustAllCerts[0] = tm;
javax.net.ssl.SSLContext sc = javax.net.ssl.SSLContext
.getInstance("SSL");
sc.init(null, trustAllCerts, null);
javax.net.ssl.HttpsURLConnection.setDefaultSSLSocketFactory(sc
.getSocketFactory());
}
static class miTM implements javax.net.ssl.TrustManager,
javax.net.ssl.X509TrustManager {
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
return null;
}
public boolean isServerTrusted(
java.security.cert.X509Certificate[] certs) {
return true;
}
public boolean isClientTrusted(
java.security.cert.X509Certificate[] certs) {
return true;
}
public void checkServerTrusted(
java.security.cert.X509Certificate[] certs, String authType)
throws java.security.cert.CertificateException {
return;
}
public void checkClientTrusted(
java.security.cert.X509Certificate[] certs, String authType)
throws java.security.cert.CertificateException {
return;
}
}
}