• 《互联网程序设计》 -- 第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 + "
    ");
     26 
     27                 btnConnect.setDisable(true);//连接服务器之后不能再次连接
     28                 btnSend.setDisable(false);//连接服务器成功之后才可以发送信息
     29                 btnUnConnect.setDisable(false);//可以启用断开连接按钮
     30 
     31             } catch (Exception e) {
     32                 taDisplay.appendText("服务器连接失败!" + e.getMessage() + "
    ");
     33             }
     34         });
     35 
     36 
     37 
     38         //退出按钮的设置
     39         btnExit.setOnAction(event -> {
     40             if(tcpClient != null){
     41                 //向服务器发送关闭连接的约定信息
     42                 taDisplay.appendText("bye" + "
    ");
     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,断开连接,拜拜了您嘞!" + "
    ");
     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() + "
    ");
     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() + "
    ");
     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 + "
    ");
    107             String receiveMsg = tcpClient.receive();//从服务器接收一行字符
    108             taDisplay.appendText(receiveMsg + "
    ");
    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 + "
    ");
    120                 String receiveMsg = tcpClient.receive();//从服务器接收一行字符
    121                 taDisplay.appendText(receiveMsg + "
    ");
    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 + "
    ");
    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 + "
    ");
    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

    认清现实,放弃幻想。 细节决定成败,心态放好,认真学习与工作。
  • 相关阅读:
    RTC驱动程序分析
    Linux下的RTC子系统
    [置顶] 谈EXPORT_SYMBOL使用
    《Linux内核修炼之道》精华分享与讨论(5)——Kernel地图:Kconfig与Makefile
    写出高效优美的单片机C语言代码
    哈夫曼树
    如何提高浮点数变整数的精度
    CF798C Mike and gcd problem
    CF822C Hacker, pack your bags!
    CF821C Okabe and Boxes
  • 原文地址:https://www.cnblogs.com/jyf2018/p/13669439.html
Copyright © 2020-2023  润新知