小弟需要做个客户端-服务器原型,但在实验时遇到下面问题:
用BufferedReader读取流时会一直阻塞,如果服务器或者客户端仅一边读取响应时则不会阻塞。
代码片段如下,求大虾指教,不胜感激!服务器端主要代码:
socket = ss.accept();
log("client connected: " + socket.getInetAddress().toString());
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
out = new PrintWriter(socket.getOutputStream(), true);
String inMsg = readAll(in);
log("you input is :" + inMsg);
//todo:process inMsg
out.print("success");
if(inMsg.startsWith("stop"))break;
out.close();
in.close();
socket.close();客户端主要代码:
socket = new Socket(ip, port);
out = new PrintWriter(socket.getOutputStream(),true);
out.println(msg);
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
log(readAll(in));
out.close();
in.close();
socket.close();
readAll函数:
protected String readAll(BufferedReader reader) throws Exception{
StringBuffer sb = new StringBuffer();
String line = null;
while( (line = reader.readLine())!=null){
sb.append(line + "\n");
System.out.println(line);
}
return sb.toString();
}

解决方案 »

  1.   

    通常ServerSocket在Accept到新的连接后,会建立一个新线程来专门处理这个连接信道上的通信,
    也就是说,你在服务器端需要写一个类似下边的类:class Reader extends Thread{
      private Socket socket;
      public Reader(Socket sock){
        this.socket=sock;
      }
      public void run(){
         in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
    out = new PrintWriter(socket.getOutputStream(), true);        
    String inMsg = readAll(in);            
    log("you input is :" + inMsg);
    //todo:process inMsg
    out.print("success");
    if(inMsg.startsWith("stop"))break;
    out.close();
    in.close();
    socket.close();
      }
    }
    服务器主程序:
    socket = ss.accept();
    Thread t=new Reader(socket);
    t.start();
    以上只是原理建议,不作为最终代码,Socket通信模型是编程里很基本的,你最好能自己研究清楚。
      

  2.   

    关键是reader.readLine()会互相等待所以产生阻塞,并不是线程的问题。写了2个方法用于socket读写文本解决此问题,原理是加一行表示此次写入的行数,从而另一段可以读取相应的行数就返回,不用一直等待。结贴,多谢关注!
    package com.ibm.sbe.sms;import java.io.BufferedReader;
    import java.io.InputStreamReader;
    import java.io.PrintWriter;
    import java.net.Socket;
    import java.text.SimpleDateFormat;
    import java.util.Date;public class SMSBase {
    protected String read(Socket socket) throws Exception {
    BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
    StringBuffer sb = new StringBuffer();
    int lines = Integer.valueOf(reader.readLine());
    for (int i = 0; i < lines; i++) {
    sb.append(reader.readLine() + "\n");
    }
    return sb.toString();
    } protected void send(Socket socket, String msg) throws Exception {
    if(!msg.endsWith("\n"))msg += "\n";

    String msg2 = msg.replaceAll("\n", "wp");
    int len = msg2.length() - msg.length();
    PrintWriter writer = new PrintWriter(socket.getOutputStream(), true);
    writer.println(len);
    writer.println(msg); }

    protected static void log(String msg) {
    System.out.println(getTimeStamp() + " " + msg);
    } protected static String getTimeStamp() {
    SimpleDateFormat f = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    return f.format(new Date());
    }
    }