[英]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
. 完成后,它将连接堆栈中的
5
, String
"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.