java–socket流的flush()的可靠性如何?

java–socket流的flush()的可靠性如何?,第1张

概述考虑这个(简化的)代码段:publicclassTest{//assignedelsewhereInetSocketAddresssocketAddress;StringsocketHost;intsocketPort;Socketsocket;intCOMMAND=10;intCONNECTION_TIMEOUT=10*1000;intSOCKET_TIMEOUT=30

考虑这个(简化的)代码段:

public class Test {    // assigned elsewhere    InetSocketAddress socketAddress;    String socketHost;    int socketPort;    Socket socket;    int COMMAND = 10;    int CONNECTION_TIMEOUT = 10 * 1000;    int SOCKET_TIMEOUT = 30 * 1000;    DataOutputStream dos;    DatainputStream  dis;    protected voID connect() throws IOException, InterruptedException {        socket.connect(socketAddress != null ? socketAddress : new InetSocketAddress(socketHost, socketPort), CONNECTION_TIMEOUT);        socket.setSoTimeout(SOCKET_TIMEOUT);        socket.setTcpNoDelay(true);    }    voID initializeDataStreams() throws IOException {        dos = new DataOutputStream(new bufferedoutputstream(socket.getoutputStream(), socket.getSendBufferSize()));        dis = new DatainputStream( new BufferedinputStream( socket.getinputStream(),  socket.getReceiveBufferSize()));    }    voID run() {        try {            connect();            initializeDataStreams();            sendCommand(COMMAND, true);            sendIDAndUsername(true);            sendSyncPreference(true);            sendBlockedIDs(true);            sendheaders();            // reading from 'dis' here            // ...        } catch (InterruptedException | IOException e){            /* ... */        }    }    voID sendCommand(int command, boolean buffered) throws IOException {        dos.write(command);        if (!buffered) {            dos.flush();        }    }    voID sendIDAndUsername(boolean buffered) throws IOException {        sendID(true);  // always buffered        String username = "user name";        dos.writeBoolean(username != null);        if (username != null) {            dos.writeUTF(username);        }        if (!buffered) {            dos.flush();        }    }    voID sendID(boolean buffered) throws IOException {        dos.writeUTF("user ID");        if (!buffered) {            dos.flush();        }    }    voID sendSyncPreference(boolean buffered) throws IOException {        boolean fullSync = true;        dos.writeBoolean(fullSync);        if (!buffered) {            dos.flush();        }    }    voID sendBlockedIDs(boolean buffered) throws IOException {        Set<String> blockedCrocoIDs = new HashSet<>();        ObjectOutputStream oos = new ObjectOutputStream(dos);        oos.writeObject(blockedCrocoIDs);        if (!buffered) {            oos.flush();        }    }    private voID sendheaders() throws IOException {        dos.writeUTF("some string");        dos.writeInt(123);        // some other writes...        // this should flush everything, right?        dos.flush();    }}

我故意用所有方法离开它,以防我在那里犯了一些非常明显的错误.当我执行Test.run()时,有时(真的很难预测到什么时候)似乎sendheaders()中的flush()根本不起作用.

服务器端在接下来的22秒内没有在其ServerSocket.accept()上收到任何东西(不要问我这个号码来自何处,这是神秘的一部分).

我的想法是,我不会在每次传输时调用flush(),但只调用一次,以节省带宽.

那么这段代码有什么问题呢?如何确保对我的流的写入是可靠的/立即的,以便服务器可以尽快读取它?

我也接受回答“没有错”,在这种情况下,它必须是并行完成并影响AndroID上的网络堆栈的东西.

编辑:服务器代码真的没什么特别的:

ListeningThread ListeningThread = new ListeningThread();ListeningThread.start();ListeningThread.join();

然后:

public class ListeningThread extends Thread {    private ServerSocket serverSocket;    public ListeningThread() {        try {            // unbound server socket            serverSocket = new ServerSocket();            serverSocket.setReuseAddress(true);            serverSocket.bind(new InetSocketAddress(NetworkUtil.APP_SERVER_PORT));        } catch (IOException e) {            log(e);        }    }    @OverrIDe    public voID run() {        log("run");        while (serverSocket.isBound() && !isInterrupted()) {            try {                Socket socket = serverSocket.accept();                new CommandThread(socket).start();            } catch (IOException e) {                log(e);            }        }        try {            serverSocket.close();        } catch (IOException e) {            log(e);        }    }}

最后:

public class CommandThread extends Thread {    private final Socket socket;    public CommandThread(Socket socket) {        log("CommandThread");        this.socket = socket;    }    @OverrIDe    public voID run() {        log("run");        try {            socket.setSoTimeout(NetworkUtil.soCKET_TIMEOUT);            socket.setTcpNoDelay(true);            inputStream is = socket.getinputStream();            int cmd = is.read(); // <========= so actually this is failing            switch (cmd) {                // handling of the command                case COMMAND:                    new DownloadMessagesThread(socket).start();                break;            }        } catch (IOException | sqlException e) {            log(e);        }    }}

正如评论中所提到的,我愿意同意对象流的任何错误.但问题是我无法触及(再次,它只是有时,它是非常随机的……)CommandThread的run().因此,除非我遗漏了其他内容,否则Object Streams无法导致这种失败.

编辑2:更正:它不接受()我无法达到,这是第一次读取 *** 作:

03-07 11:22:42.965 00010 CommandThread: CommandThread

03-07 11:22:42.966 00108 CommandThread: run

[… nothing happening …]

03-07 11:23:04.549 00111 DownloadMessagesThread: run

这可能是由于混合了对象流和数据流吗?

解决方法:

您应该验证sendBlockedIDs中的ObjectOutputStream创建不是罪魁祸首.
在混合DataStreams和ObjectStreams时,我已经有了一些协议“死锁”,因为创建Writer / Reader对ObjectStreams意味着一种握手,在混合这些流时可能会失败.

编辑:在再次阅读你的问题时,我意识到我没有回答.所以,是的,它是可靠的.和EJP答案1.

总结

以上是内存溢出为你收集整理的java – socket流的flush()的可靠性如何?全部内容,希望文章能够帮你解决java – socket流的flush()的可靠性如何?所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/web/1108419.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-29
下一篇 2022-05-29

发表评论

登录后才能评论

评论列表(0条)

保存