Fork me on GitHub

《互联网程序设计》 -- 第2周网络对话程序的设计

  经历了上一周的学习java,发现自己就是一个five,很多都忘了,还有很多底层也是不会的。很烦。不过还是一点一点地去学一下。来到第二周的互联网程序设计课,这周的任务就是设计一个网络对话程序。

  一、总览

就是说通过窗体程序登录到客户端,然后向服务器发送消息(字符串),并能读取字符串返回的消息。

  二、TCPServer,服务器的建立

这个还没有看懂下次说,

  三、TCPClient,客户端

1、连接对方,先向服务器发起三次握手。

socket = new Socket(host,port); //向服务进程发起TCP三次握手连接

然后获取字节流,(输入和输出)Socket连接成功后,通过调用socket.getXXXXXStream( )方法,可获得字节输出流和字节输入流,输出流用于发送信息,输入流用于接收信息。并可通过以下组合方式封装为输入输出的字符流:

new PrintWriter( // 设置最后一个参数为true,表示自动flush数据
    new OutputStreamWriter(//设置utf-8编码
        outputStream, "utf-8"), true);
new BufferedReader(
    new InputStreamReader(inputStream, "utf-8"));

这里采用自动flush的方法,如果没有flush则会在缓存区一直出不来,阻塞运行。

2、发送信息给服务器

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

3、服务器接收信息

public String receive() {
  String msg = null;
  try {
    //从网络输入字符流中读信息,每次只能接受一行信息
    //如果不够一行(无行结束符),则该语句阻塞,
    // 直到条件满足,程序才往下运行
    msg = br.readLine();
  } catch (IOException e) {
    e.printStackTrace();
  }
  return msg;
}

4、关闭网络连接

public void close() {
  try {
if (socket != null) {
      //关闭socket连接及相关的输入输出流,实现四次握手断开,如图2.3所示
      socket.close();
    }
  } catch (IOException e) {
    e.printStackTrace();
  }
}

四、TCPClientFX,窗体的构建

