是否有可能服务器知道TCP流已经“完成”而不管协议如何?

时间:2011-11-20 22:38:34

标签: http sockets tcp

服务器是否有可能知道客户端已完成发送数据并且现在已准备好响应 - 无论(并且不知道)应用程序协议?

编辑: 考虑创建代理服务器。你不能影响协议,你不知道每个协议的应用细节(所以你不知道什么时候流“结束”)。关于“客户端可能关闭输入流” - 这是真的,但显然客户端实际上并没有关闭流(与重用有关吗?)。这是通过Web浏览器进行的经验测试。

我可能会在错误的树上咆哮 - 对于那个代理服务器场景,不会将流复制到“另一端”的输出流就足够了吗?但是,另一端如何“知道”流已经结束了?

参见此计划:

public class Test {
public static void main(String[] args) throws IOException {
    ServerSocket serverSocket = new ServerSocket(8081, 100, InetAddress.getByName("localhost"));
    final Socket socket1 = new Socket("www.google.com", 80);
    final Socket socket = serverSocket.accept();
    new Thread(new Runnable() {
        public void run() {
            try {
                final InputStream inputStream = socket1.getInputStream();
                final OutputStream outputStream = socket.getOutputStream();
                readwrite(inputStream, outputStream, false);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    });
    final InputStream inputStream = socket.getInputStream();
    final OutputStream outputStream1 = socket1.getOutputStream();
    readwrite(inputStream, outputStream1, true);

}

private static void readwrite(InputStream inputStream, OutputStream outputStream1, boolean x) throws IOException {
    final byte[] bytes = new byte[4];
    int read = -1;
    while ((read = inputStream.read(bytes)) != -1) {
        System.out.println((x?"s ":"r ") + new String(bytes));
        outputStream1.write(bytes, 0, read);
    }
}
}

而不是做你认为它会做的事情(代理www.google.com)它只是挂起。应该从谷歌读取并写入本地套接字的线程不会检测到该输入流上的任何内容。

EDIT2: DOH! 把我放在愚蠢的角落里。忘了“开始”线程。 回到我原来的问题 - 我怎么知道流已经结束了?

EDIT3: 好吧,我的问题是完全不同的(与POST,Transfer-Encoding和HttpClient-annoying-internal-cache-that-not-off-off)有关。 为了公平起见,我会接受最能回答原始问题的答案。

3 个答案:

答案 0 :(得分:1)

如果'finished'表示TCP的入站或出站流已关闭(所谓的半关闭连接),那么就有可能。如果inputStream.read(bytes)返回-1,则关闭入站流。

如果'完成'意味着别的东西,那么答案就是否定。

如果要实现通用代理,则应同时等待来自两个套接字的数据。并将任何传入的数据写入其他套接字。 如果另一个套接字不可写,你也应该停止读取套接字。否则你必须缓冲数据。代理还应处理半封闭连接。

当交付的协议具有消息边界时,请勿尝试检测,因为某些协议可能始终将数据流向两个方向。

答案 1 :(得分:0)

否 - 但您可以使用非阻塞读取超时,这将告诉您不再有数据进入。这可以解决问题。

答案 2 :(得分:0)

客户端的TCP会话将同时具有入站和出站流。客户端可以在发送请求后关闭其出站流,使其入站流保持打开状态以接收响应。服务器将检测到这种情况,同时仍然能够回复。