LookUpScore
package lookupscore;
import java.io.*;
import java.net.Socket;
public class LookUpScore {
private Socket socket; //定义套接字
//定义字符输入流和输出流
private PrintWriter pw;
private BufferedReader br;
public LookUpScore(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();
}
}
}
LookUpScoreFX
package lookupscore;
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.input.KeyCode;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Priority;
import javafx.scene.layout.VBox;
import javafx.stage.FileChooser;
import javafx.stage.Stage;
import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.time.LocalDateTime;
import java.util.Scanner;
public class LookUpScoreFX extends Application {
LookUpScore tcpClient;
//界面按钮
private Button btnSend = new Button("发送");
private Button btnExit = new Button("退出");
private Button btnConn = new Button("连接");
//待发送文本框
private TextField tfSend = new TextField("20221003383&何聚敛&2949282402@qq.com");
//显示信息文本框
private TextArea taDisplay = new TextArea();
//IP地址
private TextField IPAddress = new TextField("202.116.195.71");
//端口号
private TextField portNumber = new TextField("9009");
//系统退出标志
private boolean EXIT = false;
@Override
public void start(Stage primaryStage) {
BorderPane mainPane = new BorderPane();
VBox vBox = new VBox();
vBox.setSpacing(10);
vBox.setPadding(new Insets(10,20,10,20));
taDisplay.setEditable(false);
taDisplay.setWrapText(true);
HBox topHBox = new HBox();
Label IPAddressLable = new Label("IP地址");
Label portNumberLable = new Label("端口号");
topHBox.getChildren().addAll(IPAddressLable,IPAddress,portNumberLable,portNumber,btnConn);
topHBox.setAlignment(Pos.CENTER);
topHBox.setSpacing(10);
vBox.getChildren().addAll(
topHBox,
new Label("信息显示区域:"),
taDisplay,
new Label("信息输入区域:"),
tfSend
);
//设置显示信息区的文本区域可以纵向自动扩充范围
VBox.setVgrow(taDisplay, Priority.ALWAYS);
mainPane.setCenter(vBox);
//底部按钮区域
HBox hBox = new HBox();
hBox.setSpacing(10);
hBox.setPadding(new Insets(10,20,10,20));
hBox.setAlignment(Pos.CENTER_RIGHT);
hBox.getChildren().addAll(btnSend,btnExit);
mainPane.setBottom(hBox);
Scene scene = new Scene(mainPane,700,400);
primaryStage.setScene(scene);
primaryStage.setTitle("查询成绩");
primaryStage.setOnCloseRequest(e->{
exit();
});
primaryStage.show();
//事件处理部分
//连接按钮
btnConn.setOnAction(event -> {
String ip = IPAddress.getText().trim();
String port = portNumber.getText().trim();
try {
//tcpClient 不是局部变量,是本程序定义的一个 TCPClient 类型的成员变量
tcpClient = new LookUpScore(ip,port);
//成功连接服务器,接收服务器发来的第一条欢迎信息
// String firstMsg = tcpClient.receive();
// taDisplay.appendText(firstMsg + "\n");
Thread receiveThread;
receiveThread = new Thread(()->{
String msg = null;
//不知道服务器有多少回传信息,就持续不断接收
//由于在另外一个线程,不会阻塞主线程的正常运行
while ((msg = tcpClient.receive()) != null && !EXIT) {
//runLater 中的 lambda 表达式不能直接访问外部非 final 类型局部变量
//所以这里使用了一个临时常量,可以省略 final,但本质还是会作为常量使用
final String msgTemp = msg; //msgTemp 实质是 final 类型
Platform.runLater(()->{
taDisplay.appendText( msgTemp + "\n");
});
}
//跳出了循环,说明服务器已关闭,读取为 null,提示对话关闭
Platform.runLater(()->{
taDisplay.appendText("对话已关闭!\n" );
});
}, "my-readServerThread");//给新线程取别名,方便识别
receiveThread.start(); //启动线程
} catch (Exception e) {
taDisplay.appendText("服务器连接失败!" + e.getMessage() + "\n");
}
});
btnExit.setOnAction(e -> {
exit();
});
btnSend.setOnAction(event -> {
String sendMsg = tfSend.getText();
tcpClient.send(sendMsg);//向服务器发送一串字符
taDisplay.appendText("客户端发送:" + sendMsg + "\n");
tfSend.clear();
// String receiveMsg = tcpClient.receive();//从服务器接收一行字符
// taDisplay.appendText(receiveMsg + "\n");
});
}
public static void main(String[] args) {
launch(args);
}
private void exit(){
if(tcpClient != null){
//向服务器发送关闭连接的约定信息
tcpClient.send("bye");
//tcpClient.close();
EXIT = true;
}
System.exit(0);
}
}