zoukankan      html  css  js  c++  java
  • 理解socket的阻塞

        从socket中得到一个输入流InputStrean,然后从这个流中取数据,如果这个时候流里面的没有数据,可能是服务还没有发数据过来或发过来的数据也取完了,那么线程就会停在那里..直到服务器在发数据过来,从Socket的InputStream中取到了数据,这个线程才会向下走.所以当要和服务器交互通信的时候,就用一个while一真从Socket的流中数据取,流中的数据取完了就停在那里.等服务器在次发数据过来.---这就是阻塞的

        这个时候就有一个问题了,当我从Socket中的流中取数据时,如果服务器一直不发数据过来,也就是从Socket中得到的InputStream流中一直没有数据,那么这个程序就一直停在从流中取数据的那一行.

        如果过了很长时间服务器还没有数据发过来,就不等了,想让程序继续执行以后的代码.这时只一个办法,把服务器端关掉.客户端检测到这个Socket连接已断开,就不会停在从流中取数据的代码,而是执行下面的代码.

        显然以把服务器关掉的方式来让Socket连接断开有点不合适,所以我想到的办法就是用多线程.让线程A执行主代码,线程B去从流中读取数据,如果服务器又迟迟不发数据过来,又不关掉这个连接,那么线程B就一真让它阻塞在那里.

        上面的所有,用一包话来概括:javaIO流是阻塞流,(JavaNIO(java new io非阻塞流,NIO这里没有用到).

        这里在说说在ServerSocket是中的accept()方法也是一个阻塞方法,也就是如果没有客户端来连接,那么就线程就一直停在那里.直到有一个客户端口连接了,才开始执行后面的代码.

        从上面一点,可以看出如果要创建多客端的服务器,就要多次调用accept()方法,同要用多线程来做,线程A来一直循环执行accept().当有socket连接来过的时候就,创建一个新的线程来处理专门处理这个连接.

        到这里还没有完,因为前面提到过,Socket连接里面的输入输出流也是阻塞的,如果这个Socket连好过后,客户端和服务器迟迟不发数据,那么这个新创建的线程也会阻塞在那里,(除非这个新创建的线程里面不操作Socket里面的IO),为了阻止这种情况,就要像上面说的,在新创建的线程里面在新创建一个线程处理Socket里面的流的问题.

    下面的程序的测试客户端口建议用Sockettool的一个小软件

    public class SocketServer {
    
        public static void main(String[] args) throws IOException {
            ServerSocket serversocket = new ServerSocket(10088);
            Socket socket = serversocket.accept();// 同样这也是一个阻塞方法
            //当第一个客户端连接进来过后就会执行这句话,
            System.out.println("accept方法通过了....");
            //这个程序如果没有第二个客户端连进,那以下的代码不会执行到的.
            Socket socket2 = serversocket.accept();
            System.out.println("accept2方法通过了....");
            InputStream instream = socket.getInputStream();
            BufferedReader reader = new BufferedReader(new InputStreamReader(instream));
            String line="";
            while (true){
                line=reader.readLine();
                if(line==null){
                    System.out.println("line 为NULL 了");
                    break;
                }
                System.out.println(line);
            }
            /**
             * 程序有一种情况可以执行到这里,就是socket客户端口断开.不是socket2断开
             * 第一个连接断开后line=reader.readLine();就不会在阻塞了.流中的数据读
             * 完过后跳就跳出了while向下执行了.
             */
            System.out.println("程序结束了");
            
            // 关闭资源
            socket.close();
            serversocket.close();
        }
    }

    所在要做网络编程就要到多线程.也这是多线程的一个理解:在多用户和多网络的的情况下,不可能为每一个用户,和网络请求都创建一个进程所以就有了线程.

  • 相关阅读:
    1212321
    123123
    好好干活
    VXLAN学习之路-结合VRF在Linux中实践VXLAN网络
    123456
    期望
    123456
    123456
    Jenkins管理员密码忘记修改操作
    Jenkins 安装与部署详细教程
  • 原文地址:https://www.cnblogs.com/yinyu/p/5298916.html
Copyright © 2011-2022 走看看