你的bug越离奇,你的错误越低级!
服务端:
package dusk.echo.simple;
import java.io.*;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
* Created by dushangkui on 2017/6/2.
*/
public class Server {
public static void main(String[] args) throws IOException {
ExecutorService executor = Executors.newFixedThreadPool(5);
ServerSocket serverSocket = new ServerSocket();
serverSocket.bind(new InetSocketAddress(9000));
while(true){
Socket socket = serverSocket.accept();
executor.submit(new Processor(socket));
}
}
}
处理器:
package dusk.echo.simple;
import java.io.*;
import java.net.Socket;
/**
* Created by dushangkui on 2017/6/2.
*/
public class Processor implements Runnable{
private Socket socket =null;
public Processor(Socket socket) {
this.socket = socket;
}
@Override
public void run() {
BufferedReader br=null;
PrintWriter writer=null;
System.out.println("get a connection");
try {
br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
writer = new PrintWriter(new OutputStreamWriter(socket.getOutputStream()));
while(true){
String msg=br.readLine();
if("bye".equals(msg)) break;
System.out.println("server recived: " + msg);
writer.println(msg);
writer.flush();
}
} catch (Exception e) {
e.printStackTrace();
}finally{
if(br!=null) {
try {
br.close();
} catch (IOException e) {
}
}
if(writer!=null) {
try {
writer.close();
} catch (Exception e) {
}
}
try {
socket.close();
} catch (IOException e) {
}
}
}
}
客户端:
package dusk.echo.simple;
import java.io.*;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.util.Scanner;
/**
* Created by dushangkui on 2017/6/2.
*/
public class Client {
public static void main(String[] args){
BufferedReader br=null;
PrintWriter writer=null;
Socket socket = new Socket();
try {
socket.connect(new InetSocketAddress("localhost", 9000));
br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
writer = new PrintWriter (new OutputStreamWriter(socket.getOutputStream()));
Scanner scanner = new Scanner(System.in);
while(true){
String msg =scanner.next();
writer.println(msg);
writer.flush();
if (msg.equals("bye")) {
break;
}
System.out.println("Recieved Server msg: " + br.readLine());
}
}catch(Exception e){
e.printStackTrace();
if(br!=null) {
try {
br.close();
} catch (IOException e1) {
}
}
if(writer!=null) {
try {
writer.close();
} catch (Exception e1) {
}
}
try {
socket.close();
} catch (IOException e1) {
}
}
}
}
但是如果我客户端使用BufferedWriter去写数据的时候发现服务器端读取不到,仔细想了想,原来是我用BufferedWriter写的时候没有在消息的结尾插入换行符,导致服务器端明明有数据到达确读不完整一行,因此阻塞。
看写法:
BufferedReader br=null;
BufferedWriter writer=null;
Socket socket = new Socket();
try {
socket.connect(new InetSocketAddress("localhost", 9000));
br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
writer = new BufferedWriter (new PrintWriter(socket.getOutputStream()));
Scanner scanner = new Scanner(System.in);
while(true){
String msg =scanner.next();
writer.write(msg+"\n");
writer.flush();
if (msg.equals("bye")) {
break;
}
System.out.println("Recieved Server msg: " + br.readLine());
}
}catch(Exception e){
看来BufferedReader和BufferedWriter是很方便但是不注意也会惹麻烦,正如行内的话:你的bug越离奇,你的错误越低级。
我们看BufferedReader的readLine源码
String readLine(boolean ignoreLF) throws IOException {
StringBuffer s = null;
int startChar;
synchronized (lock) {
ensureOpen();
boolean omitLF = ignoreLF || skipLF;
bufferLoop:
for (;;) {
if (nextChar >= nChars)
fill();
if (nextChar >= nChars) { /* EOF */
if (s != null && s.length() > 0)
return s.toString();
else
return null;
}
boolean eol = false;
char c = 0;
int i;
/* Skip a leftover '\n', if necessary */
if (omitLF && (cb[nextChar] == '\n'))
nextChar++;
skipLF = false;
omitLF = false;
charLoop:
for (i = nextChar; i < nChars; i++) {
c = cb[i];
if ((c == '\n') || (c == '\r')) {
eol = true;
break charLoop;
}
}
startChar = nextChar;
nextChar = i;
if (eol) {
String str;
if (s == null) {
str = new String(cb, startChar, i - startChar);
} else {
s.append(cb, startChar, i - startChar);
str = s.toString();
}
nextChar++;
if (c == '\r') {
skipLF = true;
}
return str;
}
if (s == null)
s = new StringBuffer(defaultExpectedLineLength);
s.append(cb, startChar, i - startChar);
}
}
}
可以看到我们到流的结尾或者遇见\r或\n才会返回一行