【问题标题】:Android TCP Client/Server not passing messages properly (Only first received)Android TCP 客户端/服务器未正确传递消息(仅第一次收到)
【发布时间】:2013-05-12 18:45:07
【问题描述】:

我创建了两个 android 应用程序,一个客户端和一个服务器,利用 TCP 跨设备通信。在服务器上,我有这段代码来监听 TCP 通信:

private class StartServer implements Runnable {     
    public void run() {
            getState(); // This just refreshes the server state
            try {
                serverSocket = new ServerSocket(5000);
                appendLog("Server successfully listening ["+getLocalIpAddress() + ":5000]"); //appendLog function just uses runOnUiThread() to update the log textview
            } catch (IOException e) {
                appendLog("Could not listen on port: 5000");
                //System.exit(-1);
            }
            BufferedReader in = null;
            BufferedWriter out = null;
            String input = null;


            try {
                clientSocket = serverSocket.accept(); 
                in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
                out = new BufferedWriter(new OutputStreamWriter(clientSocket.getOutputStream()));

                while (serverState) { //variable set by our getState() function

                    input = in.readLine();
                    appendLog("Received: " + input);
                    this.gotMessage(out, input);
                }
                in.close();
                out.close();
            } catch (IOException e) {
                //appendLog(e.toString());
                appendLog("Accept failed: 5000");
                //System.exit(-1);
            }
    }

调用这个函数来实际解析收到的消息:

private void gotMessage(BufferedWriter output, String msg) {
        if (msg != null) {
            String sString = msg;
            int to_do = 0;


            if (msg.matches("^(?i)(exit|quit|close)$")) {
                appendLog("Exiting");
                sString = "Goodbye";
                to_do=1;
            } else if (msg.matches("^(?i)(launch|run|open)\\s(.+)")) {
                appendLog("Launching application");
                sString = "Launching application";
            } else if (msg.matches("^(?i)(turn off|server off|deactivate)$")) {
                appendLog("Turning off server due to remote command.");
                sString = "Turning off...";
                to_do=2;
            } else if (msg.matches("^(?i)(restart|reboot)$")) {
                appendLog("Resetting server");
                sString = "Rebooting now...";
                to_do=3;
            }


            try {
                output.write("S: " + sString);
                output.newLine();
                output.flush();
            } catch (IOException e) {
                appendLog("Cannot parse message");
            }


            switch(to_do) {
                case 0:
                    break;
                case 1:
                    System.exit(0);
                    break;
                case 2:
                    serverOff();
                    break;
                case 3:
                    serverOff();
                    serverOn();
                    break;
                default:
                    break;
            }
        }
    }
}

服务器的线程本身是使用Thread t = new Thread(new StartServer()); t.start() 启动的。据我所知,这很好用。我可以打开一个终端和telnet到IP和端口,并且来回通信没有错误。但是当我尝试从下面的客户端代码中做同样的事情时。我只收到第一条消息,而我传递的任何其他信息都会消失在虚空中。

public void sendToServer(View v) {
    try {
        String ip = ((TextView)findViewById(R.id.ip_box)).getText().toString(); //User entered IP address
        String to_send = ((EditText)findViewById(R.id.send_to_server)).getText().toString(); //User entered text to send
        this.s = new Socket(ip, 5000);
        BufferedWriter out = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
        appendLog("Sending: " + to_send);
        out.write(to_send);
                    out.newLine();
        out.close();
    } catch (Exception e) {
        Log.d("error", e.toString());
    }
}

【问题讨论】:

    标签: java android sockets tcp serversocket


    【解决方案1】:

    to_send 字符串中有行尾字符吗?如果没有,只需将out.newLine() 添加到您的客户端代码:

    appendLog("Sending: " + to_send);
    out.write(to_send);
    out.newLine();
    

    您的服务器代码应如下所示以支持多个客户端:

    // main server loop
    while (serverIsActive) {
        clientSocket = serverSocket.accept(); 
        // spawn new thread for each client
        ClientThread ct = new ClientThread(clientSocket);
        ct.start();
    }
    

    ClientThread 应该与客户端套接字一起工作,并且有自己的循环来读取行。它应该在客户端关闭套接字后立即停止:

    class ClientThread {
        ...
        public void run() {
            ....
            while ((inputLine = in.readLine()) != null) {
                // process client message
            }
            in.close();
        }
    }
    

    【讨论】:

    • 之前试过了,很快就加回来验证了。不幸的是,仍然没有工作。第一条消息总是成功地出现,但后面的任何消息都不会。
    • 你在客户端关闭连接,这使得in缓冲区在服务器端无效
    • 将客户端上的out.close() 替换为out.flush(),但这也没有解决问题。
    • 您应该重构服务器而不是客户端,每次发送消息时都会创建新客户端,因此即使刷新客户端流,您也不再使用它。服务器仍连接到您的旧流并等待消息
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-09-08
    • 2013-01-18
    • 2020-08-07
    • 1970-01-01
    • 2017-04-22
    相关资源
    最近更新 更多