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

Java編程那些事兒109——網絡編程示例2

編輯:關於JAVA

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){}
}
}
}

在該示例中,服務器端控制部分和前面的示例中一樣。也是等待客戶端連接,如果有客戶端連接到達時,則啟動新的線程去處理客戶端連接。在邏輯線程中實現程序的核心邏輯,首先當線程執行時生產一個隨機數字,然後根據客戶端發送過來的數據,判斷客戶端發送數字和隨機數字的關系,然後反饋相應的數字的值,並記憶客戶端已經猜過的次數,當客戶端猜中以後清零猜過的次數,使得客戶端程序可以繼續進行游戲。

總體來說,該程序示例的結構以及功能都與上一個程序比較類似,希望通過比較這兩個程序,加深對於網絡編程的認識,早日步入網絡編程的大門。

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