无法以编程方式从套接字接收数据

时间:2014-10-18 16:58:18

标签: java android sockets tcp

已解决:我在第一次连接后没有重新启动服务器。现在它的工作非常漂亮;)

我在Android设备和PC之间遇到TCP连接问题。在PC上我有tcp服务器与ServerSocket等待接受,并且本地网络中的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类,它有方法getIp(),用于动态地从本地网络获取IP:

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(),....

有谁知道如何管理它?谢谢你的帮助。

1 个答案:

答案 0 :(得分:0)

好的,我解决了。事实证明,在打开IpGetter的套接字后,我没有重启服务器。现在我已经完成了!