java网络编程(七)

本人花费半年的时间总结的《Java面试指南》已拿腾讯等大厂offer,已开源在github ,欢迎star!

本文GitHub https://github.com/OUYANGSIHAI/JavaInterview 已收录,这是我花了6个月总结的一线大厂Java面试总结,本人已拿大厂offer,欢迎star

原文链接:blog.ouyangsihai.cn >> java网络编程(七)

戳上面的蓝字关注我们哦!

 精彩内容 

 

猜数字小游戏

下面这个示例是一个猜数字的控制台小游戏。该游戏的规则是:当客户端第一次连接到服务器端时,服务器端生产一个【0,50】之间的随机数字,然后客户端输入数字来猜该数字,每次客户端输入数字以后,发送给服务器端,服务器端判断该客户端发送的数字和随机数字的关系,并反馈比较结果,客户端总共有5次猜的机会,猜中时提示猜中,当输入”quit”时结束程序。

和前面的示例类似,在进行网络程序开发时,首先需要分解一下功能的实现,觉得功能是在客户端程序中实现还是在服务器端程序中实现。区分的规则一般是:客户端 程序实现接收用户输入等界面功能,并实现一些基础的校验降低服务器端的压力,而将程序核心的逻辑以及数据存储等功能放在服务器端进行实现。遵循该原则划分 的客户端和服务器端功能如下所示。

客户端程序功能列表:

  • 接收用户控制台输入- 判断输入内容是否合法- 按照协议格式发送数据- 根据服务器端的反馈给出相应提示服务器端程序功能列表:- 接收客户端发送数据- 按照协议格式解析数据- 判断发送过来的数字和随机数字的关系- 根据判断结果生产协议数据- 将生产的数据反馈给客户端
    在该示例中,实际使用的网络命令也只有两条,所以显得协议的格式比较简单。

其中客户端程序协议格式如下:

  • 将用户输入的数字转换为字符串,然后转换为byte数组- 发送“quit”字符串代表退出

其中服务器端程序协议格式如下:

  • 反馈长度为1个字节,数字0代表相等(猜中),1代表大了,2代表小了,其它数字代表错误。
    实现该程序的代码比较多,下面分为客户端程序实现和服务器端程序实现分别进行列举。

客户端程序实现代码如下:


package guess;
import java.net.*;
import java.io.*;
/**
 * 猜数字客户端
 */
public class TCPClient {
 public static void main(String[] args) {
         Socket socket = null;
         OutputStream os = null;
         InputStream is = null;
         BufferedReader br = null;
         byte[] data = new byte[2];
         try{
                   //建立连接
                   socket = new Socket(
                                     "127.0.0.1",10001);
                   //发送数据
                   os= socket.getOutputStream();
                   //读取反馈数据
                   is = socket.getInputStream();
                   //键盘输入流
                   br = new BufferedReader(
                                     new InputStreamReader(System.in));
                   //多次输入
                   while(true){
                            System.out.println("请输入数字:");
                            //接收输入
                            String s = br.readLine();
                            //结束条件
                            if(s.equals("quit")){
                                     os.write("quit".getBytes());
                                     break;
                            }
                            //校验输入是否合法
                            boolean b = true;
                            try{
                                     Integer.parseInt(s);
                            }catch(Exception e){
                                     b = false;
                            }
                            if(b){ //输入合法
                                     //发送数据
                                     os.write(s.getBytes());
                                     //接收反馈
                                     is.read(data);
                                     //判断
                                     switch(data[0]){
                                     case 0:
                                               System.out.println("相等!祝贺你!");
                                               break;
                                     case 1:
                                               System.out.println("大了!");
                                               break;
                                     case 2:
                                               System.out.println("小了!");
                                               break;
                                     default:
                                               System.out.println("其它错误!");
                                     }
                                     //提示猜的次数
                                     System.out.println("你已经猜了" + data[1] + "次!");
                                     //判断次数是否达到5次
                                     if(data[1] >= 5){
                                               System.out.println("你挂了!");
                                               //给服务器端线程关闭的机会
                                               os.write("quit".getBytes());
                                               //结束客户端程序
                                               break;
                                     }
                            }else{ //输入错误
                                     System.out.println("输入错误!");
                            }
                   }
         }catch(Exception e){
                   e.printStackTrace();
         }finally{
                   try{
                            //关闭连接
                            br.close();
                            is.close();
                            os.close();
                            socket.close();
                   }catch(Exception e){
                            e.printStackTrace();
                   }
         }
 }
      }

在该示例中,首先建立一个到IP地址为127.0.0.1的端口为10001的连接,然后进行各个流的初始化工作,将逻辑控制的代码放入在一个while循环中,这样可以在客户端多次进行输入。在循环内部,首先判断用户输入的是否为quit字符串,如果是则结束程序,如果输入不是quit,则首先校验输入的是否是数字,如果不是数字则直接输出“输入错误!”并继续接收用户输入,如果是数字则发送给服务器端,并根据服务器端的反馈显示相应的提示信息。最后关闭流和连接,结束客户端程序。

服务器端程序的实现还是分为服务器控制程序和逻辑线程,实现的代码分别如下:


