栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

通过Socket读取数据InputStream.read()阻塞问题

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

通过Socket读取数据InputStream.read()阻塞问题

想用Socket写一个Server端和Client端一个请求回复的Demo 发现程序阻塞了 记录一下

我是这么写的

public class BioClient1 {
    public static void main(String[] args) throws IOException {
        Socket socket = null;
        try {
            //发送你好
            socket = new Socket("127.0.0.1", 8080);
            OutputStream outputStream = socket.getOutputStream();
            BufferedOutputStream dos = new BufferedOutputStream(outputStream);
            dos.write("你好啊".getBytes());
            dos.flush();
            //接收服务端返回数据
            InputStream inputStream = socket.getInputStream();
            ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
            int offset = -1;
            byte[] buffer = new byte[1024];
            while ((offset = inputStream.read(buffer)) != -1) {
                byteArrayOutputStream.write(buffer, 0, offset);
            }
            inputStream.close();
            System.out.println(byteArrayOutputStream);
            byteArrayOutputStream.close();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (socket != null) {
                socket.close();
            }
        }
    }

}
public class BioServer1 {
    public static void main(String[] args) throws IOException {
        ServerSocket serverSocket = new ServerSocket(8080);

        for(;;) {
            Socket accept = serverSocket.accept();
            SocketHandle socketHandle = new SocketHandle(accept);
            socketHandle.start();
        }
    }


    static class SocketHandle extends Thread {
        private Socket socket;

        SocketHandle(Socket socket) {
            this.socket = socket;
        }

        @Override
        public void run() {
            try {
                ByteArrayOutputStream baos = new ByteArrayOutputStream();
                InputStream inputStream = socket.getInputStream();
                byte[] bytes = new byte[1024];
                int offset = -1;
                //如果用这个的话这行代码的read方法会阻塞 因为客户端的OutputStream没有关闭
                while ((offset = inputStream.read(bytes)) != -1) {
                    baos.write(bytes, 0, offset);
                }
                byte[] result = new byte[read];
                System.arraycopy(bytes, 0, result, 0, read);
                System.out.println(new String(result, StandardCharsets.UTF_8));
                OutputStream outputStream = socket.getOutputStream();
                outputStream.write("你也好啊".getBytes());
                outputStream.flush();
                outputStream.close();
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                try {
                    socket.close();
                } catch (Exception e) {
                }
            }

        }
    }
}

整个流程大概是

 阻塞问题出现在Server端的inputStream.read()中 这个是因为客户端的outputStream发送完消息后并没有close 因为我之后还要用到客户端的inputStream获取服务端回复的消息 如果客户端发送完消息就关闭outputStream 之后获取inputStream会报连接重置异常 所以这边给出两种方案

1.只修改服务端只调用一次 inputStream.read  这样就不会阻塞了 但只能获取不能大于的数组大小的字符了 

public class BioServer1 {
    public static void main(String[] args) throws IOException {
        ServerSocket serverSocket = new ServerSocket(8080);

        for(;;) {
            Socket accept = serverSocket.accept();
            SocketHandle socketHandle = new SocketHandle(accept);
            socketHandle.start();
        }
    }


    static class SocketHandle extends Thread {
        private Socket socket;

        SocketHandle(Socket socket) {
            this.socket = socket;
        }

        @Override
        public void run() {
            try {
                InputStream inputStream = socket.getInputStream();
                byte[] bytes = new byte[1024];
                int read = inputStream.read(bytes);
                byte[] result = new byte[read];
                System.arraycopy(bytes, 0, result, 0, read);
                System.out.println(new String(result, StandardCharsets.UTF_8));
                OutputStream outputStream = socket.getOutputStream();
                outputStream.write("你也好啊".getBytes());
                outputStream.flush();
                outputStream.close();
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                try {
                    socket.close();
                } catch (Exception e) {
                }
            }
        }
    }
}

客户端的代码不用修改 但如果把服务端中的最后的socket.close和outputStream.close();去掉的话 客户端依旧会阻塞 

2.在客户端发送信息完成之后调用socket的shutdownOutput方法 这个就只需要修改客户端的代码

public class BioClient1 {
    public static void main(String[] args) throws IOException {
        Socket socket = null;
        try {
            //发送你好
            socket = new Socket("127.0.0.1", 8080);
            OutputStream outputStream = socket.getOutputStream();
            BufferedOutputStream dos = new BufferedOutputStream(outputStream);
            dos.write("你好啊".getBytes());
            dos.flush();
            //添加关闭socket 输出流
            socket.shutdownOutput();

            //接收服务端返回数据
            InputStream inputStream = socket.getInputStream();
            ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
            int offset = -1;
            byte[] buffer = new byte[1024];
            while ((offset = inputStream.read(buffer)) != -1) {
                byteArrayOutputStream.write(buffer, 0, offset);
            }
            inputStream.close();
            System.out.println(byteArrayOutputStream);
            byteArrayOutputStream.close();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (socket != null) {
                socket.close();
            }
        }
    }

}

这个方法相对优雅 

相关阅读

记录一次Socket的异常:InputStream.read()阻塞问题_鸡冠花12138的博客-CSDN博客_inputstream read 超时

 

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/871850.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号