互联网程序设计--HTTP程序设计

教学和实践目的:

学会 WEB 浏览器基本的程序设计技术。

概述:

HTTP 系统包括客户端软件(浏览器)和服务器软件(HTTP 服务器)。早期的客户端软件,其主要工作可理解为文件下载和文件显示。

实际上现代的 HTTP 客户端比文件下载要复杂得多,它包括网页文件的下 载、跨平台的本地显示,参数的传递,动态网页的实现,以及交互等功能。

HTTP 系统程序设计:

(1)客户端软件(web 浏览器软件如 Edge 浏览器、360 浏览器)

(2)服务器软件(web 服务器软件如 IIS、Nginx、Tomcat 等)

HTTP 系统客户端的工作过程:

(1)客户端软件和服务器建立连接(TCP 的三次握手)

(2)发送 HTTP 头格式协议

(3)接收网页文件

(4)显示网页

 HTTP 系统服务端的工作过程:

(1)服务器软件开启 80 端口

(2)响应客户的要求、完成 TCP 连接

(3)检查客户端的 HTTP 头格式发送客户请求的网页文件(含动态网页)

一个完整的 HTTP 请求-响应如图所示:

本讲主要学习网页下载程序设计技术。网页下载技术是搜索引擎、网络爬 虫、网页采集器或网络推送服务等相关应用领域内的基础技术。

程序设计

1、基于 TCP 套接字的网页下载程序设计

利用 TCP 客户套接字 Socket 和 HTTP 服务器进行信息交互,将网页的原始 内容下载显示在图形界面中,具体工作如下:

(1)新建一个包 chapter08,将第 3 讲的 TCPClient.java 复制到此包下, 重命名为 HTTPClient.java;

(2)创建 HTTPClientFX.java 程序,界面如图 8.2 所示,网页地址输入 www.baidu.com 进行测试,端口为 80,在“连接”按钮类似以往的编码方式, 放置连接服务器的代码和启动输入流“读线程”;在“网页请求”按钮中发送 HTTP 请求头标准格式(关于 HTTP 请求头的更多信息可查阅互联网);在“退 出”按钮中,相对之前章节的代码,不是发送“bye”表示结束,而是send("Connection:close" +"\r\n") 表示结束连接。

现在将网页地址改为 www.gdufs.edu.cn,其它不变,再次连接并点击网页 请求,结果如下图所示;

这种情况HTTP服务器确实有内容返回,却不是我们预期的内容,第一行内容为“HTTP/1.1 302 Found”,这种情况一般是站点关闭了HTTP,只允许启用了SSL/TLS的HTTPS安全连接,这种连接默认是使用443端口。事实上,出于安全考虑,现在绝大部分的web站点都将放弃HTTP而启用HTTPS。

2、基于SSL Socket的网页下载程序设计

要访问HTTPS站点,就不能用普通的客户端套接字,而是使用SSL套接字。Java安全套接字扩展(Java Secure Socket Extension,JSSE)为基于SSL和TLS协议的Java网络应用程序提供了Java API以及参考实现,相关的类都定义在javax.net.ssl包下面,我们这里只使用其客户端的SSLSocket套接字。SSLSocket相对之前学习的客户端套接字,只是创建方法不同,SSLSocket对象由SSLSocketFactory创建,创建之后用法几乎一致。

(1)根据 HTTPClient.java 的内容,稍作修改,新创建 HTTPSClient.java 程序,与前者相比,主要区别的代码如下:

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();
//创建安全套接字实例
 socket = (SSLSocket)factory.createSocket(ip,
 Integer.parseInt(port));
 //得到网络输出字节流地址,并封装成网络输出字符流
 ……
 ……
 }
 ……
 }

(2)根据 HTTPClientFX.java 程序的内容,稍做修改,新创建一个 HTTPSClientFX.java 程序(实质上只需要将原来的使用 HTTPClient 及其对象实 例的的地方修改为使用 HTTPSClient 及其对象实例即可)。

(3)运行该程序

(4)完全没有必要使用两个不同的图形界面来分别访问 http 和 https,创 建一个 HTTPAllClientFX.java,融合以上两个图形客户端的功能,使得该图形客 户端既可访问 443 的 https 内容,也可以访问非 443 端口(一般是 80)的 http 内容。

3、基于URL类的网页下载程序设计

前面直接发送http请求的程序,对于复杂的地址,例如指向具体页面的地址,无法完成网页下载任务,我们可以使用基于URL类的解决方案。

URL的格式为protocol://资源地址,protocol可以是HTTP、HTTPS、FTP 和 File,资源地址中可以带有端口号及查询参数,具体可以自行搜索URL的知识。

在java.net包中定义了URL类,该类用来处理有关URL的内容。并且其封装有一个InputStream返回类型的openStream()方法,我们的程序就可以读取这个字节输入流来获得对应内容。

发送按钮事件响应中的关键代码:

