【问题标题】:Android socket still can write without exception when wifi has been disconnectedwifi断开后,Android socket仍然可以正常写入
【发布时间】:2012-12-20 22:41:11
【问题描述】:

我编写了一个 Android 套接字演示,它只是将用户的输入发布到服务器。 我通过wifi连接从android客户端建立了一个socket,一切顺利,服务器可以接收到android客户端发送的消息。问题是,然后我关闭了手机的WIFI,但是socket却可以正常写入。

Android客户端代码:

public class MyActivity extends Activity {
    private SocketHandlerThread thread;

    /**
     * Called when the activity is first created.
     */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        thread = new SocketHandlerThread("ScoketTest");
        thread.start();
    }

    class SocketHandlerThread extends HandlerThread {
        private Socket socket;
        private Handler handler;

        public SocketHandlerThread(String name) {
            super(name);
        }

        public SocketHandlerThread(String name, int priority) {
            super(name, priority);
        }

        @Override
        public void run() {
            try {
                socket = new Socket("192.168.60.184", 1990);
            } catch (IOException e) {
                Log.e("SocketTest", e.getLocalizedMessage(), e);
            }
            super.run();
        }

        Handler getHandler() {
            if (handler == null) {
                handler = new Handler(getLooper());
            }
            return handler;
        }

        void send(final String text) {
            Runnable runnable = new Runnable() {
                public void run() {
                    Log.e("SocketTest", "Start send text: " + text);
                    try {
                        socket.getOutputStream().write((text + "\n").getBytes());
                        socket.getOutputStream().flush();
                    } catch (Exception e) {
                        Log.e("SocketTest", e.getLocalizedMessage(), e);
                    }
                    Log.e("SocketTest", "Text has been send:" + text);
                }
            };
            getHandler().post(runnable);
        }

        @Override
        protected void onLooperPrepared() {
            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    findViewById(R.id.button).setEnabled(true);
                }
            });
        }
    }

    public void send(View view) {
        String text = ((EditText) findViewById(R.id.text)).getText().toString();
        thread.send(text);
    }
}

服务器代码:

public class SocketTestServer {
    ServerSocket serverSocket;

    SocketTestServer() throws IOException {
        serverSocket = new ServerSocket(1990);
    }

    void start() throws IOException {
        Socket clientSocket = serverSocket.accept();
        clientSocket.getInputStream();
        PrintWriter out = new PrintWriter(System.out, true);
        BufferedReader in =
                new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
        String inputLine;
        while ((inputLine = in.readLine()) != null) {
            out.println(inputLine);
        }
    }

    public static void main(String[] args) throws IOException {
        SocketTestServer server = new SocketTestServer();
        server.start();
    }
}

我尝试了几部手机。在 Galaxy Nexus(4.2.1) 上按预期抛出异常,但在某些 MOTO 或 HTC 手机上,套接字仍然可以毫无异常地写入,这意味着我可能会丢失一些我认为已成功接收的消息。 我怎么知道任何类型的手机上的套接字连接都断开了?

任何建议将不胜感激。

附言 我知道 Connective Change Broadcast,但在接收到广播之前,客户端可能已经通过损坏的套接字写入了一些消息。

虽然在应用协议上添加接收检查可以解决消息丢失的问题,但我更愿意保证传输层的可靠性,这也是 TCP 协议承诺的。

【问题讨论】:

    标签: android sockets wifi


    【解决方案1】:

    我在我的套接字中使用 Writer & IOException,它工作正常。试试这个:

    public static void sendUTF(String str)
        {
            try
            {
                outWriter.write(str + '\n');
                outWriter.flush();
            } 
            catch (IOException e)
            {
                e.printStackTrace();
                outServ.setText("Connection lost!");
            }
        }
    
    public static Writer outWriter = new OutputStreamWriter(outputStream, "UTF-8");
    

    【讨论】:

      【解决方案2】:

      这是TCP栈(OS层面)的问题,是一个很难解决的问题。 如果服务器是失去连接的服务器(尝试在打开套接字后重新启动服务器并且没有客户端会注意到),也会发生这种情况......下次通过套接字发送数据包时,您将遭受“管道损坏错误”。

      所以,有两种情况:

      1- 客户端发送信息时管道损坏。

      在这种情况下,您应该捕获 IOException 并重试打开连接(您必须定义重试策略)。

      2- 服务器断开连接时管道损坏

      当服务器失去连接时,客户端不会注意到,在这种情况下,您应该定期向服务器发送数据包(轮询技术)并尝试重新连接以防连接丢失。 仅当您从服务器接收更新时才需要这样做,如果您的流量始终是客户端-->服务器仅适用于场景 1。

      【讨论】:

        猜你喜欢
        • 2012-02-25
        • 2020-05-08
        • 2020-06-02
        • 2022-01-19
        • 1970-01-01
        • 1970-01-01
        • 2013-12-13
        • 2020-07-07
        • 1970-01-01
        相关资源
        最近更新 更多