## 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方法中實現了服務器端邏輯,根據客戶端發送過來的數據,判斷是否是質數,然后根據判斷結果按照協議格式要求,生成客戶端反饋數據,實現服務器端要求的功能。
- 前言
- (1)序言
- (2)程序設計是什么?
- (3)你適合學習程序設計嗎?
- (4)如何學好程序設計?
- (5)程序設計介紹小結
- (6)計算機軟件基本概念
- (7)進制的概念
- (8)計算機內部的數據表達
- (9)網絡編程基礎
- (10)Java語言簡介
- (11)JDK的獲得、安裝和配置
- (12)第一個HelloWorld程序
- (13)Eclipse基本使用
- (14)Eclipse基礎使用進階
- (15)如何學好Java語法
- (16)代碼框架、關鍵字和標識符
- (17)基本數據類型
- (18)變量和常量
- (19)數據類型轉換
- (20)空白、語句結束和注釋
- (21)算術運算符
- (22)比較運算符
- (23)邏輯運算符
- (24)賦值運算符
- (25)位運算符
- (26)移位運算符
- (27)其它運算符
- (28)運算符優先級
- (29)表達式
- (30)流程控制基礎
- (31)if語句語法(1)
- (32)if語句語法(2)
- (33)if語句語法(3)
- (34)switch語句語法
- (35)while語句語法
- (36)do-while語句語法
- (37)for語句語法
- (38)break和continue語句
- (39)流程控制綜合示例1
- (40)流程控制綜合示例2
- (41)流程控制綜合示例3
- (42)流程控制綜合練習
- (43)數組概述
- (44)數組基礎語法
- (45)數組使用示例1
- (46)數組使用示例2
- (47)數組使用示例3
- (48)多維數組基礎
- (49)多維數組使用示例1
- (50)多維數組使用示例2
- (51)多維數組練習
- (52)方法聲明
- (53)方法聲明示例
- (54)方法調用
- (55)方法重載和參數傳遞
- (56)方法練習
- (57)面向對象基礎
- (58)類(一)
- (59)類(二)
- (60)對象
- (61)面向對象設計方法和面向對象特性(一)
- (62)繼承(二)
- (63)多態性
- (64)訪問控制符、修飾符和其它關鍵字
- (65)static修飾符
- (66)final修飾符
- (67)this和super
- (68)抽象類和接口(一)
- (69)抽象類和接口(二)
- (70)抽象類和接口(三)
- (71)內部類簡介
- (72)包的概念
- (73)JDK文檔使用
- (74)java.lang包介紹1
- (75)String類使用
- (76)StringBuffer類和System類
- (77)包裝類
- (78)時間和日期處理
- (79)Random隨機處理
- (80)集合框架簡述
- (81)異常處理概述
- (82)異常處理語法1
- (83)異常處理語法2
- (84)IO簡介
- (85)IO類體系
- (86)文件操作之File類使用
- (87)文件操作之讀取文件
- (88)文件操作之寫文件
- (89)讀取控制臺輸入
- (90)裝飾流使用1
- (91)裝飾流使用2
- (92)IO使用注意問題
- (93)多線程基礎
- (94)多線程實現方式1
- (95)多線程實現方式2
- (96)多線程使用示例1
- (97)多線程使用示例2
- (98)多線程問題及處理1
- (99)多線程問題及處理2
- (100)多線程問題及處理3
- (101)網絡編程概述
- (102)網絡編程技術1
- (103)網絡編程技術2
- (104)網絡編程技術3
- (105)網絡編程技術4
- (106)網絡編程技術5
- (107)網絡協議概念
- (108)網絡編程示例1
- (109)網絡編程示例2
- (110)網絡編程小結