taDisplay.clear();
String address = tfSend.getText().trim();
 try {
URL url = new URL(address);
System.out.printf("连接%s 成功!\n", address);
 //获得 url 的字节流输入
 InputStream in = url.openStream();
 //装饰成字符输入流
 br = new BufferedReader(new InputStreamReader(in, "utf-8"));
 //用于接收信息的单独线程
 …

注意URL方式和直接发送HTTP请求报头的方式,返回结果有何不同。

(2)完善程序,使得用户输入不符合URL语法的网址,你的程序不是抛出异常报错,而是在显示区提醒用户输入地址不合规,如图所示。

总代码

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("网页请求");
  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("网页地址"),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("信息显示区"),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("服务器启动");
          // 多线程不需要这一条了
//                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("对话已关闭!\n");
            });
          });
          readThread.start();
        } catch (IOException e) {
          taDisplay.appendText("服务器连接失败" + e.getMessage() + "\n");
        }
      }

      else {
        try {
          httpClient = new HTTPClient(url, port);
          taDisplay.appendText("服务器启动");
          readThread = new Thread(() -> {
            String msg = null;
            while ((msg = httpClient.receive()) != null) {
              String msgTemp = msg;
              Platform.runLater(() -> {
                taDisplay.appendText(msgTemp + "\n");
              });
            }
            Platform.runLater(() -> {
              taDisplay.appendText("对话已关闭!\n");
            });
          });
          readThread.start();
        } catch (IOException e) {
          taDisplay.appendText("服务器连接失败" + 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){
        //向服务器发送关闭连接的约定信息
        httpClient.send("bye");
        httpClient.close();
      }else if(httpsClient != null){
        //向服务器发送关闭连接的约定信息
        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 {
    //主动向服务器发起连接,实现TCP的三次握手过程
    //如果不成功,则抛出错误信息,其错误信息交由调用者处理
    socket = new Socket(ip, Integer.parseInt(port));

    //得到网络输出字节流地址,并封装成网络输出字符流
    OutputStream socketOut = socket.getOutputStream();
    pw = new PrintWriter( // 设置最后一个参数为true,表示自动flush数据
      new OutputStreamWriter(//设置utf-8编码
        socketOut, "utf-8"), true);

    //得到网络输入字节流地址,并封装成网络输入字符流
    InputStream socketIn = socket.getInputStream();
    br = new BufferedReader(
      new InputStreamReader(socketIn, "utf-8"));
  }

  public void send(String msg) {
    //输出字符流,由Socket调用系统底层函数,经网卡发送字节流
    pw.println(msg);
  }

  public String receive() {
    String msg = null;
    try {
      //从网络输入字符流中读信息,每次只能接受一行信息
      //如果不够一行(无行结束符),则该语句阻塞等待,
      // 直到条件满足,程序才往下运行
      msg = br.readLine();
    } catch (IOException e) {
      e.printStackTrace();
    }
    return msg;
  }
  public void close() {
    try {
      if (socket != null) {
        //关闭socket连接及相关的输入输出流,实现四次握手断开
        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("网页请求");
  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("网页地址"),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("信息显示区"),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("对话已关闭!\n");
          });
        });
        readThread.start();
      } catch (IOException e) {
        taDisplay.appendText("服务器连接失败"+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 {
    //主动向服务器发起连接,实现TCP的三次握手过程
    //如果不成功,则抛出错误信息,其错误信息交由调用者处理
    factory=(SSLSocketFactory)SSLSocketFactory.getDefault();
    socket=(SSLSocket)factory.createSocket(ip,Integer.parseInt(port));

    //得到网络输出字节流地址,并封装成网络输出字符流
    OutputStream socketOut = socket.getOutputStream();
    pw = new PrintWriter( // 设置最后一个参数为true,表示自动flush数据
      new OutputStreamWriter(//设置utf-8编码
        socketOut, "utf-8"), true);

    //得到网络输入字节流地址,并封装成网络输入字符流
    InputStream socketIn = socket.getInputStream();
    br = new BufferedReader(
      new InputStreamReader(socketIn, "utf-8"));
  }

  public void send(String msg) {
    //输出字符流,由Socket调用系统底层函数,经网卡发送字节流
    pw.println(msg);
  }

  public String receive() {
    String msg = null;
    try {
      //从网络输入字符流中读信息,每次只能接受一行信息
      //如果不够一行(无行结束符),则该语句阻塞,
      // 直到条件满足,程序才往下运行
      msg = br.readLine();
    } catch (IOException e) {
      e.printStackTrace();
    }
    return msg;
  }
  public void close() {
    try {
      if (socket != null) {
        //关闭socket连接及相关的输入输出流,实现四次握手断开
        socket.close();
      }
    } catch (IOException e) {
      e.printStackTrace();
    }
  }
  //本机模块内测试与运行,需先运行TCPServer
  public static void main(String[] args) throws IOException {
    HTTPSClient tcpClient = new HTTPSClient("127.0.0.1" ,"8008");
    tcpClient.send("hello");//发送一串字符
    //接收服务器返回的字符串并显示
    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("网页请求");
  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("网页地址"),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("信息显示区"),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("对话已关闭!\n");
          });
        });
        readThread.start();
      } catch (IOException e) {
        taDisplay.appendText("服务器连接失败"+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("发送");
  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("网页信息显示区"),taDisplay,new Label("输入URL地址"),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("当前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;
            //不知道服务器有多少回传信息,就持续不断接收
            //由于在另外一个线程,不会阻塞主线程的正常运行
            try {
              while ((msg = br.readLine()) != null) {
                //lambda表达式不能直接访问外部非final类型局部变量
                //所以这里使用了一个临时变量
                String msgTemp = msg;
                Platform.runLater(() -> {
                  taDisplay.appendText(msgTemp + "\r\n");
                });
              }
            } catch (IOException e) {
              e.printStackTrace();
            }
            //跳出了循环,说明服务器已关闭,读取为null,提示对话关闭
            Platform.runLater(() -> {
              taDisplay.appendText("对话已关闭!\n");
            });
          });
          readThread.start();

        }
      }catch(IOException e) {
        e.printStackTrace();
      }
    });


  }
  public static boolean isURL(String str){
    //转换为小写
    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]\\." // 二级域名
      + "[a-z]{2,6})" // first level domain- .com or .museum
      + "(:[0-9]{1,5})?" // 端口号最大为65535,5位数
      + "((/?)|" // a slash isn't required if there is no file name
      + "(/[0-9a-z_!~*'().;?:@&=+$,%#-]+)+/?)$";
    return  str.matches(regex);
  }
}

  • 27
    点赞
  • 38
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

tsuyt

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值