zoukankan      html  css  js  c++  java
  • 关于java socket中的read方法阻塞问题

    客户端:

    public class TCPClient {
        public static void main(String[] args) throws IOException {
            FileInputStream fis=new FileInputStream("E:\Trump.jpg");
            Socket socket=new Socket("127.0.0.1",8888);
            OutputStream os=socket.getOutputStream();
            byte[] bytes=new byte[1024];
            int len;
            while((len=fis.read(bytes))!=-1){
                //将读取到的数据传输到客户端与服务器端之间的IO流
                os.write(bytes,0,len);
            }
           
            //读服务器回写的数据
            InputStream is=socket.getInputStream();
            len=is.read(bytes);
            System.out.println(new String(bytes,0,len));
    
            socket.close();
            fis.close();
        }
    }
    

    服务器端:

    public class TCPServer {
        public static void main(String[] args) throws IOException {
            ServerSocket server=new ServerSocket(8888);
            Socket socket=server.accept();
            InputStream is=socket.getInputStream();
            FileOutputStream fos=new FileOutputStream("E:\Test\Trump.jpg");
    
            int len;
            byte[] bytes=new byte[1024];
            while ((len=is.read(bytes))!=-1) {
                fos.write(bytes,0,len);
            }
    
            OutputStream os=socket.getOutputStream();
            os.write("文件上传完毕!".getBytes());
            fos.close();
            socket.close();
    
        }
    }
    

    这段代码执行以后会发现server类 read()方法发生了阻塞,经过查找资料发现read()是一个阻塞函数(阻塞函数就是当这个函数不执行完,函数所在线程就一直停止在这里不动。)。
    在输入数据可用、检测到流末尾或者抛出异常前,read方法一直阻塞。如果客户端没有声明断开outputStream那么它就会认为客户端仍旧可能发送数据,像read()这种阻塞读取函数还有BufferedReader类种的 readLine()、DataInputStream种的readUTF()等。

    解决方案:
    Socket任意一端在调用完write()方法时调用shutdownOutput()方法关闭输出流,这样服务器端的inputStream上的read操作就会返回-1, 这里我们要注意下不能调用socket.getInputStream().close()。因为它会导致socket直接被关闭。 当然如果不需要继续在socket上进行读操作,也可以直接关闭socket。但是这个方法不能用于通信双方需要多次交互的情况。

    原文:https://www.cnblogs.com/gaoqiri/p/10055610.html

  • 相关阅读:
    VS2017试用期到期后登录微软账户出现错误解决方法
    Unable to start process "dotnet-projectmodel-server" while starting VS2015 问题
    如何写.gitignore只包含指定的文件扩展名
    Win7 通过Smb共享CentOS文件步骤
    Linux下用sudo 命令时出现 is not in the sudoers file
    ubuntu下安装chorme浏览器
    qt for ios扫描二维码功能实现
    ubuntu14.04登陆后只显示桌面文件,快速启动栏不显示,终端不能打开
    编译 Qt with Openssl for IOS
    sql print原理
  • 原文地址:https://www.cnblogs.com/Frank-Hong/p/13454542.html
Copyright © 2011-2022 走看看