java Socket通信實例 – JAVA編程語言程序開發技術文章

一直做Java web,幾乎沒有做過CS方向上的東西。最近一同學來北京找工作,到我這兒來玩。說起筆試經歷,說瞭這樣一個程序題,大概是這樣的;
   用C++編程實現一個簡單的通信實例,要求服務器實時接受客戶端發送來的消息。雖說沒做過這方面的東西,但也知道需要用Java Socket來實現(坦白說C++不會)。工作之餘花瞭2個小時寫瞭一個基本滿足要求的實例。也確實遇到瞭一些問題,貼出來,共同學習。
先貼代碼。服務器端:
[java]
package qy.server; 
 
import java.io.DataInputStream; 
import java.io.DataOutputStream; 
import java.io.IOException; 
import java.net.ServerSocket; 
import java.net.Socket; 
import java.util.concurrent.ExecutorService; 
import java.util.concurrent.Executors; 
 
public class MyServer { 
    private ServerSocket serverSocket; //  
    private ExecutorService servicePool; // 線程池 
 
    public MyServer(int port) { 
        try { 
            this.serverSocket = new ServerSocket(port); 
            this.servicePool = Executors.newFixedThreadPool(5); 
        } catch (IOException e) { 
            e.printStackTrace(); 
        } 
    } 
 
    public static void main(String[] args) { 
        new MyServer(6666).service();  
    } 
 
    public void service() { 
        int i = 0; 
        while (true) { 
            try { 
                Socket socket = this.serverSocket.accept(); // 接受到一個連接,並且返回一個客戶端的Socket對象實例 
                this.servicePool.execute(new Handler(socket)); 
                System.out 
                        .println("User " + i + " is connecting to the Server"); 
                i++; 
            } catch (IOException e) { 
                e.printStackTrace(); 
                this.servicePool.shutdown(); 
            } 
        } 
    } 
 
    class Handler implements Runnable { 
        private Socket socket; 
 
        public Handler(Socket socket) { 
            this.socket = socket; 
        } 
 
        @Override 
        public void run() { 
            try { 
                // 一個輸入流,用於獲取客戶端傳來的內容 
                DataInputStream dis = new DataInputStream( 
                        this.socket.getInputStream()); 
                // 用於產生服務器準備響應的內容 
                DataOutputStream dos = new DataOutputStream(this.socket.getOutputStream()); 
                String str; 
                while (null != (str = dis.readUTF())) { 
                    System.out.println(str); 
                    if ("exit".equals(str)) { 
                        System.out.println("客戶端發出中斷請求"); 
                        dos.writeUTF("服務器已經關閉本次連接."); 
                        dos.flush(); 
//                      dos.writeUTF("exit"); //  
//                      dos.flush(); 
                         
                        dos.close(); 
                        dis.close(); 
                        break; 
                    } 
                } 
 
            } catch (IOException e) { 
                e.printStackTrace(); 
            } 
        } 
    } 

然後,客戶端:
[java] 
package qy.client; 
 
import java.io.BufferedReader; 
import java.io.DataInputStream; 
import java.io.DataOutputStream; 
import java.io.IOException; 
import java.io.InputStreamReader; 
import java.net.Socket; 
 
public class MyClient { 
 
    public static void main(String[] args) { 
        try { 
            Socket client = new Socket("localhost", 6666); 
            MyClient me = new MyClient(); 
            new Thread(me.new Handler(client)).start(); 
        } catch (IOException e) { 
            e.printStackTrace(); 
        } 
    } 
 
    class Handler implements Runnable { 
        private BufferedReader br; 
        private DataOutputStream dos; 
        private DataInputStream dis; 
        private Socket socket; 
        private boolean flag = true; // 用於控制循環結束 
 
        public Handler(Socket s) throws IOException { 
            this.br = new BufferedReader(new InputStreamReader(System.in)); // 用於從控制臺接受輸入的信息,再發送到服務器 
            this.socket = s; 
            this.dos = new DataOutputStream(this.socket.getOutputStream()); // 向服務器寫數據的輸出流 
            this.dis = new DataInputStream(this.socket.getInputStream()); // 獲取服務器返回數據的輸入流 
        } 
 
        @Override 
        public void run() { 
            while (flag) { 
                try { 
                    String str = br.readLine(); 
                    if ("exit".equals(str)) { // 客戶端終止發送信息標記 exit 
                        this.br.close();  
                        this.dos.writeUTF(str); 
                        this.dos.flush(); 
                         
                        String res = dis.readUTF(); 
                        System.out.println(res); 
 
                        this.dis.close(); 
                        this.dos.close(); 
                        this.flag = false; 
                    } else { 
                        this.dos.writeUTF(str);// 每讀一行就發送一行 
                        this.dos.flush(); 
                    } 
 
                } catch (IOException e) { 
                    e.printStackTrace(); 
                } 
            } 
        } 
    } 

遇到的問題:
最先考慮的是使用BufferedReader和BufferedWriter來完成雙向數據的寫入寫出,但是發現BufferedWriter在fush()的時候並不能把從控制臺得到的數據立即發送到服務端,就改用DataOutputStream數據流來完成雙向數據傳遞。

發佈留言