java socket server接收並返回數據


  在上章(java socket套接字編程入門)中,服務端只能處理一次,accept()是一種阻塞狀態,因此它只能同時處理一個請求,其它的請求只能排隊等待前面的處理完成。

為了支持多任務同時處理的能力,首先不要讓主服務運行完成即結束,而是一種死循環的方式,讓一直等待接收,其次,處理數據的需要另開線程進行,即socket的生命周期置於新開線程中。

  先定義SocketHandler作為線程單獨處理socket。

 

 

public class SocketHandler implements Runnable {

    private Socket socket;

    SocketHandler(Socket socket) {
        this.socket = socket;
    }

    @Override
    public void run() {
        BufferedReader bufferedReader = null;
        PrintWriter writer = null;
        try {
            System.out.println("thread:\t" + Thread.currentThread().getName() );
            bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
       //true,表示自動刷新,不需要人為觸發 writer
= new PrintWriter(new OutputStreamWriter(socket.getOutputStream()), true); String userInput; while ((userInput = bufferedReader.readLine()) != null) { if ("exit".equals(userInput)) { System.out.println("退出連接通信\t"); break; } System.out.println("接收內容:\t" + userInput); String result = "服務器時間:" + LocalDateTime.now() +"\t" + new StringBuilder(userInput).reverse(); writer.println(result); } } catch (IOException e) { e.printStackTrace(); } finally { try { if (writer != null) writer.close(); if (bufferedReader != null) bufferedReader.close(); socket.close(); } catch (IOException ioException) { ioException.printStackTrace(); } } } }

 

server服務端:

public static void main(String[] args) throws IOException {
        ServerSocket serverSocket = new ServerSocket(9090);

        //固定線程池來接收處理
        Executor executor = Executors.newFixedThreadPool(3);

        //死循環,保證主線程不退出
        while (true){
            executor.execute(new SocketHandler(serverSocket.accept()));
        }
    }

client客戶端:

public class Client {

    public void send(String message){
        Socket socket = null;
        BufferedReader bufferedReader = null;
        PrintWriter writer = null;
        try {
            socket = new Socket("127.0.0.1",9090);

            //發送數據到服務端
            writer = new PrintWriter(new OutputStreamWriter(socket.getOutputStream()), true);
            writer.println(message);
            System.out.println("發送內容:\t"+message);

            //接收服務端返回數據流
            bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
            String input = null;
            while ((input = bufferedReader.readLine()) != null){
                System.out.println("接收服務端數據:\t"+input);
                //退出指令,關閉連接
                writer.println("exit");
                break;
            }
        } catch (UnknownHostException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (writer != null) writer.close();
                if (bufferedReader != null) bufferedReader.close();
                socket.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    public static void main(String[] args) {
        Client client = new Client();
        for (int i = 0; i < 10; i++) {
            String text = RandomStringUtils.randomAlphabetic(5);
            client.send(text);
        }
    }

 

PrintWriter 與 BufferedWriter 的區別:

  PrintWriter:是一種格式化對象的輸出流,是一種高級流。此類實現了所有的PrintStream的print方法,它不包含用於寫原始字節的方法,而對於原始字節,程序應該使用未編碼的字節流。

與PrintStream相比較,它具有自動行刷新的緩沖字符輸出流。只需要在構造函數中指定參數autoFlush=true,使用方法println()即可實現自動行刷新。(println(xx) = print(xx) + println())。

這個類中的方法永遠不會拋出I/O異常,盡管它的一些構造函數可能拋出I/O異常。客戶端可以通過調用checkError()來查詢是否發生了錯誤。

PrintWriter還可以直接與文件通信:

new PrintWriter("c://text.txt");

  BufferedWriter:字符緩沖輸出流(高級流),將文本寫入字符輸出流,緩沖各個字符,從而提供單個字符、數組和字符串的高效寫入。 可以指定緩沖區的大小,或者接受默認的大小。在大多數情況下,默認值就足夠大了。

提供了一個newLine()方法,通知流結束。因此如果把上面的PrintWriter 換成BufferedWriter

BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
bufferedWriter.write(result);
bufferedWriter.newLine();
bufferedWriter.flush();

 

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM