在线观看不卡亚洲电影_亚洲妓女99综合网_91青青青亚洲娱乐在线观看_日韩无码高清综合久久

鍍金池/ 問答/Java/ Java Socket 發(fā)送數(shù)據(jù)給ServerSocket失敗

Java Socket 發(fā)送數(shù)據(jù)給ServerSocket失敗

需求
通過 adb forward tcp:localport tcp:remoteport 進行端口轉發(fā),實現(xiàn) PC(客戶端)Android(服務端) 進行 Socket 通信

PC端
PC端使用的是JavaFX編寫的界面,在其Controller中的代碼是:

    public class ImageController {
    
        public void onButtonClicked(ActionEvent event) {
            try {
                Runtime.getRuntime().exec("adb forward tcp:10000 tcp:20000");
            
                Socket client = new Socket(InetAddress.getByName("127.0.0.1"), 10000);
                // 向服務端發(fā)送消息: hello
                OutputStream out = client.getOutputStream();
                out.write("hello".getBytes());
                out.flush();
            
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

Android服務端

/**
    接收客戶端
*/
public class PCService extends Service {
    private static final int SERVER_PORT = 20000;
    
    @Override
    public void onCreate() {
        super.onCreate();
        new Thread(() -> doListening()).start();
    }
    
    private void doListening() {
        try {
            ServerSocket server = new ServerSocket(SERVER_PORT);
            Log.i(TAG, "服務器監(jiān)聽中....");
            Socket client = server.accept();
            new Thread(new SocketIO(client)).start();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

SocketIO 客戶端連接成功后,進行處理的類,繼承Runnable

class SocketIO implements Runnable {
    private Socket mClient;

    public SocketIO(Socket client) {
        mClient = client;
    }

    @Override
    public void run() {
        if (mClient.isConnected()) {
            try {
                // 接收客戶端發(fā)來的消息
                InputStream in = mClient.getInputStream();
                Scanner scan = new Scanner(in);
                scan.useDelimiter("\\A");
                String msg = scan.hasNext() ? scan.next() : "暫無";
                
                System.out.println("接收到的數(shù)據(jù): " + msg);

                switch (msg) {
                    case "hello":
                        // TODO: doSomething();
                       break;
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        } else {
            Log.i(TAG, "客戶端未連接");
        }
    }
}

問題

  1. PC端,out.flush() 之后不寫任何東西是,點擊按鈕,Android服務端沒有任何顯示,當關閉PC端應用程序時, Android服務端顯示 -> 接收到數(shù)據(jù): hello
  2. out.flush() 之后添加 client.shutdownOutputStream() 后, Android服務端顯示 -> 接收到數(shù)據(jù): 暫無 (意思就是沒有收到PC端發(fā)來的消息)

想要得到的幫助

  1. 如何解決上面的通信問題? PC端發(fā)送一條消息給Android端, Android根據(jù)消息內容作出響應返回給PC端?
回答
編輯回答
淺淺

你想寫一個通訊程序,可以先試在在普通java工程中寫好,再移植到android工程上。

這是官方指導文檔
https://docs.oracle.com/javas...

也可以看看別的代碼參考下。如http://cs.lmu.edu/~ray/notes/...

你這段代碼的主要問題在你使用的Scanner,Sacnner在讀取流的時候不會主動刷新。
客戶端發(fā)過來的數(shù)據(jù),始終在緩沖區(qū)中,當tcp鏈接異常關閉時才會被刷新。
如果服務段相關讀取數(shù)據(jù)替換成下面這樣,可以正常顯示客戶端發(fā)過來的數(shù)據(jù)。

  int len = in.available();
byte [] bys  =new byte[len];
int readbytes = in.read(bys);
if(readbytes!=0)
{
    String res= new String(bys);
    System.out.println(res);
}

問題1與問題2,因為調用client.shutdownOutputStream()后,tcp會出送rst包。收到rst包的服務器端,會丟棄緩沖區(qū)的數(shù)據(jù)。如果不調用,tcp會發(fā)送fin包,服務器收到fin包,知道要結束了,于是主動刷新Scanner,準備退出。

2017年6月29日 04:38