简体   繁体   English

服务器刷新数据之前,套接字如何从服务器接收数据?

[英]How can data be received by a socket from a server before server flushes the data?

So here is the code I have: 所以这是我的代码:

public class TestClass {
    public static void main(String[] args) throws IOException, InterruptedException {
        Thread server = new Thread(new MyServer());
        server.start();
        Thread.sleep(750);
        Thread client = new Thread(new MyClient());
        client.start();
    }
}

The Server: 服务器:

public class MyServer implements Runnable{

    public static synchronized void go() throws IOException {

        System.out.println("MyServer: Go called...");
        ServerSocket serverSocket = new ServerSocket(5000);
        while(true){
            Socket socket = serverSocket.accept();
            System.out.println(time() + "MyServer: Connection accepted!");
            OutputStream outputStream = socket.getOutputStream();
            System.out.println(time() + "MyServer: socket.getOutputStream");
            PrintWriter printWriter = new PrintWriter(outputStream);
            System.out.println(time() + "MyServer: New PrintWriter object created!");
            printWriter.write("Hello from my socket!");
            System.out.println(time() + "MyServer: printwriter.write method called..");
            printWriter.flush();
            System.out.println(time() + "MyServer: Flushed!");
            printWriter.close();
            System.out.println(time() + "MyServer: printWriter closed...");
        }
    }

    public static String time(){
        return String.valueOf(MyCounterClass.getCounter()) + " ";
    }

    @Override
    public void run() {
        try {
            go();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

The Client: 客户端:

public class MyClient implements Runnable {

    public static synchronized void go() throws IOException {
        Socket socket = new Socket("localhost",5000);
        System.out.println(time() + "My Client: Connection established...");
        InputStream inputStream = socket.getInputStream();
        System.out.println(time() + "MyClient: socket.getInputStream...");
        BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
        System.out.println(time() + "MyClient: BufferedReader object created...");
        System.out.println(time() + "Bufferedreader readline being called and directly printer: " + bufferedReader.readLine());
        System.out.println(time() + "bufferedReader.readline has just been called...");
    }

    public static String time(){
        return String.valueOf(MyCounterClass.getCounter()) + " ";
    }

    @Override
    public void run() {
        try {
            go();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

} }

And the Counter class: 和Counter类:

public class MyCounterClass {
    private static volatile int counter = 0;
    synchronized public static int getCounter(){
        return counter++;
    }
}

And the output will be: 输出将是:

0 My Client: Connection established...
1 MyServer: Connection accepted!
2 MyClient: socket.getInputStream...
3 MyClient: BufferedReader object created...
4 MyServer: socket.getOutputStream
6 MyServer: New PrintWriter object created!
7 MyServer: printwriter.write method called..
8 MyServer: Flushed!
9 MyServer: printWriter closed...
5 Bufferedreader readline being called and directly printer: Hello from my socket!
10 bufferedReader.readline has just been called...

When ordered: 订购时:

0 My Client: Connection established...
1 MyServer: Connection accepted!
2 MyClient: socket.getInputStream...
3 MyClient: BufferedReader object created...
4 MyServer: socket.getOutputStream
5 Bufferedreader readline being called and directly printer: Hello from my socket!
6 MyServer: New PrintWriter object created!
7 MyServer: printwriter.write method called..
8 MyServer: Flushed!
9 MyServer: printWriter closed...
10 bufferedReader.readline has just been called...

So what is weird to me is line 5 is before 6,7,8... How is this possible? 所以对我来说很奇怪的是,第5行在6,7,8之前...这怎么可能?

There are a number of things happening here 这里发生了很多事情

System.out.println(time() + "Bufferedreader readline being called and directly printer: " + bufferedReader.readLine());

First time() is invoked to get a value. 首次调用time()以获取值。 Say it returns 5. That value is stored on the stack. 说它返回5。该值存储在堆栈中。 Then readLine() is invoked and blocks until it receives something. 然后调用readLine()并阻塞直到它接收到一些东西。 Once it does, it concatenates the 5 from the stack, the String "Bufferedreader read... " and the String returned from readLine . 完成后,它将连接堆栈中的5String "Bufferedreader read... ”和从readLine返回的String

So even though the flush() (and writing to the stream) comes later, the value from time() has already been retrieved. 因此,即使flush() (和写入流)稍后出现, time()的值也已被检索到。

You'd need to synchronized around the whole String concatenation operation. 您需要围绕整个String串联操作进行同步。

flush will programatically empty and send the remaining buffer conttent but that does not mean that other automatic flushes won't be performed when the buffers fill completely during transmission over the socket. flush将以编程方式清空,并发送剩余的缓冲区内容,但这并不意味着在通过套接字传输期间缓冲区完全充满时,将不会执行其他自动刷新。

That is, flush must be used to make sure the last remains of data in the buffer are sent when you have finished your transmission. 也就是说,必须使用flush来确保在完成传输后发送缓冲区中的最后数据。 However, many iterations of fill-send-flush may have been happened in the mean time. 但是,在此期间可能发生了很多次fill-send-flush的迭代。

在此处输入图片说明

In this diagram, the explicit flush that you perform within go method is the one responsible for sending the red colored bytes. 在此图中,您在go方法内执行的显式flush是负责发送红色字节的副本。

It may happen that your buffer is never filled before the call to flush and, in that case the client won't be sent the bytes until that call has finished : 可能会发生以下情况,即在调用flush之前永远不会填充缓冲区,在这种情况下,直到该调用完成,客户端才会收到字节:

在此处输入图片说明

EDIT Although the exposed in this answer is right, it is not full explanation for the problem you are experiencing, Sotirios's answer adds more insight on other problems with your code. 编辑尽管此答案中公开的内容是正确的,但这并不是对您遇到的问题的完整解释,Sotirios的答案为您的代码中的其他问题提供了更多见解。 Do not forget anyway that flush at the end of go does not imply the complete chunk is sent at that moment, m * sizeof(buffer) may have already been sent before that. 无论如何,请不要忘记go结束时的flush并不意味着在那一刻发送了完整的块,在此之前可能已经发送了m * sizeof(buffer)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 在从服务器接收数据时,在关闭套接字后显示/接收数据。 服务器发送后如何立即接收。 - On receiving a data from the server it is displayed/received after closing the socket. How to receive it immediately once the server sends.? 如何使用套接字从节点服务器检索数据? - How to Retrieve Data from Node Server With Socket? 如何在片段中共享从套接字接收到的数据? - How to share received data from socket in fragments? 如何使客户端套接字等待来自服务器套接字的数据 - how to make client socket wait for data from server socket 套接字编程在服务器之间传输数据 - socket programming transfer data from server to server 通过 TCP 套接字服务器解析 java 中的二进制数据 - Parsing binary data in java received over TCP socket server 如果使用 Java 接收数据,如何制作一个从服务器接收数据并将数据发送到服务器的程序 - How to make a program that receives data from the server and sends data to the server if data is received with Java 如何基于从服务器接收的数据在android中渲染视图? - how to render view in android based on the data received from server? 处理从套接字接收的数据 - Processing received data from socket 无法将数据从Java Socket Server发送到NodeJS客户端 - Can't send data from Java Socket Server to NodeJS client
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM