記錄 serverSocket socket 輸入,輸出流,關閉順序,阻塞,PrintWriter的一些問題.


關於socket.getOutputStream() 的一些問題, OutputStream的flush是一個空方法,所以需要另一個實現了Flush的流來包裝一下

這里為什么使用PrintWriter,而不使用BufferedWriter

原因是在接收方使用BufferedReader 的readLine,而BufferedWriter.write並不會自動換行,所以會導致讀取阻塞,需要手動換行,代碼如下:

            BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
            bw.write("你好啊");
//            因為在服務端使用的是readLine,所以如果不調用newLine,那么會一直阻塞
            bw.newLine();
            bw.flush();

 

 

以下兩個測試類代碼,在輸出數據的時候,輸出空行為結束符,在讀取輸入流的時候都在循環內判斷了readLine長度是否為0(當然規范的做法是約定長度,根據長度判斷是否結束),原因如下摘抄☞:點擊這里

對於socket,不能認為把某次寫入到流中的數據讀取完了就算流結尾了,但是socket流還存在,還可以繼續往里面寫入數據然后再讀取。所以用BufferedReader封裝socket的輸入流,調用BufferedReader的readLine方法是不會返回null的

所以在循環內如果不判斷   msg!=null&&msg.length()>0  那么程序將會一直阻塞在這里(程序是因為readLine阻塞,並不是死循環)

 

關於流的關閉會影響socket的使用,而且對一次連接關閉流以后,沒有辦法再次打開,哪怕只關閉輸入流,也會導致輸出流不能使用.反之亦然.

所以如果在一次IO操作以后,還有另一次IO,那么就先不關閉.等全部用完再關閉.

 

ServerSocket 

@RunWith(JUnit4.class)
public class ServerSocketTest {
    @Test
    public void testServer(){
        ServerSocket serverSocket = null;
        try {
            serverSocket = new ServerSocket();
//            serverSocket.setReuseAddress(true);
//            System.out.println(InetAddress.getLocalHost());//獲取的本機地址不一定正確
            serverSocket.bind(new InetSocketAddress(8000));
            
            while(true){
                //一旦連接,返回的socket包含客戶端信息的socket
                Socket socket = serverSocket.accept();
                PrintWriter pw = new PrintWriter(socket.getOutputStream(),true);
                pw.println("host:"+socket.getInetAddress()+":"+socket.getPort()+"建立鏈接");
                //這里發送空行作為結束符,當然規范做法是根據長度作為標識
                pw.println("");
                //因為new PrinWriter的時候指定了autoFlush的參數為true所以不用手動flush
//                pw.flush();
                BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
                for(String msg = br.readLine();msg!=null&&msg.length()>0;msg = br.readLine()){
                    System.out.println(msg);
                }
                pw.close();
                br.close();
            }
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

    }
    
}

 

 

ClientSocket

/**
 * 
 * @author lzw
 *
 */
@RunWith(JUnit4.class)
public class SocketClient {
    @Test
    public void testClient() throws UnknownHostException, IOException{
        //表示連接到服務器的 地址以及端口
        SocketAddress address = new InetSocketAddress("19.95.103.112",8000);
        Socket socket = new Socket();
        socket.connect(address,60000);//連接
        //讀取服務端返回的數據
        getMsb(socket);
        sendMsg(socket);
        socket.close();
    }
    
    
    private void sendMsg(Socket socket){
        PrintWriter pw = null;
//        BufferedWriter bw = null;
        try {
            
//            bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
//            bw.write("你好啊");
            //因為在服務端使用的是readLine,所以如果不調用newLine,那么會一直阻塞
//            bw.newLine();
//            bw.flush();
//            OutputStream os =  socket.getOutputStream();
//            //這個是一個空方法
//            os.flush();
            pw = new PrintWriter(socket.getOutputStream(),true);
            pw.println("你好啊");
       //輸出空行作為結束標識
       pw.println("");
//因為new PrinWriter的時候指定了autoFlush的參數為true所以不用手動flush // pw.flush(); } catch (IOException e) { e.printStackTrace(); }finally{ //因為本次連接,到這個方法以后沒有更多交互,所以可以關閉 if(pw!=null){ pw.close(); } } } private void getMsb(Socket socket){ InputStream is = null; BufferedReader br = null; try { is = socket.getInputStream(); br = new BufferedReader(new InputStreamReader(is)); for(String msg = br.readLine();msg!=null&&msg.length()>0;msg = br.readLine()){ System.out.println(msg+"--"); } } catch (IOException e) { e.printStackTrace(); }finally{ //這里不能關閉流,否則會把socket也關閉了(因為后面還要發送數據,所以不能關閉流,不管是關閉輸入輸入其中之一,都會導致輸入和輸出都不能使用) // try { // if(br!=null) // br.close(); // } catch (IOException e) { // e.printStackTrace(); // } } } }

 


免責聲明!

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



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