Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sockets/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android TCP在套接字关闭之前不会刷新_Android_Sockets_Tcp_Flush_Dataoutputstream - Fatal编程技术网

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

Android TCP在套接字关闭之前不会刷新,android,sockets,tcp,flush,dataoutputstream,Android,Sockets,Tcp,Flush,Dataoutputstream,我一直在尝试各种实现来实现这一点,并在StackOverflow和Android开发人员中寻找解决方案,但我在编程方面没有太多经验,无法让这段代码正常工作 我的意图: 这是在一个线程中,该线程将循环检查是否有outMessage,如果有,它将发送消息 接下来,它将检查in-stream中是否有任何内容,如果有,它将把它发送给我的主活动中的处理程序 最后,它将休眠1秒,然后再次检查 这应该允许我读/写多次,而无需关闭和打开套接字 问题: 直到我关上插座,外流才被冲洗。flush()似乎没有效果

我一直在尝试各种实现来实现这一点,并在StackOverflow和Android开发人员中寻找解决方案,但我在编程方面没有太多经验,无法让这段代码正常工作

我的意图:

  • 这是在一个线程中,该线程将循环检查是否有outMessage,如果有,它将发送消息
  • 接下来,它将检查in-stream中是否有任何内容,如果有,它将把它发送给我的主活动中的处理程序
  • 最后,它将休眠1秒,然后再次检查
  • 这应该允许我读/写多次,而无需关闭和打开套接字
  • 问题:

    • 直到我关上插座,外流才被冲洗。flush()似乎没有效果
    我的请求:

    • 请发布所需的更改,以使此代码如上所述正常工作(任何解释原因的注释都将不胜感激。指向其他类似问题/答案的链接将非常有助于我的学习,但我已经看了几周了,只是无法使其正常工作,因此请确保您还包括此代码所需的更改,以便按上述方式工作。提前感谢
    其他:

    • 我想知道我的流内和/或流外是否需要查找行尾字符
    • 这里会使用像TCP_NODELAY这样的东西吗
    • 任何可以提供的额外信息都将非常感谢。我想好好学习这些东西,但我目前无法得到任何有用的东西
    代码:

    构成插座的螺纹:

    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();
        }
    }
    }
    

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


    在这两种情况下,
    TCP\u NODELAY
    都会有所帮助。

    我怀疑您正在消费者处读行,但您没有写行,因此消费者会阻止,直到它得到EOS并发送一条大行。在发送时根据需要添加行终止符。

    消息有多大?它们是在不同的线程中生成的吗?没有锁定?首先,在e消息大多是小字符串,比如“掉头”或“笔直行走”也可能有多行的,但仍然很短。第二,如果你是指阻塞,我不这么认为,但我对它的工作原理/如何检查有点困惑。我很确定它只在创建套接字时阻塞。这个阻塞应该在任何地方吗?如果你确实是指“锁定”我不知道在这个上下文中是什么。我的意思是锁定,以避免线程之间的竞争条件。我的问题是
    outMessage
    是在哪里创建的?mSocket.setTcpNoDelay(on);是我如何解释的,但eclipse希望我初始化“on”我是否设置do boolean on=true;?由于状态应该是持久的,所以我在创建套接字时是否应该执行这些操作?outMessage是我的服务中的静态成员。它当前是一个字符串,但在套接字正常工作后,我最终会将其更改为队列。此方法位于服务中的嵌套类中。因此,我可以保持套接字运行在可以绑定到服务的多个活动之间1.ACK代表什么?我在谷歌上搜索了它,但找不到定义2.我会给你和Nikolai建议的TCP_NODELAY一个镜头,如果它确实回答了问题,mark会回答。感谢到目前为止的帮助!ACK是TCP确认。而不是为每个s发送ACK此外,服务器可能正在等待将其捆绑。如果客户端实现Nagle的algo,它将在发送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(); } } }