🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
## Java编程那些事儿109——网络编程示例2 陈跃峰 出自:[http://blog.csdn.net/mailbomb](http://blog.csdn.net/mailbomb) **13.3.2 猜数字小游戏** 下面这个示例是一个猜数字的控制台小游戏。该游戏的规则是:当客户端第一次连接到服务器端时,服务器端生产一个【0,50】之间的随机数字,然后客户端输入数字来猜该数字,每次客户端输入数字以后,发送给服务器端,服务器端判断该客户端发送的数字和随机数字的关系,并反馈比较结果,客户端总共有5次猜的机会,猜中时提示猜中,当输入”quit”时结束程序。 和前面的示例类似,在进行网络程序开发时,首先需要分解一下功能的实现,觉得功能是在客户端程序中实现还是在服务器端程序中实现。区分的规则一般是:客户端程序实现接收用户输入等界面功能,并实现一些基础的校验降低服务器端的压力,而将程序核心的逻辑以及数据存储等功能放在服务器端进行实现。遵循该原则划分的客户端和服务器端功能如下所示。 客户端程序功能列表: 1、  接收用户控制台输入 2、  判断输入内容是否合法 3、  按照协议格式发送数据 4、  根据服务器端的反馈给出相应提示 服务器端程序功能列表: 1、  接收客户端发送数据 2、  按照协议格式解析数据 3、  判断发送过来的数字和随机数字的关系 4、  根据判断结果生产协议数据 5、  将生产的数据反馈给客户端 在该示例中,实际使用的网络命令也只有两条,所以显得协议的格式比较简单。 其中客户端程序协议格式如下: 1、  将用户输入的数字转换为字符串,然后转换为byte数组 2、  发送“quit”字符串代表退出 其中服务器端程序协议格式如下: 1、  反馈长度为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){}               }       } } ~~~ 在该示例中,服务器端控制部分和前面的示例中一样。也是等待客户端连接,如果有客户端连接到达时,则启动新的线程去处理客户端连接。在逻辑线程中实现程序的核心逻辑,首先当线程执行时生产一个随机数字,然后根据客户端发送过来的数据,判断客户端发送数字和随机数字的关系,然后反馈相应的数字的值,并记忆客户端已经猜过的次数,当客户端猜中以后清零猜过的次数,使得客户端程序可以继续进行游戏。 总体来说,该程序示例的结构以及功能都与上一个程序比较类似,希望通过比较这两个程序,加深对于网络编程的认识,早日步入网络编程的大门。