Java Socket 阻塞问题 求解

pangjingji 2013-12-24 09:55:48
服务器端

public class DayTimeServer {

public static void main(String[] args){

ServerSocket server=null;
try {
//服务器端8080端口
server=new ServerSocket(8080);
} catch (IOException e) {
e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
return;
}


int i=0;
while(true){
Socket socket = null;
try {
socket = server.accept();
// BufferedInputStream bIn=new BufferedInputStream(socket.getInputStream());
BufferedOutputStream bOut=new BufferedOutputStream(socket.getOutputStream());
BufferedWriter bWriter=new BufferedWriter(new OutputStreamWriter(bOut,"ASCII"));
bWriter.write((new SimpleDateFormat("yyyy-MM-dd")).format(new Date()));
bWriter.flush();
System.out.println(++i);
} catch (IOException e) {
e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
}/* finally{
if(socket!=null){
try {
socket.close();
} catch (IOException e) {
e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
}
}
}*/
}
}

}



客户端:

public class Client {
public static void main(String[] args) {

InetSocketAddress address = null;
address = new InetSocketAddress("127.0.0.1", 8080);

int i = 0;
while (true) {
Socket socket = null;
try {
socket = new Socket();
socket.connect(address);
BufferedInputStream bIn = new BufferedInputStream(socket.getInputStream());
int c;
while ((c = bIn.read()) != -1) {
System.out.print((char) c);
}
System.out.println(++i);
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
if (socket != null) {
try {
socket.close();
} catch (IOException e) {
// TODO Auto-generated catch block
}
}
}

}

}

}

服务器端socket.close()被注释掉后,会造成客户端阻塞,不晓得why? 求解
...全文
183 7 打赏 收藏 转发到动态 举报
写回复
用AI写文章
7 条回复
切换为时间正序
请发表友善的回复…
发表回复
xiaomm627 2013-12-25
  • 打赏
  • 举报
回复
引用 6 楼 pangjingji 的回复:
[quote=引用 1 楼 xiaomm627 的回复:] 当你在服务端注释掉close方法后,客户端这种接收方式,是不晓得服务端是否已经传输完数据,此时客户端还在等待服务端传来的数据(其实数据已经传完了,但客户端却无法判断出来,所以一直还在接收数据)当然会阻塞了。 两种改进方法: 1、如果单纯的发送字符串数据可以用PrintWrite(.println())发送,接收时用BufferedReader(.readLine()) 2、使用字节数组。write(byte[]),服务端告知客户端发送多少字节的数据,,客户端一旦接收完这么多数据就退出循环。
为什么阻塞上面的解释说的是对的。但对于方法一只能读取一行,方法二只能读取固定字节。 谢谢你的解释。在服务器端调用socket.shutdownInput()也是可以的,这样会给客户端输入流一个结束标记。[/quote] socket.shutdownInput()是半关闭,只关闭了输入流不能发数据但可以接收数据,但是我觉得如果没有特殊需求,应该关闭socket的,呵呵。 另外及时socket.shutdownInput()和socket.shutdownOutput()都写了,socket也不会关闭。
pangjingji 2013-12-24
  • 打赏
  • 举报
回复
引用 1 楼 xiaomm627 的回复:
当你在服务端注释掉close方法后,客户端这种接收方式,是不晓得服务端是否已经传输完数据,此时客户端还在等待服务端传来的数据(其实数据已经传完了,但客户端却无法判断出来,所以一直还在接收数据)当然会阻塞了。 两种改进方法: 1、如果单纯的发送字符串数据可以用PrintWrite(.println())发送,接收时用BufferedReader(.readLine()) 2、使用字节数组。write(byte[]),服务端告知客户端发送多少字节的数据,,客户端一旦接收完这么多数据就退出循环。
为什么阻塞上面的解释说的是对的。但对于方法一只能读取一行,方法二只能读取固定字节。 谢谢你的解释。在服务器端调用socket.shutdownInput()也是可以的,这样会给客户端输入流一个结束标记。
xiaomm627 2013-12-24
  • 打赏
  • 举报
回复
产生阻塞的原因我已经说过了,总之 像你这种通讯结束后在服务端不关闭socket,也就是所谓的长连接。这种方式有些场合需要,比如socket连接池。没有特殊需求,建议关闭socket。
xiaomm627 2013-12-24
  • 打赏
  • 举报
回复
法二代码(改动最小) 服务端
import java.io.BufferedOutputStream;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.text.SimpleDateFormat;
import java.util.Date;




