使用dataInputStream和dataOutputStream造成“死锁”或“阻塞”

zylwszylws 2010-04-08 02:19:15
如题,请各位大侠帮我看看,如何解决

//客户端
public class ClientTest_Short {
private ClientSocket_Short cs = null;

private String ip = "localhost";// 设置成服务器IP

private int port = 8821;

private String sendMessage = "sss";

private Socket socket = null;

public ClientTest_Short() {
try {
if (createConnection()) {
sendMessage();
// getMessage();
}

} catch (Exception ex) {
ex.printStackTrace();
}
}

private boolean createConnection() {
cs = new ClientSocket_Short(ip, port);
try {
socket = cs.CreateConnection();
if(socket != null)
{
System.out.print("连接服务器成功!" + "\n");
}
else
{
System.out.println("socket is null");
}
return true;
} catch (Exception e) {
System.out.print("连接服务器失败!" + "\n");
return false;
}

}

private void sendMessage() throws IOException {
String filePath = "D:\\OOo_3.2.0rc5_20100203_Win32Intel_install_wJRE_zh-CN.exe";
File fi = new File(filePath);

System.out.println("文件长度:" + (int) fi.length());
System.out.println("建立socket链接");

DataInputStream fis = new DataInputStream(new BufferedInputStream(new FileInputStream(filePath)));
DataOutputStream ps = new DataOutputStream(socket.getOutputStream());
//将文件名及长度传给客户端。这里要真正适用所有平台,例如中文名的处理,还需要加工,具体可以参见Think In Java 4th里有现成的代码。
ps.writeUTF(fi.getName());
ps.flush();
ps.writeLong((long) fi.length());
ps.flush();

int bufferSize = 8192;
byte[] buf = new byte[bufferSize];

while (true) {
int read = 0;
if (fis != null) {
read = fis.read(buf);
}

if (read == -1) {
break;
}
ps.write(buf, 0, read);
}
ps.flush();
fis.close();

//接收服务器端成功返回信息
DataInputStream inputStream = new DataInputStream(new BufferedInputStream(socket.getInputStream()));
//在这里发生死锁或者阻塞
System.out.println("从服务器返回的信息 = " + inputStream.readUTF());

socket.close();
System.out.println("文件传输完成");
}


public static void main(String arg[]) {
new ClientTest_Short();
}
}

//服务器端
public class ServerTest_Short {
int port = 8821;

void start() {
Socket s = null;
try {
ServerSocket ss = new ServerSocket(port);
while (true) {
// 选择进行传输的文件
String filePath = "D:/compress-image.sh";
File fi = new File(filePath);

System.out.println("文件长度:" + (int) fi.length());

// public Socket accept() throws
// IOException侦听并接受到此套接字的连接。此方法在进行连接之前一直阻塞。

s = ss.accept();
DataInputStream inputStream = null;
try {
inputStream = new DataInputStream(new BufferedInputStream(s.getInputStream()));
} catch (Exception e) {
System.out.print("接收消息缓存错误\n");
return;
}

try {
//本地保存路径,文件名会自动从服务器端继承而来。
String savePath = "E:\\";
int bufferSize = 8192;
byte[] buf = new byte[bufferSize];
int passedlen = 0;
long len=0;

savePath += inputStream.readUTF();
System.out.println("savePath = " + savePath);
DataOutputStream fileOut = new DataOutputStream(new BufferedOutputStream(new BufferedOutputStream(new FileOutputStream(savePath))));
len = inputStream.readLong();

System.out.println("文件的长度为:" + len + "\n");
System.out.println("开始接收文件!" + "\n");

while (true) {
int read = 0;
if (inputStream != null) {
read = inputStream.read(buf);
}
passedlen += read;
if (read == -1) {
break;
}
//下面进度条本为图形界面的prograssBar做的,这里如果是打文件,可能会重复打印出一些相同的百分比
// System.out.println("文件接收了" + (passedlen * 100/ len) + "%\n");
fileOut.write(buf, 0, read);
}
System.out.println("接收完成,文件存为" + savePath + "\n");
fileOut.close();

//将成功信息返回客户端
DataOutputStream outputStream = new DataOutputStream(s.getOutputStream());
outputStream.writeUTF("success");
outputStream.flush();

} catch (Exception e) {
System.out.println("接收消息错误" + "\n");
return;
}

}

} catch (Exception e) {
e.printStackTrace();
}
}

public static void main(String arg[]) {
new ServerTest_Short().start();
}
}

//工具类
public class ClientSocket_Short {
private String ip;

private int port;

private Socket socket = null;

DataOutputStream out = null;

DataInputStream getMessageStream = null;

public ClientSocket_Short(String ip, int port) {
this.ip = ip;
this.port = port;
}

/** *//**
* 创建socket连接
*
* @throws Exception
* exception
*/
public Socket CreateConnection() throws Exception {
try {
socket = new Socket(ip, port);
} catch (Exception e) {
e.printStackTrace();
if (socket != null)
socket.close();
throw e;
} finally {
}
return socket;
}

public void sendMessage(String sendMessage) throws Exception {
try {
out = new DataOutputStream(socket.getOutputStream());
if (sendMessage.equals("Windows")) {
out.writeByte(0x1);
out.flush();
return;
}
if (sendMessage.equals("Unix")) {
out.writeByte(0x2);
out.flush();
return;
}
if (sendMessage.equals("Linux")) {
out.writeByte(0x3);
out.flush();
} else {
out.writeUTF(sendMessage);
out.flush();
}
} catch (Exception e) {
e.printStackTrace();
if (out != null)
out.close();
throw e;
} finally {
}
System.out.println("发送结束1");
}

public DataInputStream getMessageStream() throws Exception {
try {
getMessageStream = new DataInputStream(new BufferedInputStream(socket.getInputStream()));
return getMessageStream;
} catch (Exception e) {
e.printStackTrace();
if (getMessageStream != null)
getMessageStream.close();
throw e;
} finally {
}
}

public void shutDownConnection() {
try {
if (out != null)
out.close();
if (getMessageStream != null)
getMessageStream.close();
if (socket != null)
socket.close();
} catch (Exception e) {

}
}
}
...全文
598 5 打赏 收藏 转发到动态 举报
写回复
用AI写文章
5 条回复
切换为时间正序
请发表友善的回复…
发表回复
GK20182 2010-09-27
  • 打赏
  • 举报
