检测套接字是否被丢弃的最合适方法是什么?或者是否确实发送了数据包?
我有一个库,可以通过Apple gatways(可在GitHub上获得)向Apple发送Apple推送通知.客户端需要打开套接字并发送每条消息的二进制表示; 但不幸的是,Apple没有回复任何确认.连接可以重复使用以发送多条消息.我正在使用简单的Java Socket连接.相关代码是:
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);
Run Code Online (Sandbox Code Playgroud)
在某些情况下,如果在发送消息时或之前删除了连接; Socket.getOutputStream().write()虽然成功完成了.我预计这是由于TCP窗口尚未用完.
有没有办法可以确定数据包是否实际进入网络?我尝试了以下两种解决方案:
插入socket.getInputStream().read()250ms超时的附加操作.这会强制在删除连接时失败的读取操作,否则会挂起250ms.
将TCP发送缓冲区大小(例如Socket.setSendBufferSize())设置为消息二进制大小.
这两种方法都有效,但它们会严重降低服务质量; 吞吐量最多从100条消息/秒到大约10条消息/秒.
有什么建议?
更新:
受到多个答案的质疑,质疑所描述的可能性.我构建了我所描述的行为的"单元"测试.查看Gist 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 = …Run Code Online (Sandbox Code Playgroud)