今天在学习socket通信的时候,写了一个简单的Demo,运行的时候出现了一个问题,客户端在写入数据并调用flush方法后,服务器端并没有接收到数据。
客户端主要代码如下:
Socket socket = new Socket(ipAddress, 2017);
BufferedReader inReader = new BufferedReader(new InputStreamReader(
socket.getInputStream()));
PrintWriter writer = new PrintWriter(socket.getOutputStream());
BufferedReader systemReader = new BufferedReader(
new InputStreamReader(System.in));
String inputText = systemReader.readLine();
while (!inputText.equals("over")) {
mCommonPrint.print("Client:" + inputText);
writer.print(inputText);
writer.flush();
mCommonPrint.print("Server:" + inReader.readLine());
inputText = systemReader.readLine();
}
writer.close();
systemReader.close();
inReader.close();
socket.close();
服务器端主要代码如下:
BufferedReader inReader = new BufferedReader(new InputStreamReader(
socket.getInputStream()));
mCommonPrint.print("Clinet:" + inReader.readLine());
PrintWriter writer = new PrintWriter(socket.getOutputStream());
BufferedReader systemReader = new BufferedReader(
new InputStreamReader(System.in));
String inputText = systemReader.readLine();
while (!inputText.equals("over")) {
writer.print(inputText);
writer.flush();
mCommonPrint.print("Server:" + inputText);
mCommonPrint.print("Clinet:" + inReader.readLine());
inputText = systemReader.readLine();
}
systemReader.close();
writer.close();
inReader.close();
socket.close();
serverSocket.close();
在网上查的资料都说是没有调用PrintWriter的flush()方法,但是我明明调用了。。。。
我试了一下如果直接在writer.print()后调用writer.close()方法,那么服务器端是可以获取到数据的。。。
但是依然木有解决问题。。。
最后仔细的看了看别人写的代码,发现问题了。。。
其他网友调用的是writer.println()方法,而我调用的是writer.print()方法,于是我换成了writer.println()方法,结果问题解决了!
但是为什么呢?
于是看了一下源码。。。
print()方法源码:
public void print(String s) {
if (s == null) {
s = “null”;
}
write(s);
}
println()方法源码:
public void println(String x) {
synchronized (lock) {
print(x);
println();
}
}
其中的println()调用了newLine():
private void newLine() {
try {
synchronized (lock) {
ensureOpen();
out.write(lineSeparator);
if (autoFlush)
out.flush();
}
}
catch (InterruptedIOException x) {
Thread.currentThread().interrupt();
}
catch (IOException x) {
trouble = true;
}
}
从源码中可以看出,print()方法和write()方法没有太大的区别,println()方法中多了一个out.write(lineSeparator);添加了一个分隔符,并且可以设置自动flush,因为默认的autoFlush=false,可以在创建PrintWriter时设置为true。
PrintWriter writer = new PrintWriter(socket.getOutputStream(),true);
由此看来,是这个分隔符的原因。。。
然后发现了这句代码:
inReader.readLine()
readLine()是一行一行读取数据,而标识一行的方式就是使用分隔符。
官方说明:
Reads a line of text. A line is considered to be terminated by any one of a line feed (‘\n’), a carriage return (‘\r’), or a carriage return followed immediately by a linefeed
也就是说是如果没有遇到换行或者回车的分隔符,就会一直读取数据。
但是print()和write()方法中并没有添加分隔符,所以就出现了刚才的问题。
解决办法:
1.将writer.println(inputText);改为writer.println(inputText+“\n”);手动添加分隔符。
2.使用println()方法。
但是不管使用哪种方法都要调用flush()方法。