package guess;
import java.net.*;
/**
 * TCP连接方式的服务器端
 * 实现功能:接收客户端的数据,判断数字关系
 */
public class TCPServer {
 public static void main(String[] args) {
         try{
                   //监听端口
                   ServerSocket ss = new ServerSocket(10001);
                   System.out.println("服务器已启动:");
                   //逻辑处理
                   while(true){
                            //获得连接
                            Socket s = ss.accept();
                            //启动线程处理
                            new LogicThread(s);
                   }
         }catch(Exception e){
                   e.printStackTrace();
         }
 }
     }
      package guess;
import java.net.*;
import java.io.*;
import java.util.*;
/**
 * 逻辑处理线程
 */
public class LogicThread extends Thread {
      Socket s;
      static Random r = new Random();
      public LogicThread(Socket s){
              this.s = s;
              start(); //启动线程
      }
      public void run(){
              //生成一个[0,50]的随机数
              int randomNumber = Math.abs(r.nextInt() % 51);
              //用户猜的次数
              int guessNumber = 0;
              InputStream is = null;
              OutputStream os = null;
              byte[] data = new byte[2];
              try{
                       //获得输入流
                       is = s.getInputStream();
                       //获得输出流
                       os = s.getOutputStream();
                       while(true){ //多次处理
                                 //读取客户端发送的数据
                                 byte[] b = new byte[1024];
                                 int n = is.read(b);
                                 String send = new String(b,0,n);
                                 //结束判别
                                 if(send.equals("quit")){
                                          break;
                                 }
                                 //解析、判断
                                 try{
                                          int num = Integer.parseInt(send);
                                          //处理
                                          guessNumber++; //猜的次数增加1
                                          data[1] = (byte)guessNumber;
                                          //判断
                                          if(num > randomNumber){
                                                   data[0] = 1;
                                          }else if(num < randomNumber){
                                                   data[0] = 2;
                                          }else{
                                                   data[0] = 0;
                                                   //如果猜对
                                                   guessNumber = 0; //清零
                                                   randomNumber = Math.abs(r.nextInt() % 51);
                                          }
                                          //反馈给客户端
                                          os.write(data);                                    
                                 }catch(Exception e){ //数据格式错误
                                          data[0] = 3;
                                          data[1] = (byte)guessNumber;
                                          os.write(data); //发送错误标识
                                          break;
                                 }
                                 os.flush();   //强制发送
                       }
              }catch(Exception e){
                       e.printStackTrace();
              }finally{
                       try{
                                 is.close();
                                 os.close();
                                 s.close();
                       }catch(Exception e){}
              }
      }
}

在 该示例中,服务器端控制部分和前面的示例中一样。也是等待客户端连接,如果有客户端连接到达时,则启动新的线程去处理客户端连接。在逻辑线程中实现程序的 核心逻辑,首先当线程执行时生产一个随机数字,然后根据客户端发送过来的数据,判断客户端发送数字和随机数字的关系,然后反馈相应的数字的值,并记忆客户 端已经猜过的次数,当客户端猜中以后清零猜过的次数,使得客户端程序可以继续进行游戏。

总体来说,该程序示例的结构以及功能都与上一个程序比较类似,希望通过比较这两个程序,加深对于网络编程的认识,早日步入网络编程的大门。

回复以下关键字获取更多学习资源****

``

java基础|html5|css|js|jquery|angularJs|ajax|node.js|javaEE基础| |struts2|hibernate|spring|svn|maven|springmvc|mybatis|linux|oracle| |luncene|solr|redis|springboot|架构师资源|dubbo|php|webservice|c++基础|nginx|mysql|sqlserver|asp.net更多学习资源逐步更新,请置顶公众号不要错过更新

好好学java

每日推送java优质文章、视频教程、热点资讯

微信ID:SIHAI0911

长按左侧二维码关注

原文地址:https://sihai.blog.csdn.net/article/details/109464691

本人花费半年的时间总结的《Java面试指南》已拿腾讯等大厂offer,已开源在github ,欢迎star!

本文GitHub https://github.com/OUYANGSIHAI/JavaInterview 已收录,这是我花了6个月总结的一线大厂Java面试总结,本人已拿大厂offer,欢迎star

原文链接:blog.ouyangsihai.cn >> java网络编程(七)


 上一篇
java基础(二) 自增自减与贪心规则 java基础(二) 自增自减与贪心规则
戳上面的蓝字关注我们哦!  精彩内容    引言   JDK中提供了自增运算符++,自减运算符–。这两个操作符各有两种使用方式:前缀式(++ a,–a),后缀式(a++,a–)。可能说到这里,说不得有读者就会吐槽说,前后缀式都挺简单
2021-04-04
下一篇 
java基础(三) 加强型for循环与Iterator java基础(三) 加强型for循环与Iterator
戳上面的蓝字关注我们哦!  精彩内容    引言   从JDK1.5起,增加了加强型的for循环语法,也被称为 “for-Each 循环”。加强型循环在操作数组与集合方面增加了很大的方便性。那么,加强型for循环是怎么解析的呢?同时
2021-04-04