程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> 關於JAVA >> Java編程那些事兒108——網絡編程示例1

Java編程那些事兒108——網絡編程示例1

編輯:關於JAVA

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方法中實現了服務器端邏輯,根據客戶端發送過來的數據,判斷是否是質數,然後根據判斷結果按照協議格式要求,生成客戶端反饋數據,實現服務器端要求的功能。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved