【Socket编程】为什么这段程序会产生阻塞?

supNate 2009-04-21 06:38:55
小弟需要做个客户端-服务器原型,但在实验时遇到下面问题:
用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();
}


...全文
76 4 打赏 收藏 转发到动态 举报
写回复
用AI写文章
4 条回复
切换为时间正序
请发表友善的回复…
发表回复
supNate 2009-04-22
  • 打赏
  • 举报
回复
关键是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());
}
}

jinxfei 2009-04-21
  • 打赏
  • 举报
回复
通常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通信模型是编程里很基本的,你最好能自己研究清楚。
zoutuo 2009-04-21
  • 打赏
  • 举报
回复
加入线程可以解决这个问题。单线程情况下,客户端和服务端的通讯是排队进行的。如果客户端不与服务器端的连接断开,那么第二个人就无法和服务器进行交互。
不善^ 2009-04-21
  • 打赏
  • 举报
回复
楼下回答














----------------------------------華麗的個性簽名----------------------------------------
500人的编程群期待大家的加入,一起交流探讨软件开发
群名:程序人生大联盟主群
群号:49282233

67,514

社区成员

发帖
与我相关
我的任务
社区描述
J2EE只是Java企业应用。我们需要一个跨J2SE/WEB/EJB的微容器,保护我们的业务核心组件(中间件),以延续它的生命力,而不是依赖J2SE/J2EE版本。
社区管理员
  • Java EE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