这个大体上和上一周的simplefx差不多,我就略说了。不过有些是需要注意的点。

  1 public void start(Stage primaryStage) {
  2         taDisplay.setEditable(false);
  3         btnUnConnect.setDisable(true);
  4         btnSend.setDisable(true);
  5         btnUnConnect.setStyle("-fx-color: RED");
  6         btnExit.setStyle("-fx-color: RED");
  7         BorderPane mainPane = new BorderPane();
  8 
  9         mainPane.setCenter(getVBox());
 10         mainPane.setBottom(getHBoxBottom());
 11         mainPane.setTop(getHBoxTop());
 12 
 13 
 14 
 15         //这里是按钮的控制:
 16         btnConnect.setOnAction(event -> {
 17             String ip = tfIP.getText().trim();
 18             String port = tfPort.getText().trim();
 19 
 20             try {
 21                 //tcpClient不是局部变量,是本程序定义的一个TCPClient类型的成员变量
 22                 tcpClient = new TCPClient(ip,port);
 23                 //成功连接服务器,接收服务器发来的第一条欢迎信息
 24                 String firstMsg = tcpClient.receive();
 25                 taDisplay.appendText(firstMsg + "\n");
 26 
 27                 btnConnect.setDisable(true);//连接服务器之后不能再次连接
 28                 btnSend.setDisable(false);//连接服务器成功之后才可以发送信息
 29                 btnUnConnect.setDisable(false);//可以启用断开连接按钮
 30 
 31             } catch (Exception e) {
 32                 taDisplay.appendText("服务器连接失败!" + e.getMessage() + "\n");
 33             }
 34         });
 35 
 36 
 37 
 38         //退出按钮的设置
 39         btnExit.setOnAction(event -> {
 40             if(tcpClient != null){
 41                 //向服务器发送关闭连接的约定信息
 42                 taDisplay.appendText("bye" + "\n");
 43 //                TimeUnit.SECONDS.sleep(2);
 44                 tcpClient.send("bye");
 45                 tcpClient.close();
 46             }
 47             System.exit(0);
 48         });
 49 
 50         btnUnConnect.setOnAction(event -> {
 51             if(tcpClient != null){
 52                 //向服务器发送关闭连接的约定信息
 53                 taDisplay.appendText("bye,断开连接,拜拜了您嘞!" + "\n");
 54                 tcpClient.send("bye");
 55                 tcpClient.close();
 56                 btnUnConnect.setDisable(true);
 57                 btnConnect.setDisable(false);
 58                 btnSend.setDisable(true);
 59             }
 60         });
 61 
 62         //点x的设置
 63         primaryStage.setOnCloseRequest(event -> {
 64             String ip = tfIP.getText().trim();
 65             String port = tfPort.getText().trim();
 66             try {
 67                 tcpClient = new TCPClient(ip,port);
 68                 if(tcpClient != null){
 69                     //向服务器发送关闭连接的约定信息
 70                     tcpClient.send("bye");
 71                     tcpClient.close();
 72                 }
 73                 System.exit(0);
 74             }catch (Exception e){
 75                 taDisplay.appendText("退出失败!" + e.getMessage() + "\n");
 76             }
 77         });
 78 
 79         //点x的设置
 80         primaryStage.setOnCloseRequest(event -> {
 81             String ip = tfIP.getText().trim();
 82             String port = tfPort.getText().trim();
 83             try {
 84                 TCPClient tcpClient = new TCPClient(ip,port);
 85                 if(tcpClient != null){
 86                     //向服务器发送关闭连接的约定信息
 87                     tcpClient.send("bye");
 88                     tcpClient.close();
 89                 }
 90                 System.exit(0);
 91             }catch (Exception e){
 92                 taDisplay.appendText("退出失败!" + e.getMessage() + "\n");
 93             }
 94         });
 95 
 96         //发送按钮的设置;
 97         btnSend.setOnAction(event -> {
 98             String sendMsg = tfSend.getText();
 99             tcpClient.send(sendMsg);//向服务器发送一串字符
100             if (sendMsg.equals("bye")){
101                 btnUnConnect.setDisable(true);
102                 btnConnect.setDisable(false);
103                 btnSend.setDisable(true);
104                 btnSend.setDisable(true);
105             }
106             taDisplay.appendText("客户端发送:" + sendMsg + "\n");
107             String receiveMsg = tcpClient.receive();//从服务器接收一行字符
108             taDisplay.appendText(receiveMsg + "\n");
109             tfSend.clear();
110         });
111 
112 //        btnSend.requestFocus();
113         tfSend.requestFocus();//聚焦一定是在发送框,因为输入信息后焦点就在发送框,而不是按钮或其他
114         tfSend.setOnKeyPressed(event -> {
115 
116             if(event.isShiftDown() == true && event.getCode().equals(KeyCode.ENTER )){
117                 String sendMsg = tfSend.getText();
118                 tcpClient.send("echo:" + sendMsg);//向服务器发送一串字符
119                 taDisplay.appendText("客户端发送:echo:" + sendMsg + "\n");
120                 String receiveMsg = tcpClient.receive();//从服务器接收一行字符
121                 taDisplay.appendText(receiveMsg + "\n");
122                 tfSend.clear();
123             }
124             else if (event.getCode().equals(KeyCode.ENTER)) {
125                 String sendMsg = tfSend.getText();
126                 tcpClient.send(sendMsg);//向服务器发送一串字符
127                 taDisplay.appendText("客户端发送:" + sendMsg + "\n");
128                 if (sendMsg.equals("bye")){
129                     btnUnConnect.setDisable(true);
130                     btnConnect.setDisable(false);
131                     btnSend.setDisable(true);
132                 }
133                 String receiveMsg = tcpClient.receive();//从服务器接收一行字符
134                 taDisplay.appendText(receiveMsg + "\n");
135                 tfSend.clear();
136             }
137         });
138 
139         Scene scene = new Scene(mainPane,900,500);
140         primaryStage.setTitle("网络通信测试111");
141         primaryStage.setScene(scene);
142         primaryStage.show();
143     }
144 
145     private VBox getVBox(){
146         VBox vBox = new VBox(10);
147         vBox.setPadding(new Insets(10,20,10,20));
148         vBox.getChildren().addAll(new Label("信息显示:") , taDisplay, new Label("信息输入:"), tfSend);
149         VBox.setVgrow(taDisplay, Priority.ALWAYS);
150 
151         return vBox;
152     }
153 
154     private HBox getHBoxBottom(){
155         HBox hBox = new HBox(10);
156         hBox.setPadding(new Insets(10,20,10,20));
157         hBox.setAlignment(Pos.CENTER_RIGHT);
158         hBox.getChildren().addAll(btnSend,btnExit);
159 
160         return hBox;
161     }
162 
163     private HBox getHBoxTop(){
164         HBox hBox = new HBox(10);
165         hBox.setPadding(new Insets(10,20,10,20));
166         hBox.setAlignment(Pos.CENTER);
167         hBox.getChildren().addAll(new Label("IPAdress:") , tfIP, new Label("Interface:"), tfPort, btnConnect,btnUnConnect);
168 
169         return hBox;
170     }
TCOClientFX

btnConnect的按钮是连接服务器,还没懂不谈。其他类似

 

这里注意的点有,你需要在窗体类TCPClientFX下声明好TCPClient,不然后面的退出按钮的功能你可用不了。

还有的是

TCPClientFX客户端窗体程序中,连接成功服务器后,如果用户再次点击“连接”按钮,会造成服务器资源浪费,还可能使程序运行不正常,无法正常发送信息;

没有连接服务器时,或者发送bye以后,点击“发送”按钮,控制台也会产生异常;

当已连接上服务器时候,直接就可以在btnConnect连接的代码那里加入这三行代码就可以解决啦。

                btnConnect.setDisable(true);//连接服务器之后不能再次连接
                btnSend.setDisable(false);//连接服务器成功之后才可以发送信息
                btnUnConnect.setDisable(false);//可以启用断开连接按钮        

当发送bye的信息给服务器之后,在btnSend按钮的点击动作加入下面的判断代码

if (sendMsg.equals("bye")){
                btnUnConnect.setDisable(true);
                btnConnect.setDisable(false);
                btnSend.setDisable(true);
            }

 

 

 

好了,今天就这样理解到这里。

下面是完整程序的代码连接:

https://wws.lanzous.com/iFgtWgmi9mh

 

posted @ 2020-09-14 21:22  走位,走位  阅读(261)  评论(0编辑  收藏  举报