回复
忘了说“fileOut.write(buf, 0, read);”需要放到“if (read <= buf.length)”上面

测试小文件没问题,大文件同样出现阻塞现象(估计是客户端问题)……等高人解答
GK20182 2010-09-27
  • 打赏
  • 举报
回复
刚测试了一下LZ的代码,问题出在服务端。
把服务端读取客户端信息那处的“if (read == -1)”改为“if (read <= buf.length)”即可。
因为LZ程序中服务端的“if (read == -1)”在客户端输出口不close的情况下,永远不会成立,所以会锁死。

没想到翻了个老帖出来,希望对新手有所帮助。我自己也是菜鸟,有什么说错的请多多指教。
GK20182 2010-09-27
  • 打赏
  • 举报
回复
楼上的没做过Socket通信吧
shuaiAWP 2010-04-08
  • 打赏
  • 举报
回复

//这里添代码

shuaiAWP 2010-04-08
  • 打赏
  • 举报
回复
while循环都是死循环
JAVA SOCKET 编程的经典之书,(中文版)里面的代码可直接复制使用! 目录: 第1章简介..........3 1.1 计算机网络,分组报文和协议..........3 1.2 关于地址..........6 1.3 关于名字..........8 1.4 客户端和服务器..........8 1.5 什么是套接字..........9 1.6 练习..........10 第2章基本套接字..........10 2.1 套接字地址..........10 2.2 TCP套接字..........17 2.2.1 TCP客户端..........17 2.2.2 TCP服务器端..........22 2.2.3 输入输出流..........26 2.3 UDP套接字..........28 2.3.1 DatagramPacket类..........28 2.3.2 UDP客户端..........30 2.3.3 UDP服务器端..........36 2.3.4 使用UDP套接字发送和接收信息..........38 2.4 练习..........40 第3章发送和接收数据..........41 3.1 信息编码..........42 3.1.1 基本整型..........42 3.1.2 字符串和文本..........48 3.1.3 位操作:布尔值编码..........50 3.2 组合输入输出流..........51 3.3 成帧与解析..........52 3.4 Java特定编码..........58 3.5 构建和解析协议消息..........59 3.5.1 基于文本的表示方法..........62 3.5.2 二进制表示方法..........65 3.5.3 发送和接收..........67 3.6 结束..........76 3.7 练习..........76 第4章进阶..........77 4.1 多任务处理..........77 4.1.1 Java 多线程..........78 4.1.2 服务器协议..........80 4.1.3 一客户一线程..........84 4.1.4 线程池..........86 4.1.5 系统管理调度:Executor接口..........89 4.2 阻塞和超时..........91 4.2.1 accept(),read()和receive()..........91 4.2.2 连接和写数据..........92 4.2.3 限制每个客户端的时间..........92 4.3 多接收者..........94 4.3.1 广播..........94 4.3.2 多播..........95 4.4 控制默认行为..........100 4.4.1 Keep-Alive..........100 4.4.2 发送和接收缓存区的大小..........101 4.4.3 超时..........101 4.4.4 地址重用..........102 4.4.5 消除缓冲延迟..........102 4.4.6 紧急数据..........103 4.4.7 关闭后停留..........103 4.4.8 广播许可..........103 4.4.9 通信等级..........104 4.4.10 基于性能的协议选择..........104 4.5 关闭连接..........104 4.6 Applets..........111 4.7 结束..........112 4.8 练习..........112 第5章 NIO..........112 5.1 为什么需要NIO?..........113 5.2 与Buffer一起使用Channel..........115 5.3 Selector..........118 5.4 Buffer详解..........125 5.4.1 Buffer索引..........125 5.4.2 创建Buffer..........126 5.4.3 存储和接收数据..........128 5.4.4 准备Buffer:clear(),flip(),和rewind()..........130 5.4.5 压缩Buffer中的数据..........132 5.4.6 Buffer透视:duplicate(),slice()等..........134 5.4.7 字符编码..........136 5.5 流(TCP)信道详解..........136 5.6 Selector详解..........139 5.6.1 在信道中注册..........139 5.6.2 选取和识别准备就绪的信道..........141 5.6.3 信道附件..........143 5.6.4 Selector小结..........144 5.7 数据报(UDP)信道..........144 5.8 练习..........149 1. 使用定长的写缓冲区改写TCPEchoClientNonblocking.java。..........149 2.使用Buffer和DatagramChannel编写一个回显客户端。..........149 第6章深入剖析..........149 6.1 缓冲和TCP..........152 6.2 死锁风险..........155 6.3 性能相关..........158 6.4 TCP套接字的生存周期..........158 6.4.1 连接..........158 6.4.2 关闭TCP连接..........164 6.5 解调多路复用揭秘..........167 6.6 练习..........169

62,628

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

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