【Java TCP阻塞问题...在线等...】有没有好心人帮我看看为什么这段代码会阻塞啊? 对了,请问大家在TCP套接字中(SendQ)发送队列 与 (RecvQ)接收队列 大小是多少啊? 解决方案 » 免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货 private static void sendBytes(Socket socket, InputStream fileIn) throws IOException { OutputStream sockOut = socket.getOutputStream(); int bytesRead = 0; byte[] buffer = new byte[BUFSIZE]; while ((bytesRead = fileIn.read(buffer)) != -1)//这里会阻塞的,因为如果没有字节读,则阻塞 { sockOut.write(buffer, 0, bytesRead); System.out.print("W"); } System.out.println("\nClient send data complete!"); socket.shutdownOutput(); System.out.println("Client is deadlock? No"); }这段代码有问题, 读socket 中 read(buffer) != -1 只在一种情况成立,就是在对方调用了 socket.shutdownOutput();方法.其它情况 永远不会有 -1出现, 所以你这里永远不可能结束,除非两种情况:1 对方调用了 socket.shutdownOutput();//你会收到-1, 但是如果对方程序不是你写的,不能保证哦.2 对方调用了 socket.close(); //会有异常,则结束,但是异常必须你再次读写数据时才会出现!! //不管是客户机,还是服务器程序,你这段代码只能是学习用, 要用到项目中去, 不能这么简单的写.while ((bytesRead = in.read(buffer)) != -1) { out.write(buffer, 0, bytesRead);}用如下代码, 自己再完善:try{ int pava=0; int cava=0; int sumb=0; int i=0; int c=0; ByteArrayOutputStream buffeOut =new ByteArrayOutputStream(); byte readbuf[] = new byte[10240]; while (socket.isConnected() && !socket.isClosed()) { i++; pava =in.available(); if(pava>0){ while ((c = in.read(readbuf)) != -1) { buffeOut.write(readbuf, 0, c); sumb =sumb + c; cava =in.available(); if(cava<=0){ Thread.sleep(100); cava =in.available(); if(cava<=0) break; } } String strin = new String(buffeOut.toByteArray(),"utf-8"); System.out.println("读取流数据内容: "+strin+","+sumb); buffeOut.reset(); //读完后回复信息. out.write((i+",我是服务器,已收到数据!").getBytes("utf-8")); out.flush(); if(c == -1) break;//对方关闭了输入流. }else{ sumb=0; out.write((i+",我是服务器,请发送数据!").getBytes("utf-8")); out.flush(); Thread.sleep(1000); } } } catch (SocketException e) { e.printStackTrace(); } catch (InterruptedException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } finally { System.out.println("Request,NO["+requestCount+"],读取流数据完成."); } 谢谢你,我的问题自己解决了,首先你将的不错,但是有一点你分析错了,当调用sockOut.write(buffer, 0, bytesRead)时,我发现程序是到这里才被阻塞,这说明——"接收端SendQ队列已被填满,所以才会造成服务端调用sockOut.write(buffer, 0, bytesRead)时阻塞", 这个问题与 "Socket的接收队列SendQ"有关!不过,这里还是要谢谢你,while ((bytesRead = in.read(buffer)) != -1) 这种写法得看用在什么场景下,也可以使用“自定义消息边界符”来实现。谢谢大家! “socket 中 read(buffer) != -1 只在一种情况成立” ,你说的这个观点是错的,正确观点是:只有两种观点成立,1.socket.shutdownOutput() 2.socket.close() ,建议你自己试试! 我这里写的代码,只是学习使用,不建议大家直接用到项目中,仅仅是学习使用哦!正确的代码如下:/* * 服务端 */public class TestServer{ public static void main(String[] args) throws IOException { System.out.println("服务端启动......"); ServerSocket server = new ServerSocket(8888); Socket client = server.accept(); OutputStream output = client.getOutputStream(); InputStream input = client.getInputStream(); byte[] temp = new byte[10]; int realLen = 0; while ((realLen = input.read(temp)) != -1) { System.out.println("【服务端】正在发送数据......"); output.write(temp, 0, realLen); } System.out.println("【客户端】发送数据完毕!"); output.flush(); client.close(); }}/* * 客户端 */public class TestClient{ public static void main(String[] args) throws UnknownHostException, IOException { System.out.println("客户端启动......"); final Socket client = new Socket(InetAddress.getLocalHost(), 8888); final OutputStream out = client.getOutputStream(); InputStream in = client.getInputStream(); final FileInputStream fileIn = new FileInputStream(new File( "D:\\杂乱\\桌面.jpg")); // 使用一个子线程发送数据 Thread handlerExecute = new Thread() { @Override public void run() { try { byte[] fileTemp = new byte[1024]; int realFileLen = 0; while ((realFileLen = fileIn.read(fileTemp)) != -1) { System.out.println("【客户端】正在发送数据......"); out.write(fileTemp, 0, realFileLen); } System.out.println("【客户端】发送数据完毕!"); out.flush(); client.shutdownOutput(); } catch (IOException e) { e.printStackTrace(); } } }; handlerExecute.start(); // 使用主线程接收数据 ByteArrayOutputStream byteArray = new ByteArrayOutputStream(); int realLen = 0; byte[] temp = new byte[10]; while ((realLen = in.read(temp)) != -1) { byteArray.write(temp, 0, realLen); } byte[] recvByte = byteArray.toByteArray(); System.out.println("客户端接收消息成功,消息长度:" + recvByte.length); }}一切有完好如初!再次感谢 guishuanglin !!! test1 方法中老是提示没有返回值类型 但是把i<=5去掉就行 求解 反编译类还原 int c=213 , 如何打印 “a” 这个字母呢? java类库学习中的疑惑 网站编程 与j2ee 一个有点意思的问题? Linuix 下生成图片问题 如何使ResultSet的游标往后移??? 我怎么将插入在TextArea中的内容显示在当前页面?详细内容请入内查看!! 一个线程的概念问题..... 这是什么意思 Jpcap抓取的数据包能否解析出具体的报文?若能该怎么做到
private static void sendBytes(Socket socket, InputStream fileIn)
throws IOException
{
OutputStream sockOut = socket.getOutputStream();
int bytesRead = 0;
byte[] buffer = new byte[BUFSIZE];
while ((bytesRead = fileIn.read(buffer)) != -1)//这里会阻塞的,因为如果没有字节读,则阻塞
{
sockOut.write(buffer, 0, bytesRead);
System.out.print("W");
}
System.out.println("\nClient send data complete!");
socket.shutdownOutput();
System.out.println("Client is deadlock? No");
}
这段代码有问题,
其它情况 永远不会有 -1出现, 所以你这里永远不可能结束,除非两种情况:
1 对方调用了 socket.shutdownOutput();//你会收到-1, 但是如果对方程序不是你写的,不能保证哦.
2 对方调用了 socket.close(); //会有异常,则结束,但是异常必须你再次读写数据时才会出现!!
//不管是客户机,还是服务器程序,你这段代码只能是学习用, 要用到项目中去, 不能这么简单的写.
while ((bytesRead = in.read(buffer)) != -1)
{
out.write(buffer, 0, bytesRead);
}用如下代码, 自己再完善:try{ int pava=0;
int cava=0;
int sumb=0;
int i=0;
int c=0;
ByteArrayOutputStream buffeOut =new ByteArrayOutputStream();
byte readbuf[] = new byte[10240];
while (socket.isConnected() && !socket.isClosed()) {
i++;
pava =in.available();
if(pava>0){
while ((c = in.read(readbuf)) != -1) {
buffeOut.write(readbuf, 0, c);
sumb =sumb + c;
cava =in.available();
if(cava<=0){
Thread.sleep(100);
cava =in.available();
if(cava<=0) break;
}
}
String strin = new String(buffeOut.toByteArray(),"utf-8");
System.out.println("读取流数据内容: "+strin+","+sumb);
buffeOut.reset();
//读完后回复信息.
out.write((i+",我是服务器,已收到数据!").getBytes("utf-8"));
out.flush();
if(c == -1) break;//对方关闭了输入流.
}else{
sumb=0;
out.write((i+",我是服务器,请发送数据!").getBytes("utf-8"));
out.flush();
Thread.sleep(1000);
}
}
} catch (SocketException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
System.out.println("Request,NO["+requestCount+"],读取流数据完成.");
}
谢谢你,我的问题自己解决了,首先你将的不错,但是有一点你分析错了,当调用sockOut.write(buffer, 0, bytesRead)时,我发现程序是到这里才被阻塞,这说明——"接收端SendQ队列已被填满,所以才会造成服务端调用sockOut.write(buffer, 0, bytesRead)时阻塞", 这个问题与 "Socket的接收队列SendQ"有关!不过,这里还是要谢谢你,while ((bytesRead = in.read(buffer)) != -1) 这种写法得看用在什么场景下,也可以使用“自定义消息边界符”来实现。谢谢大家!
“socket 中 read(buffer) != -1 只在一种情况成立” ,你说的这个观点是错的,正确观点是:只有两种观点成立,1.socket.shutdownOutput() 2.socket.close() ,建议你自己试试!
正确的代码如下:/*
* 服务端
*/
public class TestServer
{
public static void main(String[] args) throws IOException
{
System.out.println("服务端启动......");
ServerSocket server = new ServerSocket(8888); Socket client = server.accept();
OutputStream output = client.getOutputStream();
InputStream input = client.getInputStream(); byte[] temp = new byte[10];
int realLen = 0;
while ((realLen = input.read(temp)) != -1)
{
System.out.println("【服务端】正在发送数据......");
output.write(temp, 0, realLen);
}
System.out.println("【客户端】发送数据完毕!");
output.flush(); client.close();
}
}
/*
* 客户端
*/
public class TestClient
{
public static void main(String[] args) throws UnknownHostException,
IOException
{
System.out.println("客户端启动......");
final Socket client = new Socket(InetAddress.getLocalHost(), 8888); final OutputStream out = client.getOutputStream();
InputStream in = client.getInputStream();
final FileInputStream fileIn = new FileInputStream(new File(
"D:\\杂乱\\桌面.jpg")); // 使用一个子线程发送数据
Thread handlerExecute = new Thread()
{
@Override
public void run()
{
try
{
byte[] fileTemp = new byte[1024];
int realFileLen = 0; while ((realFileLen = fileIn.read(fileTemp)) != -1)
{
System.out.println("【客户端】正在发送数据......");
out.write(fileTemp, 0, realFileLen);
}
System.out.println("【客户端】发送数据完毕!"); out.flush();
client.shutdownOutput();
}
catch (IOException e)
{
e.printStackTrace();
}
}
}; handlerExecute.start(); // 使用主线程接收数据
ByteArrayOutputStream byteArray = new ByteArrayOutputStream();
int realLen = 0;
byte[] temp = new byte[10];
while ((realLen = in.read(temp)) != -1)
{
byteArray.write(temp, 0, realLen);
}
byte[] recvByte = byteArray.toByteArray(); System.out.println("客户端接收消息成功,消息长度:" + recvByte.length); }
}一切有完好如初!再次感谢 guishuanglin !!!