public class DayTimeServer {

    public static void main(String[] args){

        ServerSocket server=null;
        try {
            //服务器端8080端口
            server=new ServerSocket(8080);
        } catch (IOException e) {
            e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
            return;
        }


        int i=0;
        while(true){
            Socket socket = null;
            try {
                socket = server.accept();
                // BufferedInputStream bIn=new BufferedInputStream(socket.getInputStream());
                BufferedOutputStream bOut=new BufferedOutputStream(socket.getOutputStream());
                BufferedWriter bWriter=new BufferedWriter(new OutputStreamWriter(bOut,"ASCII"));
                bWriter.write((new SimpleDateFormat("yyyy-MM-dd")).format(new Date()));
                bWriter.flush();
                System.out.println(++i);
            } catch (IOException e) {
                e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
            }/* finally{ 
                if(socket!=null){
                    try {
                        socket.close();
                    } catch (IOException e) {
                        e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
                    }
                }
            }*/
        }
    }

}




客户端:
import java.io.BufferedInputStream;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.UnknownHostException;


public class Client {
    public static void main(String[] args) {

        InetSocketAddress address = null;
        address = new InetSocketAddress("127.0.0.1", 8080);

        int i = 0;
        while (true) {
            Socket socket = null;
            try {
                socket = new Socket();
                socket.connect(address);
                BufferedInputStream bIn = new BufferedInputStream(socket.getInputStream());
                int c;
                byte[] buff = new byte[10];
                //while ((c = bIn.read(buff)) != -1) {//不能用while循环,否则会产生阻塞
                    c = bIn.read(buff);
                    System.out.print(new String(buff));
                //}
                System.out.println(++i);
            } catch (UnknownHostException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } finally {
                if (socket != null) {
                    try {
                        socket.close();
                    } catch (IOException e) {
                        // TODO Auto-generated catch block
                    }
                }
            }

        }

    }

}
xiaomm627 2013-12-24
  • 打赏
  • 举报
回复
法一代码: 服务端

import java.io.IOException;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.text.SimpleDateFormat;
import java.util.Date;



public class DayTimeServer {

    public static void main(String[] args){

        ServerSocket server=null;
        try {
            //鏈嶅姟鍣ㄧ8080绔彛
            server=new ServerSocket(8080);
        } catch (IOException e) {
            e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
            return;
        }


        int i=0;
        while(true){
            Socket socket = null;
            try {
                socket = server.accept();
                // BufferedInputStream bIn=new BufferedInputStream(socket.getInputStream());
                PrintWriter pw=new PrintWriter(socket.getOutputStream());
                pw.println((new SimpleDateFormat("yyyy-MM-dd")).format(new Date()));
                pw.flush();
            } catch (IOException e) {
                e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
            }/* finally{ 
                if(socket!=null){
                    try {
                        socket.close();
                    } catch (IOException e) {
                        e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
                    }
                }
            }*/
        }
    }

}
客户端:

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.UnknownHostException;



public class Client {
    public static void main(String[] args) {

        InetSocketAddress address = null;
        address = new InetSocketAddress("127.0.0.1", 8080);

        int i = 0;
        while (true) {
            Socket socket = null;
            try {
                socket = new Socket();
                socket.connect(address);
                BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
                String str = null;
               // while ((str = br.readLine()) != null) {//注意这里不能用while循环 否则还会产生阻塞
                	str = br.readLine();
                    System.out.print(str);
                //}
                System.out.println(++i);
            } catch (UnknownHostException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } finally {
                if (socket != null) {
                    try {
                        socket.close();
                    } catch (IOException e) {
                        // TODO Auto-generated catch block
                    }
                }
            }

        }

    }

}


teemai 2013-12-24
  • 打赏
  • 举报
回复
按照楼上的,用字节数组或者readline读取吧
xiaomm627 2013-12-24
  • 打赏
  • 举报
回复
当你在服务端注释掉close方法后,客户端这种接收方式,是不晓得服务端是否已经传输完数据,此时客户端还在等待服务端传来的数据(其实数据已经传完了,但客户端却无法判断出来,所以一直还在接收数据)当然会阻塞了。 两种改进方法: 1、如果单纯的发送字符串数据可以用PrintWrite(.println())发送,接收时用BufferedReader(.readLine()) 2、使用字节数组。write(byte[]),服务端告知客户端发送多少字节的数据,,客户端一旦接收完这么多数据就退出循环。

62,614

社区成员

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

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