教學(xué)和實(shí)踐目的:
學(xué)會(huì) WEB 瀏覽器基本的程序設(shè)計(jì)技術(shù)。
概述:
HTTP 系統(tǒng)包括客戶端軟件(瀏覽器)和服務(wù)器軟件(HTTP 服務(wù)器)。早期的客戶端軟件,其主要工作可理解為文件下載和文件顯示。
實(shí)際上現(xiàn)代的 HTTP 客戶端比文件下載要復(fù)雜得多,它包括網(wǎng)頁(yè)文件的下 載、跨平臺(tái)的本地顯示,參數(shù)的傳遞,動(dòng)態(tài)網(wǎng)頁(yè)的實(shí)現(xiàn),以及交互等功能。
HTTP 系統(tǒng)程序設(shè)計(jì):
(1)客戶端軟件(web 瀏覽器軟件如 Edge 瀏覽器、360 瀏覽器)
(2)服務(wù)器軟件(web 服務(wù)器軟件如 IIS、Nginx、Tomcat 等)
HTTP 系統(tǒng)客戶端的工作過(guò)程:
(1)客戶端軟件和服務(wù)器建立連接(TCP 的三次握手)
(2)發(fā)送 HTTP 頭格式協(xié)議
(3)接收網(wǎng)頁(yè)文件
(4)顯示網(wǎng)頁(yè)
?HTTP 系統(tǒng)服務(wù)端的工作過(guò)程:
(1)服務(wù)器軟件開(kāi)啟 80 端口
(2)響應(yīng)客戶的要求、完成 TCP 連接
(3)檢查客戶端的 HTTP 頭格式發(fā)送客戶請(qǐng)求的網(wǎng)頁(yè)文件(含動(dòng)態(tài)網(wǎng)頁(yè))
一個(gè)完整的 HTTP 請(qǐng)求-響應(yīng)如圖所示:
本講主要學(xué)習(xí)網(wǎng)頁(yè)下載程序設(shè)計(jì)技術(shù)。網(wǎng)頁(yè)下載技術(shù)是搜索引擎、網(wǎng)絡(luò)爬 蟲(chóng)、網(wǎng)頁(yè)采集器或網(wǎng)絡(luò)推送服務(wù)等相關(guān)應(yīng)用領(lǐng)域內(nèi)的基礎(chǔ)技術(shù)。
程序設(shè)計(jì)
1、基于 TCP 套接字的網(wǎng)頁(yè)下載程序設(shè)計(jì)
利用 TCP 客戶套接字 Socket 和 HTTP 服務(wù)器進(jìn)行信息交互,將網(wǎng)頁(yè)的原始 內(nèi)容下載顯示在圖形界面中,具體工作如下:
(1)新建一個(gè)包 chapter08,將第 3 講的 TCPClient.java 復(fù)制到此包下, 重命名為 HTTPClient.java;
(2)創(chuàng)建 HTTPClientFX.java 程序,界面如圖 8.2 所示,網(wǎng)頁(yè)地址輸入 www.baidu.com 進(jìn)行測(cè)試,端口為 80,在“連接”按鈕類似以往的編碼方式, 放置連接服務(wù)器的代碼和啟動(dòng)輸入流“讀線程”;在“網(wǎng)頁(yè)請(qǐng)求”按鈕中發(fā)送 HTTP 請(qǐng)求頭標(biāo)準(zhǔn)格式(關(guān)于 HTTP 請(qǐng)求頭的更多信息可查閱互聯(lián)網(wǎng));在“退 出”按鈕中,相對(duì)之前章節(jié)的代碼,不是發(fā)送“bye”表示結(jié)束,而是send("Connection:close" +"\r\n") 表示結(jié)束連接。
現(xiàn)在將網(wǎng)頁(yè)地址改為 www.gdufs.edu.cn,其它不變,再次連接并點(diǎn)擊網(wǎng)頁(yè) 請(qǐng)求,結(jié)果如下圖所示;
這種情況HTTP服務(wù)器確實(shí)有內(nèi)容返回,卻不是我們預(yù)期的內(nèi)容,第一行內(nèi)容為“HTTP/1.1 302 Found”,這種情況一般是站點(diǎn)關(guān)閉了HTTP,只允許啟用了SSL/TLS的HTTPS安全連接,這種連接默認(rèn)是使用443端口。事實(shí)上,出于安全考慮,現(xiàn)在絕大部分的web站點(diǎn)都將放棄HTTP而啟用HTTPS。
2、基于SSL Socket的網(wǎng)頁(yè)下載程序設(shè)計(jì)
要訪問(wèn)HTTPS站點(diǎn),就不能用普通的客戶端套接字,而是使用SSL套接字。Java安全套接字?jǐn)U展(Java Secure Socket Extension,JSSE)為基于SSL和TLS協(xié)議的Java網(wǎng)絡(luò)應(yīng)用程序提供了Java API以及參考實(shí)現(xiàn),相關(guān)的類都定義在javax.net.ssl包下面,我們這里只使用其客戶端的SSLSocket套接字。SSLSocket相對(duì)之前學(xué)習(xí)的客戶端套接字,只是創(chuàng)建方法不同,SSLSocket對(duì)象由SSLSocketFactory創(chuàng)建,創(chuàng)建之后用法幾乎一致。
(1)根據(jù) HTTPClient.java 的內(nèi)容,稍作修改,新創(chuàng)建 HTTPSClient.java 程序,與前者相比,主要區(qū)別的代碼如下:
import javax.net.ssl.SSLSocket;
import javax.net.ssl.SSLSocketFactory;
import java.io.*;
public class HTTPSClient {
//定義 SSL 套接字
private SSLSocket socket;
//定義 SSL 工廠類
private SSLSocketFactory factory;
//定義字符輸入流和輸出流
……
public HTTPSClient(String ip, String port)
throws IOException {
factory =(SSLSocketFactory)SSLSocketFactory.getDefault();
//創(chuàng)建安全套接字實(shí)例
socket = (SSLSocket)factory.createSocket(ip,
Integer.parseInt(port));
//得到網(wǎng)絡(luò)輸出字節(jié)流地址,并封裝成網(wǎng)絡(luò)輸出字符流
……
……
}
……
}
(2)根據(jù) HTTPClientFX.java 程序的內(nèi)容,稍做修改,新創(chuàng)建一個(gè) HTTPSClientFX.java 程序(實(shí)質(zhì)上只需要將原來(lái)的使用 HTTPClient 及其對(duì)象實(shí) 例的的地方修改為使用 HTTPSClient 及其對(duì)象實(shí)例即可)。
(3)運(yùn)行該程序
(4)完全沒(méi)有必要使用兩個(gè)不同的圖形界面來(lái)分別訪問(wèn) http 和 https,創(chuàng) 建一個(gè) HTTPAllClientFX.java,融合以上兩個(gè)圖形客戶端的功能,使得該圖形客 戶端既可訪問(wèn) 443 的 https 內(nèi)容,也可以訪問(wèn)非 443 端口(一般是 80)的 http 內(nèi)容。
3、基于URL類的網(wǎng)頁(yè)下載程序設(shè)計(jì)
前面直接發(fā)送http請(qǐng)求的程序,對(duì)于復(fù)雜的地址,例如指向具體頁(yè)面的地址,無(wú)法完成網(wǎng)頁(yè)下載任務(wù),我們可以使用基于URL類的解決方案。
URL的格式為protocol://資源地址,protocol可以是HTTP、HTTPS、FTP 和 File,資源地址中可以帶有端口號(hào)及查詢參數(shù),具體可以自行搜索URL的知識(shí)。
在java.net包中定義了URL類,該類用來(lái)處理有關(guān)URL的內(nèi)容。并且其封裝有一個(gè)InputStream返回類型的openStream()方法,我們的程序就可以讀取這個(gè)字節(jié)輸入流來(lái)獲得對(duì)應(yīng)內(nèi)容。
發(fā)送按鈕事件響應(yīng)中的關(guān)鍵代碼:
taDisplay.clear();
String address = tfSend.getText().trim();
try {
URL url = new URL(address);
System.out.printf("連接%s 成功!\n", address);
//獲得 url 的字節(jié)流輸入
InputStream in = url.openStream();
//裝飾成字符輸入流
br = new BufferedReader(new InputStreamReader(in, "utf-8"));
//用于接收信息的單獨(dú)線程
…
注意URL方式和直接發(fā)送HTTP請(qǐng)求報(bào)頭的方式,返回結(jié)果有何不同。
(2)完善程序,使得用戶輸入不符合URL語(yǔ)法的網(wǎng)址,你的程序不是拋出異常報(bào)錯(cuò),而是在顯示區(qū)提醒用戶輸入地址不合規(guī),如圖所示。
文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-776998.html
總代碼
文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-776998.html
HTTPAllClientFX
package chapter08;
import javafx.application.Application;
import javafx.application.Platform;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.TextArea;
import javafx.scene.control.TextField;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import java.io.IOException;
public class HTTPAllClientFX extends Application {
private Button btnConnect = new Button("連接");
private Button btnClose = new Button("退出");
private Button btnClear = new Button("清空");
private Button btnHttp = new Button("網(wǎng)頁(yè)請(qǐng)求");
private TextField tfUrl = new TextField("www.gdufs.edu.cn");
private TextField tfPort = new TextField("443");
private TextArea taDisplay = new TextArea();
private HTTPClient httpClient;
private HTTPSClient httpsClient;
Thread readThread;
String url;
String port;
@Override
public void start(Stage primaryStage){
BorderPane mainpane = new BorderPane();
HBox tophbox = new HBox();
tophbox.setSpacing(10);
tophbox.setPadding(new Insets(10,20,10,20));
tophbox.setAlignment(Pos.CENTER);
tophbox.getChildren().addAll(new Label("網(wǎng)頁(yè)地址"),tfUrl,new Label("端口"),tfPort,btnConnect);
VBox vBox = new VBox();
vBox.setPadding(new Insets(10,20,10,20));
vBox.setSpacing(10);
vBox.getChildren().addAll(new Label("信息顯示區(qū)"),taDisplay);
HBox buttomHbox = new HBox();
buttomHbox.setPadding(new Insets(10,20,10,20));
buttomHbox.setSpacing(10);
buttomHbox.setAlignment(Pos.CENTER_RIGHT);
buttomHbox.getChildren().addAll(btnHttp,btnClear,btnClose);
mainpane.setTop(tophbox);
mainpane.setCenter(vBox);
mainpane.setBottom(buttomHbox);
Scene scene = new Scene(mainpane,800,400);
primaryStage.setScene(scene);
primaryStage.show();
btnConnect.setOnAction(event -> {
url = tfUrl.getText().trim();
port = tfPort.getText().trim();
if(port.equals("443")) {
try {
httpsClient = new HTTPSClient(url, port);
taDisplay.appendText("服務(wù)器啟動(dòng)");
// 多線程不需要這一條了
// String firstMsg = tcpClient.receive();
// taDisplay.appendText(firstMsg+"\n");
// btnConnect.setDisable(true);
//多線程方法
readThread = new Thread(() -> {
String msg = null;
while ((msg = httpsClient.receive()) != null) {
String msgTemp = msg;
Platform.runLater(() -> {
taDisplay.appendText(msgTemp + "\n");
});
}
Platform.runLater(() -> {
taDisplay.appendText("對(duì)話已關(guān)閉!\n");
});
});
readThread.start();
} catch (IOException e) {
taDisplay.appendText("服務(wù)器連接失敗" + e.getMessage() + "\n");
}
}
else {
try {
httpClient = new HTTPClient(url, port);
taDisplay.appendText("服務(wù)器啟動(dòng)");
readThread = new Thread(() -> {
String msg = null;
while ((msg = httpClient.receive()) != null) {
String msgTemp = msg;
Platform.runLater(() -> {
taDisplay.appendText(msgTemp + "\n");
});
}
Platform.runLater(() -> {
taDisplay.appendText("對(duì)話已關(guān)閉!\n");
});
});
readThread.start();
} catch (IOException e) {
taDisplay.appendText("服務(wù)器連接失敗" + e.getMessage() + "\n");
}
}
});
btnHttp.setOnAction(event -> {
StringBuffer msg = new StringBuffer("GET / HTTP/1.1" + "\r\n"); //
// StringBuffer msg = new StringBuffer("GET / connecttest.txt HTTP/1.1 " + "\r\n"); //注意/后面需要有空格
msg.append("HOST:" + url + "\r\n");
msg.append("Accept: */*" + "\r\n");
msg.append("Accept-Language: zh-cn" + "\r\n");
msg.append("Accept-Encoding: deflate" + "\r\n");
msg.append("User-Agent:Mozilla/4.0(compatible;MSIE6.0;Windows XP)" + "\r\n");
msg.append("Connection:Keep-Alive" + "\r\n");
//msg.append
if(port.equals("443")){
httpsClient.send(msg.toString());
}else{
httpClient.send(msg.toString());
}
});
btnClear.setOnAction(event -> {
taDisplay.clear();
});
btnClose.setOnAction(event -> {
if(httpClient != null){
//向服務(wù)器發(fā)送關(guān)閉連接的約定信息
httpClient.send("bye");
httpClient.close();
}else if(httpsClient != null){
//向服務(wù)器發(fā)送關(guān)閉連接的約定信息
httpsClient.send("bye");
httpsClient.close();
}
System.exit(0);
});
}
}
HTTPClient
package chapter08;
import java.io.*;
import java.net.Socket;
public class HTTPClient {
private Socket socket; //定義套接字
//定義字符輸入流和輸出流
private PrintWriter pw;
private BufferedReader br;
public HTTPClient(String ip, String port) throws IOException {
//主動(dòng)向服務(wù)器發(fā)起連接,實(shí)現(xiàn)TCP的三次握手過(guò)程
//如果不成功,則拋出錯(cuò)誤信息,其錯(cuò)誤信息交由調(diào)用者處理
socket = new Socket(ip, Integer.parseInt(port));
//得到網(wǎng)絡(luò)輸出字節(jié)流地址,并封裝成網(wǎng)絡(luò)輸出字符流
OutputStream socketOut = socket.getOutputStream();
pw = new PrintWriter( // 設(shè)置最后一個(gè)參數(shù)為true,表示自動(dòng)flush數(shù)據(jù)
new OutputStreamWriter(//設(shè)置utf-8編碼
socketOut, "utf-8"), true);
//得到網(wǎng)絡(luò)輸入字節(jié)流地址,并封裝成網(wǎng)絡(luò)輸入字符流
InputStream socketIn = socket.getInputStream();
br = new BufferedReader(
new InputStreamReader(socketIn, "utf-8"));
}
public void send(String msg) {
//輸出字符流,由Socket調(diào)用系統(tǒng)底層函數(shù),經(jīng)網(wǎng)卡發(fā)送字節(jié)流
pw.println(msg);
}
public String receive() {
String msg = null;
try {
//從網(wǎng)絡(luò)輸入字符流中讀信息,每次只能接受一行信息
//如果不夠一行(無(wú)行結(jié)束符),則該語(yǔ)句阻塞等待,
// 直到條件滿足,程序才往下運(yùn)行
msg = br.readLine();
} catch (IOException e) {
e.printStackTrace();
}
return msg;
}
public void close() {
try {
if (socket != null) {
//關(guān)閉socket連接及相關(guān)的輸入輸出流,實(shí)現(xiàn)四次握手?jǐn)嚅_(kāi)
socket.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args) throws IOException{
HTTPClient tcpClient = new HTTPClient("127.0.0.1", "8008");
tcpClient.send("hello");
System.out.println(tcpClient.receive());
}
}
HTTPClientFX
package chapter08;
import javafx.application.Application;
import javafx.application.Platform;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.TextArea;
import javafx.scene.control.TextField;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import java.io.IOException;
public class HTTPClientFX extends Application{
private Button btnConnect = new Button("連接");
private Button btnClose = new Button("退出");
private Button btnClear = new Button("清空");
private Button btnHttp = new Button("網(wǎng)頁(yè)請(qǐng)求");
private TextField tfUrl = new TextField();
private TextField tfPort = new TextField();
private TextArea taDisplay = new TextArea();
private HTTPClient httpClient;
Thread readThread;
@Override
public void start(Stage primaryStage){
BorderPane mainpane = new BorderPane();
HBox tophbox = new HBox();
tophbox.setSpacing(10);
tophbox.setPadding(new Insets(10,20,10,20));
tophbox.setAlignment(Pos.CENTER);
tophbox.getChildren().addAll(new Label("網(wǎng)頁(yè)地址"),tfUrl,new Label("端口"),tfPort,btnConnect);
VBox vBox = new VBox();
vBox.setPadding(new Insets(10,20,10,20));
vBox.setSpacing(10);
vBox.getChildren().addAll(new Label("信息顯示區(qū)"),taDisplay);
HBox buttomHbox = new HBox();
buttomHbox.setPadding(new Insets(10,20,10,20));
buttomHbox.setSpacing(10);
buttomHbox.setAlignment(Pos.CENTER_RIGHT);
buttomHbox.getChildren().addAll(btnHttp,btnClear,btnClose);
mainpane.setTop(tophbox);
mainpane.setCenter(vBox);
mainpane.setBottom(buttomHbox);
Scene scene = new Scene(mainpane,800,400);
primaryStage.setScene(scene);
primaryStage.show();
btnConnect.setOnAction(event -> {
String url = tfUrl.getText().trim();
String port = tfPort.getText().trim();
try {
httpClient = new HTTPClient(url,port);
// 多線程不需要這一條了
// String firstMsg = tcpClient.receive();
// taDisplay.appendText(firstMsg+"\n");
// btnConnect.setDisable(true);
//多線程方法
readThread = new Thread(()->{
String msg = null;
while((msg = httpClient.receive())!=null){
String msgTemp = msg;
Platform.runLater(()->{
taDisplay.appendText(msgTemp+"\n");
});
}
Platform.runLater(()->{
taDisplay.appendText("對(duì)話已關(guān)閉!\n");
});
});
readThread.start();
} catch (IOException e) {
taDisplay.appendText("服務(wù)器連接失敗"+e.getMessage()+"\n");
}
});
btnHttp.setOnAction(event -> {
String ip = tfUrl.getText();
StringBuffer msg = new StringBuffer("GET / HTTP/1.1" + "\r\n"); //
// StringBuffer msg = new StringBuffer("GET / connecttest.txt HTTP/1.1 " + "\r\n"); //注意/后面需要有空格
msg.append("HOST:" + ip + "\r\n");
msg.append("Accept: */*" + "\r\n");
msg.append("Accept-Language: zh-cn" + "\r\n");
msg.append("Accept-Encoding: deflate" + "\r\n");
msg.append("User-Agent:Mozilla/4.0(compatible;MSIE6.0;Windows XP)" + "\r\n");
msg.append("Connection:Keep-Alive" + "\r\n");
//msg.append
httpClient.send(msg.toString());
});
}
}
HTTPSClient
package chapter08;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.SSLSocketFactory;
import java.io.*;
public class HTTPSClient {
private SSLSocket socket; //定義套接字
private SSLSocketFactory factory;
//定義字符輸入流和輸出流
private PrintWriter pw;
private BufferedReader br;
public HTTPSClient(String ip, String port) throws IOException {
//主動(dòng)向服務(wù)器發(fā)起連接,實(shí)現(xiàn)TCP的三次握手過(guò)程
//如果不成功,則拋出錯(cuò)誤信息,其錯(cuò)誤信息交由調(diào)用者處理
factory=(SSLSocketFactory)SSLSocketFactory.getDefault();
socket=(SSLSocket)factory.createSocket(ip,Integer.parseInt(port));
//得到網(wǎng)絡(luò)輸出字節(jié)流地址,并封裝成網(wǎng)絡(luò)輸出字符流
OutputStream socketOut = socket.getOutputStream();
pw = new PrintWriter( // 設(shè)置最后一個(gè)參數(shù)為true,表示自動(dòng)flush數(shù)據(jù)
new OutputStreamWriter(//設(shè)置utf-8編碼
socketOut, "utf-8"), true);
//得到網(wǎng)絡(luò)輸入字節(jié)流地址,并封裝成網(wǎng)絡(luò)輸入字符流
InputStream socketIn = socket.getInputStream();
br = new BufferedReader(
new InputStreamReader(socketIn, "utf-8"));
}
public void send(String msg) {
//輸出字符流,由Socket調(diào)用系統(tǒng)底層函數(shù),經(jīng)網(wǎng)卡發(fā)送字節(jié)流
pw.println(msg);
}
public String receive() {
String msg = null;
try {
//從網(wǎng)絡(luò)輸入字符流中讀信息,每次只能接受一行信息
//如果不夠一行(無(wú)行結(jié)束符),則該語(yǔ)句阻塞,
// 直到條件滿足,程序才往下運(yùn)行
msg = br.readLine();
} catch (IOException e) {
e.printStackTrace();
}
return msg;
}
public void close() {
try {
if (socket != null) {
//關(guān)閉socket連接及相關(guān)的輸入輸出流,實(shí)現(xiàn)四次握手?jǐn)嚅_(kāi)
socket.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
//本機(jī)模塊內(nèi)測(cè)試與運(yùn)行,需先運(yùn)行TCPServer
public static void main(String[] args) throws IOException {
HTTPSClient tcpClient = new HTTPSClient("127.0.0.1" ,"8008");
tcpClient.send("hello");//發(fā)送一串字符
//接收服務(wù)器返回的字符串并顯示
System.out.println(tcpClient.receive());
}
}
HTTPSClientFX
package chapter08;
import javafx.application.Application;
import javafx.application.Platform;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.TextArea;
import javafx.scene.control.TextField;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import java.io.IOException;
public class HTTPSClientFX extends Application{
private Button btnConnect = new Button("連接");
private Button btnClose = new Button("退出");
private Button btnClear = new Button("清空");
private Button btnHttp = new Button("網(wǎng)頁(yè)請(qǐng)求");
private TextField tfUrl = new TextField();
private TextField tfPort = new TextField();
private TextArea taDisplay = new TextArea();
private HTTPSClient httpsClient;
Thread readThread;
@Override
public void start(Stage primaryStage){
BorderPane mainpane = new BorderPane();
HBox tophbox = new HBox();
tophbox.setSpacing(10);
tophbox.setPadding(new Insets(10,20,10,20));
tophbox.setAlignment(Pos.CENTER);
tophbox.getChildren().addAll(new Label("網(wǎng)頁(yè)地址"),tfUrl,new Label("端口"),tfPort,btnConnect);
VBox vBox = new VBox();
vBox.setPadding(new Insets(10,20,10,20));
vBox.setSpacing(10);
vBox.getChildren().addAll(new Label("信息顯示區(qū)"),taDisplay);
HBox buttomHbox = new HBox();
buttomHbox.setPadding(new Insets(10,20,10,20));
buttomHbox.setSpacing(10);
buttomHbox.setAlignment(Pos.CENTER_RIGHT);
buttomHbox.getChildren().addAll(btnHttp,btnClear,btnClose);
mainpane.setTop(tophbox);
mainpane.setCenter(vBox);
mainpane.setBottom(buttomHbox);
Scene scene = new Scene(mainpane,800,400);
primaryStage.setScene(scene);
primaryStage.show();
btnConnect.setOnAction(event -> {
String url = tfUrl.getText().trim();
String port = tfPort.getText().trim();
try {
httpsClient = new HTTPSClient(url,port);
// 多線程不需要這一條了
// String firstMsg = tcpClient.receive();
// taDisplay.appendText(firstMsg+"\n");
// btnConnect.setDisable(true);
//多線程方法
readThread = new Thread(()->{
String msg = null;
while((msg = httpsClient.receive())!=null){
String msgTemp = msg;
Platform.runLater(()->{
taDisplay.appendText(msgTemp+"\n");
});
}
Platform.runLater(()->{
taDisplay.appendText("對(duì)話已關(guān)閉!\n");
});
});
readThread.start();
} catch (IOException e) {
taDisplay.appendText("服務(wù)器連接失敗"+e.getMessage()+"\n");
}
});
btnHttp.setOnAction(event -> {
String ip = tfUrl.getText();
StringBuffer msg = new StringBuffer("GET / HTTP/1.1" + "\r\n"); //
// StringBuffer msg = new StringBuffer("GET / connecttest.txt HTTP/1.1 " + "\r\n"); //注意/后面需要有空格
msg.append("HOST:" + ip + "\r\n");
msg.append("Accept: */*" + "\r\n");
msg.append("Accept-Language: zh-cn" + "\r\n");
msg.append("Accept-Encoding: deflate" + "\r\n");
msg.append("User-Agent:Mozilla/4.0(compatible;MSIE6.0;Windows XP)" + "\r\n");
msg.append("Connection:Keep-Alive" + "\r\n");
//msg.append
httpsClient.send(msg.toString());
});
}
}
URLClientFX
package chapter08;
import javafx.application.Application;
import javafx.application.Platform;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.TextArea;
import javafx.scene.control.TextField;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Priority;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;
public class URLClientFX extends Application{
private Button btnClose = new Button("退出");
private Button btnClear = new Button("清空");
private Button btnHttp = new Button("發(fā)送");
private TextField tfUrl = new TextField();
private TextArea taDisplay = new TextArea();
private HTTPClient httpClient;
Thread readThread;
BufferedReader br;
@Override
public void start(Stage primaryStage){
BorderPane mainpane = new BorderPane();
taDisplay.setWrapText(true);
VBox vBox = new VBox();
vBox.setPadding(new Insets(10,20,10,20));
vBox.setSpacing(10);
vBox.getChildren().addAll(new Label("網(wǎng)頁(yè)信息顯示區(qū)"),taDisplay,new Label("輸入U(xiǎn)RL地址"),tfUrl);
VBox.setVgrow(taDisplay, Priority.ALWAYS);
HBox buttomHbox = new HBox();
buttomHbox.setPadding(new Insets(10,20,10,20));
buttomHbox.setSpacing(10);
buttomHbox.setAlignment(Pos.CENTER_RIGHT);
buttomHbox.getChildren().addAll(btnHttp,btnClear,btnClose);
mainpane.setCenter(vBox);
mainpane.setBottom(buttomHbox);
Scene scene = new Scene(mainpane,800,400);
primaryStage.setScene(scene);
primaryStage.show();
btnClear.setOnAction(event -> {
taDisplay.clear();
});
btnHttp.setOnAction(event -> {
taDisplay.clear();
try {
String ip = tfUrl.getText();
if (!isURL(ip)) {
taDisplay.appendText("當(dāng)前url不合法");
} else {
URL url = new URL(ip);
System.out.println("連接成功!");
InputStream in = url.openStream();
br = new BufferedReader(new InputStreamReader(in, "utf-8"));
// readThread=new Thread(){
// String msg =null;
// while((msg=br.readLine())!=null){
// taDisplay.appendText(msg.toString());
// }
// };
readThread = new Thread(() -> {
String msg;
//不知道服務(wù)器有多少回傳信息,就持續(xù)不斷接收
//由于在另外一個(gè)線程,不會(huì)阻塞主線程的正常運(yùn)行
try {
while ((msg = br.readLine()) != null) {
//lambda表達(dá)式不能直接訪問(wèn)外部非final類型局部變量
//所以這里使用了一個(gè)臨時(shí)變量
String msgTemp = msg;
Platform.runLater(() -> {
taDisplay.appendText(msgTemp + "\r\n");
});
}
} catch (IOException e) {
e.printStackTrace();
}
//跳出了循環(huán),說(shuō)明服務(wù)器已關(guān)閉,讀取為null,提示對(duì)話關(guān)閉
Platform.runLater(() -> {
taDisplay.appendText("對(duì)話已關(guān)閉!\n");
});
});
readThread.start();
}
}catch(IOException e) {
e.printStackTrace();
}
});
}
public static boolean isURL(String str){
//轉(zhuǎn)換為小寫(xiě)
str = str.toLowerCase();
String regex = "^((https|http|ftp|rtsp|mms)?://)" //https、http、ftp、rtsp、mms
+ "(([0-9a-z_!~*'().&=+$%-]+: )?[0-9a-z_!~*'().&=+$%-]+@)?" //ftp的user@
+ "(([0-9]{1,3}\\.){3}[0-9]{1,3}" // IP形式的URL- 例如:199.194.52.184
+ "|" // 允許IP和DOMAIN(域名)
+ "([0-9a-z_!~*'()-]+\\.)*" // 域名- www.
+ "([0-9a-z][0-9a-z-]{0,61})?[0-9a-z]\\." // 二級(jí)域名
+ "[a-z]{2,6})" // first level domain- .com or .museum
+ "(:[0-9]{1,5})?" // 端口號(hào)最大為65535,5位數(shù)
+ "((/?)|" // a slash isn't required if there is no file name
+ "(/[0-9a-z_!~*'().;?:@&=+$,%#-]+)+/?)$";
return str.matches(regex);
}
}
到了這里,關(guān)于互聯(lián)網(wǎng)程序設(shè)計(jì)--HTTP程序設(shè)計(jì)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!