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

Java 在服务器刷新数据之前,套接字如何从服务器接收数据?,java,multithreading,sockets,synchronization,Java,Multithreading,Sockets,Synchronization,下面是我的代码: 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

下面是我的代码:

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();
    }
}
服务器:

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();
        }
    }
}
客户:

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();
        }
    }
}

柜台类:

public class MyCounterClass {
    private static volatile int counter = 0;
    synchronized public static int getCounter(){
        return counter++;
    }
}
输出将是:

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...
订购时:

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...

所以我觉得奇怪的是第5行在6,7,8之前。。。这怎么可能

flush
将以编程方式清空并发送剩余的缓冲区内容,但这并不意味着在通过套接字传输期间缓冲区完全填满时,不会执行其他自动刷新

也就是说,必须使用
flush
,以确保在完成传输后发送缓冲区中最后剩余的数据。然而,在这段时间内,可能已经发生了许多次fill-send-flush迭代

在此图中,在
go
方法中执行的显式
flush
是负责发送红色字节的方法

在调用
flush
之前,缓冲区可能从未被填满,在这种情况下,在该调用完成之前,不会向客户端发送字节:


编辑尽管此答案中的答案是正确的,但它并不能完全解释您遇到的问题,Sotirios的答案为您的代码的其他问题提供了更多的见解。无论如何,不要忘记,
go
末尾的flush并不意味着此时发送完整的块,
m*sizeof(buffer)
在此之前可能已经发送。

刷新将以编程方式清空并发送剩余的缓冲区内容,但这并不意味着在通过插槽传输期间缓冲区完全填满时,不会执行其他自动刷新

也就是说,必须使用
flush
,以确保在完成传输后发送缓冲区中最后剩余的数据。然而,在这段时间内,可能已经发生了许多次fill-send-flush迭代

在此图中,在
go
方法中执行的显式
flush
是负责发送红色字节的方法

在调用
flush
之前,缓冲区可能从未被填满,在这种情况下,在该调用完成之前,不会向客户端发送字节:


编辑尽管此答案中的答案是正确的,但它并不能完全解释您遇到的问题,Sotirios的答案为您的代码的其他问题提供了更多的见解。无论如何,不要忘记,
go
末尾的flush并不意味着此时发送了完整的块,
m*sizeof(buffer)
在此之前可能已经发送了。

这里发生了很多事情

System.out.println(time() + "Bufferedreader readline being called and directly printer: " + bufferedReader.readLine());
首先调用
time()
,以获取一个值。假设它返回5。该值存储在堆栈上。然后调用
readLine()
,并阻塞它,直到它接收到某个内容。一旦这样做,它就将堆栈中的
5
字符串
“Bufferedreader read…”
“和从
读线
返回的
字符串
连接起来

因此,即使
flush()
(并写入流)来得晚,也已经从
time()
中检索到了值


您需要围绕整个
字符串
串联操作进行同步。

这里发生了许多事情

System.out.println(time() + "Bufferedreader readline being called and directly printer: " + bufferedReader.readLine());
首先调用
time()
,以获取一个值。假设它返回5。该值存储在堆栈上。然后调用
readLine()
,并阻塞它,直到它接收到某个内容。一旦这样做,它就将堆栈中的
5
字符串
“Bufferedreader read…”
“和从
读线
返回的
字符串
连接起来

因此,即使
flush()
(并写入流)来得晚,也已经从
time()
中检索到了值


您需要围绕整个
字符串
串联操作进行同步。

“Flush”意味着数据已被确保传输,或者方法将等待传输完成。它可以更快地传输。@alk的可能副本它不是副本。“Flush”表示数据已被确保传输,或者该方法将等待数据被传输。它可以更快地传输。@alk的可能副本它不是一个副本。我不认为这与这个问题有什么关系。5在6,7,8之前是如何发生的?您的答案如何解释?@SotiriosDelimanolis“在服务器刷新数据之前,套接字如何从服务器接收数据”,尽管我的答案并没有针对所有情况,但它解决了为什么5可以在8之前发生。要发生8,6和7必须发生。在服务器创建发送数据的对象之前,客户端不能接收数据。这里的问题是日志记录有误导性。@SotiriosDelimanolis你这次是。不过,我会保留答案,因为缺少对
flush
的调用并不意味着某些数据尚未发送。我不认为这与问题有什么关系。5在6,7,8之前是如何发生的?您的答案如何解释?@SotiriosDelimanolis“在服务器刷新数据之前,套接字如何从服务器接收数据”,尽管我的答案并没有针对所有情况,但它解决了为什么5可以在8之前发生。要发生8,6和7必须发生。在服务器创建发送数据的对象之前,客户端不能接收数据。这里的问题是日志记录有误导性。@SotiriosDelimanolis你这次是。不过,我会保留答案,因为缺少对
flush
的调用并不意味着某些数据尚未发送。当我将其更改为…readLine()+时间时,一切都很酷,因此非常感谢。当我将其更改为…readLine()+时间时,一切都很酷,谢谢