簡體   English   中英

無法從以編程方式打開的套接字接收數據

[英]Cannot receive data from socket opened programmatically

已解決 :第一次連接后,我沒有重新啟動服務器。 現在它工作得很漂亮;)

我在Android設備和PC之間的TCP連接方面遇到麻煩。 在PC上,我有一個帶有ServerSocket等待接受的tcp服務器,並且本地網絡中的Android設備正試圖連接到它。 當我將靜態IP地址添加到代碼中時,一切正常,但是當我以編程方式使它(從0到255在硬編碼端口上搜索192.168.1.x)時,它接受連接,但是我既無法從ServerSocket也無法接收數據從Android套接字。

在Android上,我有帶有3個按鈕的Widget,所有通信均由AsyncTasks處理。 這是TCP服務器:

public class TCPClient {

private static final String TAG = "TCPClient";
private final Handler mHandler;


private String ipNumber;
BufferedReader in;
PrintWriter out;
private OnMessageReceived mMessageListener = null;
private boolean mRun = false;
private String serverMessage,command;

public TCPClient(Handler mHandler, String command, String ipNumber, OnMessageReceived listener) {
    mMessageListener = listener;
    this.ipNumber = ipNumber;
    this.command = command;
    this.mHandler = mHandler;
}

public void sendMessage(String message){
    if (out != null && !out.checkError()) {
        out.println(message);
        out.flush();
        mHandler.obtainMessage(MainActivity.SENDING);
        Log.d(TAG, "Sent Message: " + message);

    }
}


public void stopClient(){
    mRun = false;

}

public void run() {

    mRun = true;


    try {
        //here you must put your computer's IP address.
        InetAddress serverAddr = InetAddress.getByName(ipNumber);

        Log.d(TAG, "C: Connecting...");

        //create a socket to make the connection with the server
        Socket socket = new Socket(serverAddr, 4444);


        try {

            //send the message to the server
            out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())), true);

            Log.d("TCP Client", "C: Sent.");

            Log.d("TCP Client", "C: Done.");

            //receive the message which the server sends back
            in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
            this.sendMessage(command);
            //in this while the client listens for the messages sent by the server
            while (mRun) {
                serverMessage = in.readLine();


                Log.d("TCP", "S: Received Message: '" + serverMessage + "'");
                if (serverMessage != null && mMessageListener != null) {
                    //call the method messageReceived from MyActivity class
                    mMessageListener.messageReceived(serverMessage);

                }
                serverMessage = null;

            }

            Log.d("TCP", "S: Received Message: '" + serverMessage + "'");

        } catch (Exception e) {

            Log.d("TCP", "S: Error", e);

        } finally {
            //the socket must be closed. It is not possible to reconnect to this socket
            // after it is closed, which means a new socket instance has to be created.
            out.flush();
            out.close();
            in.close();
            socket.close();
            Log.d("TCP", "Socket Closed");
        }

    } catch (Exception e) {

        Log.d("TCP", "C: Error", e);

    }

}

//Declare the interface. The method messageReceived(String message) will must be implemented in the MyActivity
//class at on asynckTask doInBackground
public interface OnMessageReceived {
    public void messageReceived(String message);
}

}

在這里,我有AsyncTask用於啟動和處理連接:

public class ShutdownAsyncTask extends AsyncTask<String, String, TCPClient> {

private static final String COMMAND = "shutdown -s";
private TCPClient tcpClient;
private Handler mHandler;
private static final String TAG = "ShutdownAsyncTask";

public ShutdownAsyncTask(Handler mHandler){
    this.mHandler = mHandler;
}

@Override
protected TCPClient doInBackground(String... params) {
    Log.d(TAG, "In do in background");

    try{
        tcpClient = new TCPClient(mHandler,COMMAND, new IpGetter().getIp(), new TCPClient.OnMessageReceived() {
            @Override
            public void messageReceived(String message) {
                publishProgress(message);
            }
        });
    }catch (NullPointerException e){
        Log.d(TAG, "Caught null pointer exception");
        e.printStackTrace();
    }
    tcpClient.run();
    return null;
}

@Override
protected void onProgressUpdate(String... values) {
    super.onProgressUpdate(values);
    Log.d(TAG, "In progress update, values: " + values);
    if(values.equals("connected")){
        tcpClient.sendMessage(COMMAND);
        tcpClient.stopClient();
        mHandler.obtainMessage(MainActivity.SHUTDOWN);
    }else{
        tcpClient.sendMessage("wrong");
        mHandler.obtainMessage(MainActivity.ERROR);
        tcpClient.stopClient();
    }
}

@Override
protected void onPostExecute(TCPClient result){
    super.onPostExecute(result);
    Log.d(TAG, "In on post execute");
}

}

這里我有IpGetter類,該類具有用於從本地網絡動態獲取IP的方法getIp():

public class IpGetter {

private static Future<String> portIsOpen(final ExecutorService es, final String ip, final int port, final int timeout) {
   Log.d("IpGetter", "In portIsOpen");
    return es.submit(new Callable<String>() {
        @Override public String call() {
            try {
                Socket socket = new Socket();
                socket.connect(new InetSocketAddress(ip, port), timeout);
                socket.close();
                Log.d("portIsOpen", "ip: " + ip);
                return ip;
            } catch (Exception ex) {
                return null;

            }
        }
    });
}

public static String getIp(){
    final ExecutorService es = Executors.newFixedThreadPool(20);

    final int timeout = 200;
    final int port = 4444;
    final List<Future<String>> futures = new ArrayList<Future<String>>();
    for (int i = 0; i <= 255; i++) {
        String ip = "192.168.1."+i;
        futures.add(portIsOpen(es, ip, port, timeout));
    }
    es.shutdown();

    for (final Future<String> f : futures) {
        try {
            if (f.get() != null) {
                Log.d("F get", f.get());
                return f.get();
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
    }
    return null;
}

}

在服務器端,一切正常。 當我改變時,一切都在改變:

try{
        tcpClient = new TCPClient(mHandler,COMMAND, "192.168.1.103",...

至:

try{
        tcpClient = new TCPClient(mHandler,COMMAND, new IpGetter().getIp(),....

有人知道如何管理嗎? 感謝幫助。

好的,我解決了。 原來,我沒有為IpGetter打開套接字后才重新啟動服務器。 現在我完成了!

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM