1. 程式人生 > >Java-Tcp通訊,解決只能第一次接收到資料

Java-Tcp通訊,解決只能第一次接收到資料

今天老師讓寫一個服務端和客戶端通訊的小程式,本以為很快就能寫完,但是在寫的過程中卻發現了自己很多的問題,所以寫篇部落格記錄一下

寫完測試的時候發現,客服端只能發第一次資料給服務端,後面傳送的服務端都接受不到

//服務端        
    serverSocket=new ServerSocket(12900);
            socket=serverSocket.accept();
            inputStream=socket.getInputStream();
            byte[] bytes = new byte[1024];
            inputStream.read(bytes);
            String string = new String(bytes);
            System.out.println(string);

//客戶端
 String mess=message.getText();
                outputStream=socket.getOutputStream();
                outputStream.write(mess.getBytes());
                message.setText("");

後面加上了迴圈,發現還是隻能傳送第一次資料

 try {
            serverSocket=new ServerSocket(12900);
              
           while (true){   
                socket=serverSocket.accept();//一直阻塞直到有人連線它          
               inputStream=socket.getInputStream();
               byte[] bytes = new byte[1024];
               inputStream.read(bytes);
               String string = new String(bytes);
//                message.append(string+"\n");
               System.out.println(string);
           }

        }

查了資料才知道,socket是阻塞式通訊,accep()是會阻塞的和,read()也會阻塞,一直到有東西連線為止,或者有資料可讀,所以在這個迴圈中,第一次的時候因為有客戶端連線,所以能夠執行後面的程式碼,輸出資料,但後面開始就沒有客戶端連線,所以就一直阻塞在accept(),導致後面的沒法執行

 try {
            serverSocket=new ServerSocket(12900);
             socket=serverSocket.accept(); 
           while (true){   
                         
               inputStream=socket.getInputStream();
               byte[] bytes = new byte[1024];
               inputStream.read(bytes);
               String string = new String(bytes);
//                message.append(string+"\n");
               System.out.println(string);
           }

        }

這樣子就能夠實現客戶端一直給服務端傳送資料了

我對上面的程式進行了下改進,加入了執行緒,每一次有客戶端連線時,就建立一個執行緒處理這個客戶端的收發資料,也可藉此實現多客戶端向服務端通訊。

服務端執行緒類:

public class ServerThread extends Thread {
    private Socket socket;
    InputStream inputStream
    public  ServerThread(Socket socket){
        this.socket=socket;
    }
    public void run(){
        try {
            while (true){
                inputStream=socket.getInputStream();
                byte[] bytes = new byte[1024];
                inputStream.read(bytes);
                String string = new String(bytes);
                System.out.println(string);
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

服務端:

                System.out.println("wait client connect....");
                serverSocket=new ServerSocket(8808);
                while (true){
                    socket=serverSocket.accept();//有連線會返回一個Socket,其作為引數傳給服務端執行緒類
                    System.out.println("client successed !");
                    new ServerThread(socket).start();//有新的連線就建立一個對應的執行緒
                }

加入執行緒不好的地方就是,當執行緒多了會佔記憶體,而你每個執行緒只執行一點點事情,就會造成記憶體浪費,而且執行緒多了,Cpu會在各個執行緒來回切換,造成Cpu效率低 

客戶端:

                socket=new Socket("localhost", 12900);
                String mess=message.getText();
                outputStream=socket.getOutputStream();
                outputStream.write(mess.getBytes());
                message.setText("");

 

這是本人結合網上的方法,如有不對或者效率更好的方法,歡迎指出和請教。

其實,有個點我沒明白,我沒關閉輸入流和Socket,不是應該是一直連線的嗎能夠一直接收到資料,為啥還需要迴圈才能一直接收到資料呢,要是有大佬能看到我這篇,希望幫我解答下,提前謝謝啦