一直做Java web,幾乎沒有做過CS方向上的東西。最近一同學來北京找工作,到我這兒來玩。說起筆試經曆,說了這樣一個程式題,大概是這樣的;
用C++編程實現一個簡單的通訊執行個體,要求伺服器即時接受用戶端發送來的訊息。雖說沒做過這方面的東西,但也知道需要用Java Socket來實現(坦白說C++不會)。工作之餘花了2個小時寫了一個基本滿足要求的執行個體。也確實遇到了一些問題,貼出來,共同學習。
先貼代碼。伺服器端:
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;}@Overridepublic 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();}}}}
然後,用戶端:
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()); // 擷取伺服器返回資料的輸入資料流}@Overridepublic void run() {while (flag) {try {String str = br.readLine();if ("exit".equals(str)) { // 用戶端終止發送資訊標記 exitthis.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資料流來完成雙向資料傳遞。