🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
## Java编程那些事儿108——网络编程示例1 陈跃峰 出自:[http://blog.csdn.net/mailbomb](http://blog.csdn.net/mailbomb) **13.3 网络编程示例** “实践出真知”,所以在进行技术学习时,还是需要进行很多的练习,才可以体会技术的奥妙,下面通过两个简单的示例,演示网络编程的实际使用。 **13.3.1质数判别示例** 该示例实现的功能是质数判断,程序实现的功能为客户端程序接收用户输入的数字,然后将用户输入的内容发送给服务器端,服务器端判断客户端发送的数字是否是质数,并将判断的结果反馈给客户端,客户端根据服务器端的反馈显示判断结果。 质数的规则是:最小的质数是2,只能被1和自身整除的自然数。当用户输入小于2的数字,以及输入的内容不是自然数时,都属于非法输入。 网络程序的功能都分为客户端程序和服务器端程序实现,下面先描述一下每个程序分别实现的功能: 1、  客户端程序功能: a)接收用户控制台输入 b)判断输入内容是否合法 c)按照协议格式生成发送数据 d)发送数据 e)接收服务器端反馈 f)解析服务器端反馈信息,并输出 2、  服务器端程序功能: a)接收客户端发送数据 b)按照协议格式解析数据 c)判断数字是否是质数 d)根据判断结果,生成协议数据 e)将数据反馈给客户端 分解好了网络程序的功能以后,就可以设计网络协议格式了,如果该程序的功能比较简单,所以设计出的协议格式也不复杂。 客户端发送协议格式: 将用户输入的数字转换为字符串,再将字符串转换为byte数组即可。 例如用户输入16,则转换为字符串“16”,使用getBytes转换为byte数组。 客户端发送“quit”字符串代表结束连接 服务器端发送协议格式: 反馈数据长度为1个字节。数字0代表是质数,1代表不是质数,2代表协议格式错误。 例如客户端发送数字12,则反馈1,发送13则反馈0,发送0则反馈2。 功能设计完成以后,就可以分别进行客户端和服务器端程序的编写了,在编写完成以后联合起来进行调试即可。 下面分别以TCP方式和UDP方式实现该程序,注意其实现上的差异。不管使用哪种方式实现,客户端都可以多次输入数据进行判断。对于UDP方式来说,不需要向服务器端发送quit字符串。 以TCP方式实现的客户端程序代码如下: package example1; ~~~ import java.io.*; import java.net.*; /**  * 以TCP方式实现的质数判断客户端程序  */ public class TCPPrimeClient {          static BufferedReader br;          static Socket socket;          static InputStream is;          static OutputStream os;          /**服务器IP*/          final static String HOST = "127.0.0.1";          /**服务器端端口*/          final static int PORT = 10005;                   public static void main(String[] args) {                    init(); //初始化                    while(true){                             System.out.println("请输入数字:");                             String input = readInput(); //读取输入                             if(isQuit(input)){ //判读是否结束                                      byte[] b = "quit".getBytes();                                      send(b);                                      break; //结束程序                             }                             if(checkInput(input)){ //校验合法                                      //发送数据                                      send(input.getBytes());                                      //接收数据                                      byte[] data = receive();                                      //解析反馈数据                                      parse(data);                             }else{                                      System.out.println("输入不合法,请重新输入!");                             }                    }                    close();  //关闭流和连接          }                   /**           * 初始化           */          private static void init(){                    try {                             br = new BufferedReader(                                                new InputStreamReader(System.in));                             socket = new Socket(HOST,PORT);                             is = socket.getInputStream();                             os = socket.getOutputStream();                    } catch (Exception e) {}          }                   /**           * 读取客户端输入           */          private static String readInput(){                    try {                             return br.readLine();                    } catch (Exception e) {                             return null;                    }          }                   /**           * 判断是否输入quit           * @param input 输入内容           * @return true代表结束,false代表不结束           */          private static boolean isQuit(String input){                    if(input == null){                             return false;                    }else{                             if("quit".equalsIgnoreCase(input)){                                      return true;                             }else{                                      return false;                             }                    }          }                   /**           * 校验输入           * @param input 用户输入内容           * @return true代表输入符合要求,false代表不符合           */          private static boolean checkInput(String input){                    if(input == null){                             return false;                    }                    try{                             int n = Integer.parseInt(input);                             if(n >= 2){                                      return true;                             }else{                                      return false;                             }                    }catch(Exception e){                             return false;  //输入不是整数                    }          }                   /**           * 向服务器端发送数据           * @param data 数据内容           */          private static void send(byte[] data){                    try{                             os.write(data);                    }catch(Exception e){}          }                   /**           * 接收服务器端反馈           * @return 反馈数据           */          private static byte[] receive(){                    byte[] b = new byte[1024];                    try {                             int n = is.read(b);                             byte[] data = new byte[n];                             //复制有效数据                             System.arraycopy(b, 0, data, 0, n);                             return data;                    } catch (Exception e){}                    return null;          }                   /**           * 解析协议数据           * @param data 协议数据           */          private static void parse(byte[] data){                    if(data == null){                             System.out.println("服务器端反馈数据不正确!");                             return;                    }                    byte value = data[0]; //取第一个byte                    //按照协议格式解析                    switch(value){                    case 0:                             System.out.println("质数");                             break;                    case 1:                             System.out.println("不是质数");                             break;                    case 2:                             System.out.println("协议格式错误");                             break;                    }          }                   /**           * 关闭流和连接           */          private static void close(){                    try{                             br.close();                             is.close();                             os.close();                             socket.close();                    }catch(Exception e){                             e.printStackTrace();                    }          } } ~~~ 在该代码中,将程序的功能使用方法进行组织,使得结构比较清晰,核心的逻辑流程在main方法中实现。 以TCP方式实现的服务器端的代码如下: package example1; ~~~ import java.net.*; /**  * 以TCP方式实现的质数判别服务器端  */ public class TCPPrimeServer {          public static void main(String[] args) {                    final int PORT = 10005;                    ServerSocket ss  = null;                    try {                             ss = new ServerSocket(PORT);                             System.out.println("服务器端已启动:");                             while(true){                                      Socket s = ss.accept();                                      new PrimeLogicThread(s);                             }                    } catch (Exception e) {}                    finally{                             try {                                      ss.close();                             } catch (Exception e2) {}                    }                             } } package example1; import java.io.*; import java.net.*; /**  * 实现质数判别逻辑的线程  */ public class PrimeLogicThread extends Thread {          Socket socket;          InputStream is;          OutputStream os;                   public PrimeLogicThread(Socket socket){                    this.socket = socket;                    init();                    start();          }          /**           * 初始化           */          private void init(){                    try{                             is = socket.getInputStream();                             os = socket.getOutputStream();                    }catch(Exception e){}          }                   public void run(){                    while(true){                             //接收客户端反馈                             byte[] data = receive();                             //判断是否是退出                             if(isQuit(data)){                                      break;  //结束循环                             }                             //逻辑处理                             byte[] b = logic(data);                             //反馈数据                             send(b);                    }                    close();          }                   /**           * 接收客户端数据           * @return 客户端发送的数据           */          private  byte[] receive(){                    byte[] b = new byte[1024];                    try {                             int n = is.read(b);                             byte[] data = new byte[n];                             //复制有效数据                             System.arraycopy(b, 0, data, 0, n);                             return data;                    } catch (Exception e){}                    return null;          }                   /**           * 向客户端发送数据           * @param data 数据内容           */          private void send(byte[] data){                    try{                             os.write(data);                    }catch(Exception e){}          }                   /**           * 判断是否是quit           * @return 是返回true,否则返回false           */          private boolean isQuit(byte[] data){                    if(data == null){                             return false;                    }else{                             String s = new String(data);                             if(s.equalsIgnoreCase("quit")){                                      return true;                             }else{                                      return false;                             }                    }          }                   private byte[] logic(byte[] data){                    //反馈数组                    byte[] b = new byte[1];                    //校验参数                    if(data == null){                             b[0] = 2;                             return b;                    }                    try{                             //转换为数字                             String s = new String(data);                             int n = Integer.parseInt(s);                             //判断是否是质数                             if(n >= 2){                                      boolean flag = isPrime(n);                                      if(flag){                                                b[0] = 0;                                      }else{                                                b[0] = 1;                                      }                             }else{                                      b[0] = 2;  //格式错误                                      System.out.println(n);                             }                    }catch(Exception e){                             e.printStackTrace();                             b[0] = 2;                    }                    return b;          }                   /**           *           * @param n           * @return           */          private boolean isPrime(int n){                    boolean b = true;                    for(int i = 2;i <= Math.sqrt(n);i++){                             if(n % i == 0){                                      b = false;                                      break;                             }                    }                    return b;          }                   /**           * 关闭连接           */          private void close(){                    try {                             is.close();                             os.close();                             socket.close();                    } catch (Exception e){}          } } ~~~ 本示例使用的服务器端的结构和前面示例中的结构一致,只是逻辑线程的实现相对来说要复杂一些,在线程类中的logic方法中实现了服务器端逻辑,根据客户端发送过来的数据,判断是否是质数,然后根据判断结果按照协议格式要求,生成客户端反馈数据,实现服务器端要求的功能。