什么是最适当的方式来检测,如果一个插座已经下降或没有?或一个包是否确实获得发送?

我有一个图书馆发送的苹果推动通知的iphone手机通过的苹果gatways(提供。).客户需要打开一个插座和发送一个二元性表示每个消息;但不幸的是苹果没有返回的任何承认任何责任。连接可以重复使用发送的多个消息。我使用的是简单的Java座连接。相关代码是:

Socket socket = socket();   // returns an reused open socket, or a new one
socket.getOutputStream().write(m.marshall());
socket.getOutputStream().flush();
logger.debug("Message \"{}\" sent", m);

在某些情况下,如果一个连接是下降的话,一个消息发送或权利; Socket.getOutputStream().write() 成功完成。我希望这是由于TCP窗口未用尽。

有没有办法,我可以告诉为确保一个包是否实际上得到了在该网络中或没有?我尝试了以下两个方案:

  1. 插入一个附加的 socket.getInputStream().read() 操作与250毫秒的超时。这迫使一读操作失败的当连接下降,但挂否则为250毫秒。

  2. 设置TCP发送缓冲区的大小(例如 Socket.setSendBufferSize())的二进制信息的大小。

两者的方法的工作,但它们显着降低质量的服务;吞吐量从100条/第二至约10邮件/第二,在最多。

任何建议?

更新:

挑战通过多个答案质疑的可能性的说明。我构造的"单元"的试验的行为我描述的。检查单位的情况下在 主旨273786.

这两个单元的测试有两个线程、服务器和客户。服务器关闭,而该客户发送数据没有IOException扔无论如何。这里是主要的方法:

public static void main(String[] args) throws Throwable {
    final int PORT = 8005;
    final int FIRST_BUF_SIZE = 5;

    final Throwable[] errors = new Throwable[1];
    final Semaphore serverClosing = new Semaphore(0);
    final Semaphore messageFlushed = new Semaphore(0);

    class ServerThread extends Thread {
        public void run() {
            try {
                ServerSocket ssocket = new ServerSocket(PORT);
                Socket socket = ssocket.accept();
                InputStream s = socket.getInputStream();
                s.read(new byte[FIRST_BUF_SIZE]);

                messageFlushed.acquire();

                socket.close();
                ssocket.close();
                System.out.println("Closed socket");

                serverClosing.release();
            } catch (Throwable e) {
                errors[0] = e;
            }
        }
    }

    class ClientThread extends Thread {
        public void run() {
            try {
                Socket socket = new Socket("localhost", PORT);
                OutputStream st = socket.getOutputStream();
                st.write(new byte[FIRST_BUF_SIZE]);
                st.flush();

                messageFlushed.release();
                serverClosing.acquire(1);

                System.out.println("writing new packets");

                // sending more packets while server already
                // closed connection
                st.write(32);
                st.flush();
                st.close();

                System.out.println("Sent");
            } catch (Throwable e) {
                errors[0] = e;
            }
        }
    }

    Thread thread1 = new ServerThread();
    Thread thread2 = new ClientThread();

    thread1.start();
    thread2.start();

    thread1.join();
    thread2.join();

    if (errors[0] != null)
        throw errors[0];
    System.out.println("Run without any errors");
}

[顺便说一下,我还有一个并发的测试图书馆,这使得建立一个更好和更清楚。结账的样本要点以及].

当我得到以下产出:

Closed socket
writing new packets
Finished writing
Run without any errors
有帮助吗?

解决方案

这没有多大帮助你,但从技术上讲你提出的解决方案是不正确的。使用的输出流。flush()和任何其他API电话,你能想到的都不会做,你需要什么。

只有便携式和可靠的方法来确定如果分组已经收到的对等等待确认,从对等。这的确认可以是一个实际的回应,或一个优美的插座停机。故事结束-没有真的没有其他办法,而这不Java特定-这是基本网络中的节目。

如果这不是一个持续的连接,也就是说,如果你只是送些东西然后关闭连接-你的方式做这是你钓到的所有IOExceptions(他们的任何指示错误)和执行一个优美的插座停机:

1. socket.shutdownOutput();
2. wait for inputStream.read() to return -1, indicating the peer has also shutdown its socket

其他提示

之后多的麻烦,落连接,我把我的代码 采用增强的格式, ,其中很多意味着你改变你的包到这样的:

enter image description here

这种方式苹果将不会下降一个连接,如果发生错误,但是将编写一个反馈码的座。

如果你发送的信息的使用TCP/IP协议的苹果你必须接受确认。但是你说:

苹果不能返回任何 确认任何

你什么意思?TCP/IP保证输送,因此接收器必须承认收据。它并不能保证时的交付将发生的,但是。

如果你发送的通知到苹果你打破你的连接之前接收的ACK有没有办法告诉你是否成功的或不那么你就必须重新发送。如果推动同一信息的两倍是一个问题,或处理不当的设备,然后有一个问题。该方案是修复的设备处理的重复推动通知:没有什么你可以在推动边。

@澄清意见/问题

"确定"。第一部分,你明白的是你的回答第二部分。唯一的分组已收到确认已经发送和接收正常。我敢肯定,我们可以想到一些非常复杂的方案,跟踪每个分组自己,但TCP是想抽象的这一层走并处理它对您。在你结束你只需要处理的众多的失败是可能发生(在Java如果任何这些发生异常升起).如果没有异常的数据,你只是试图发送保证TCP/IP协议。

有一个情况下,数据似乎是"发送"的,但不能保证收到,那里没有异常升起?答案应是否定的。

@实例

好的例子,这种澄清的事情很多。我会想一错误就会被抛出。在例如发布了一个错误是扔在第二编写的,但不是第一次。这是有趣的行为...我是不是能找到很多信息说明为什么它的行为就像这个。但是它解释为什么我们必须制定我们自己的应用程序级别协议来核实交付。

看来你是正确的,没有一个协议对于确认他们是没有保证的苹果设备将收到的通知。苹果也只队列是最后的消息。看一点点在服务,我能够确定这种服务更为便利于客户,但不能用于担保服务和必须结合其他的方法。我读这从以下来源。

http://blog.boxedice.com/2009/07/10/how-to-build-an-apple-push-notification-provider-server-tutorial/

似乎答案是没有是否可以告诉肯定的。你可能能够使用一个分组的嗅探器等查看来告诉我们,如果它已发送,但这仍然不能保证它是接收和发送到设备由于性质的服务。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top