在关闭套接字之前,Android TCP不会刷新

时间:2012-08-07 13:28:14

标签: android sockets tcp flush dataoutputstream

我一直在尝试各种实现来完成这项工作,并且已经搜索了StackOverflow和Android开发人员以获得解决方案,但我在编程方面没有太多经验,并且无法使这个块能够使代码正常工作。

我的意图:

  1. 这是一个循环检查是否有outMessage的线程,如果有,它将发送消息。
  2. 接下来它会检查插件中是否有任何内容,如果有,它会将其发送到我的主要活动中的处理程序。
  3. 最后,它将睡眠1秒钟,然后再次检查。
  4. 这应该允许我多次读/写,而无需关闭和打开套接字。
  5. 问题:

    • 在我关闭套接字之前,流不会被刷新。 flush()似乎没有效果。

    我的要求:

    • 请发布所需的更改,以使此代码正常工作,如上所述(任何注释解释为什么会非常感激。链接到其他类似的问题/答案将很好,以帮助我学习,但我一直在看那些几个星期而且无法让它工作,所以请确保您还包含更改此代码所需的内容,以便按上述方式工作。提前致谢。

    其他:

    • 我想知道我的插播和/或外流是否需要寻找行尾字符?
    • 这里会使用像TCP_NODELAY这样的东西吗?
    • 我们非常感谢您提供的任何额外信息。我想好好学习这些东西,但我目前无法正常工作。

    代码:

     public void run() {                        
            while (connectionStatus == TCP_SOCKET_STATUS_CONNECTED) {
                try {   
                    if (outMessage != null){
                       OutStream.writeBytes(outMessage);
                       OutStream.flush();           
                       outMessage = ("OUT TO SERVER: " + outMessage);           
                    // socketClient.close();     
                       sendMessageToAllUI(0, MAINACTIVITY_SET_TEXT_STATE, "appendText" , outMessage);
                       outMessage = null;               
                    } 
                    if (InStream != null) {                     
                        String modifiedSentence = InStream.readLine();      
                        sendMessageToAllUI(0, MAINACTIVITY_SET_TEXT_STATE, "appendText" , "\n" + "IN FROM SERVER: " + modifiedSentence);
                }
                Thread.sleep(1000);
            } catch (IOException e) {               
                connectionLost();
                break;
            } catch (InterruptedException e) {
                    e.printStackTrace();
                }
        }                           
    }
    

    创建套接字的线程:

    public void run() {
            if(I) Log.i(LOGTAG, "Attempt Connection with IP: " + serverIP + " ...");
            setName("AttemptConnectionThread");
            connectionStatus = TCP_SOCKET_STATUS_CONNECTING;
            try {
                SocketAddress sockaddr = new InetSocketAddress(serverIP, port);
                tempSocketClient = new Socket(); // Create an unbound socket
    
                // This method will block no more than timeoutMs. If the timeout occurs, SocketTimeoutException is thrown.
                tempSocketClient.connect(sockaddr, timeoutMs);
                OutStream = new DataOutputStream(tempSocketClient.getOutputStream());
                InStream = new BufferedReader(new InputStreamReader(tempSocketClient.getInputStream()));
                socketClient = tempSocketClient;
                socketClient.setTcpNoDelay(true);
                connected(); 
            } catch (UnknownHostException e) {
                if(I) Log.i(LOGTAG,"     ...UnknownException e: e.getMessage() shows: " + e.getMessage());
                connectionFailed();
            } catch (SocketTimeoutException e) {
                if(I) Log.i(LOGTAG,"     ...SocketTimoutException e: e.getMessage() shows: " + e.getMessage());
                connectionFailed();
            } catch (IOException e) {
                if(I) Log.i(LOGTAG,"     ...caught on run()");
                // Close the socket
                try {
                    tempSocketClient.close();
                } catch (IOException e2) {
                    Log.e(LOGTAG, "unable to close() socket during connection failure", e2);
                }
                if(I) Log.i(LOGTAG,"     ...IOException e: e.getMessage() shows: " + e.getMessage());
                connectionFailed();
                return;
            }
        } 
    

    我在网上找到并使用的java服务器,直到我将其移植到真实服务器上:

    public class Server {
    
    private static String SERVERIP;
    
    /**
     * @param args
     * @throws IOException
     */
    
    public static void main(String[] args) throws IOException {
        String clientSentence;
        String capitalizedSentence;
    
        try {
            ServerSocket welcomeSocket = new ServerSocket(8888);
            getIp();
            System.out.println("Connected and waiting for client input!\n");
    
            while (true) {
                Socket connectionSocket = welcomeSocket.accept();
                BufferedReader inFromClient = new BufferedReader(
                        new InputStreamReader(connectionSocket.getInputStream()));
                DataOutputStream outToClient = new DataOutputStream(
                        connectionSocket.getOutputStream());
    
                clientSentence = inFromClient.readLine();
                String ip = connectionSocket.getInetAddress().toString()
                        .substring(1);
                System.out.println("In from client (" + ip + "): "
                        + clientSentence);
                if (clientSentence != null) {
                    capitalizedSentence = clientSentence.toUpperCase() + '\n';
                    System.out.println("Out to client (" + ip + "): "
                            + capitalizedSentence);
                    outToClient.writeBytes(capitalizedSentence + "\n");
                }
    
            }
        } catch (IOException e) {
            // if server is already running, it will not open new port but
            // instead re-print the open ports information
            getIp();
            System.out
                    .println("Server connected and waiting for client input!\n");
    
        }
    }
    
    private static void getIp() {
        InetAddress ipAddr;
        try {
            ipAddr = InetAddress.getLocalHost();
            System.out.println("Current IP address : "
                    + ipAddr.getHostAddress());
    
        } catch (UnknownHostException e) {
            e.printStackTrace();
        }
    }
    }
    

2 个答案:

答案 0 :(得分:3)

我怀疑你正在阅读消费者的内容,但你不是在写行,所以消费者阻止它直到获得EOS并提供一条大线。根据需要在发送时添加行终止符。

答案 1 :(得分:1)

由于这些是短消息(< MSS),我猜堆栈可能正在实现Nagle的算法。服务器是否在进行某种延迟的ACK?如果可能,您应捕获跟踪并查看另一方是否有待处理的确认。

在任何一种情况下,TCP_NODELAY都应该有所帮助。