每当我在标题中的任何编写者(包装OutputStreamWriter)上调用.flush()
时,都不会发送刷新的数据;但是,当在编写器上调用.close()
时,它会刷新并且服务器可以读取数据。我不知道我是否错误地调用.write()
或.readLine()
,或者,如果由于读取操作已被阻止,那么问题是什么?我需要找到一种方法来刷新数据而不关闭套接字(我将在另一个程序中使用它)。在我所拥有的两个SSCCE中,有System.out.println()
个用于调试。在客户端,它将进入"检查4"什么都不循环(它在实际程序中执行更多的读写操作,在示例中只能将它关闭)。在服务器中,它进入"检查2"并在reader.readLine()
处阻止。我已经阅读了SO,但我所提出的是readLine()
对于网络程序来说并不是一个好主意,我应该实现自己的协议;但是没有一个帖子指向一个好的教程网站,或其他任何有良好的网络编码教程。以下是SSCCE:
客户SSCCE
package testClient;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.Socket;
import java.net.UnknownHostException;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.KeySpec;
import java.util.Random;
import javax.crypto.Cipher;
import javax.crypto.CipherOutputStream;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.SecretKeySpec;
public class Client {
public static void main(String[] args) {
try {
Socket s = new Socket("127.0.0.1",48878);
System.out.println("check 1");
PrintWriter pw = new PrintWriter(new OutputStreamWriter(s.getOutputStream(),"UTF-8"));
System.out.println("check 2");
pw.write("Hello StackOverFlow.");
System.out.println("check 3");
pw.flush();
System.out.println("check 4");
while(true){}
} catch (IOException e) {
e.printStackTrace();
}
}
}
服务器SSCCE
package testServer;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;
public class Server {
public static void main(String[] args) {
try {
ServerSocket ss = new ServerSocket(48878);
Socket client = ss.accept();
System.out.println("check 1");
BufferedReader reader = new BufferedReader(new InputStreamReader(client.getInputStream(),"UTF-8"));
System.out.println("check 2");
byte[] buffer = new byte[20];
int i = 0;;
int x;
while((x=reader.read())!=-1) {
buffer[i] += (byte)x;
i = i++;
}
String text = new String(buffer,"UTF-8");
System.out.println("check 3");
System.out.println(text);
client.close();
ss.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
答案 0 :(得分:2)
尝试PrintWriter的自动刷新属性,一旦新行方法被调用,就会刷新数据。在流中写入任何数据后无需调用flush。
与
PrintStream
类不同,如果启用了自动刷新,则仅在调用println
,printf
或format
方法之一时才会执行,而不是每当输出换行符时。
示例代码:
客户端:
PrintWriter pw = new PrintWriter(new OutputStreamWriter(s.getOutputStream(),"UTF-8"),true);
pw.println("Hello StackOverFlow.");
服务器:
BufferedReader reader = new BufferedReader(new InputStreamReader(client.getInputStream(),"UTF-8"));
System.out.println(reader.readLine());
答案 1 :(得分:2)
“bug”位于用于读取数据的循环中。仅当您关闭另一侧的流时才会发送EOF。所以循环似乎挂了,尽管事实上已经可能已经向数组添加了N个字节。
您需要做的是向服务器发送有关客户端将要发送的数据长度的提示。这可以是字节数/字符数或终止字符(换行符)。
在发件人中,发送数据+提示,然后刷新。
在接收器中,读取尽可能多的数据,而不是单个字节。这样,接收器就不会阻塞。
在您的情况下,只要您对发件人使用reader.readLine()
+ flush,println()
就可以正常工作。