cook503 2013-02-07 18:37 采纳率: 0%
浏览 316
已采纳

网络编程中阻塞式IO的真正含义到底是什么

这两天在看socket编程,可以说这方面是个新手,其中看到了nio,网上有很多文章介绍了nio相对于多线程处理网络链接(每建立一个socket链接,服务器便会开启一个线程来对此socket单独处理和客户端的通信)的优点。因为nio是事件驱动,不会发生Socket读取流数据时的阻塞。我想问的是这里所说的读取流数据的阻塞是我们平时所说的线程进入阻塞态吗?

当一个线程单独处理一个客户端请求时,它需要等待客户端向它的输出流写入数据,完后服务器端处理此socket的线程才能读取数据,如果客户端未写入数据,那么服务器端线程便会一直停留在对流的读取状态,即调用流的read()方法,我感到疑惑的是当客户端未写入数据而服务器端正在进入read()读取数据时,服务器端处理的这个线程是由运行态进入阻塞态了还是说一直在read()方法循环检测流中的数据(这样的话线程仍然在运行态),网上的很多表达让我对它们产生了很大的疑惑,关于网络中流的读取写入本人还是个新手,这可能涉及到更底层的一些东西,希望有人能够给指点一下。

我也看了java的源码,当流读取时,是进入一个 for(;;)的死循环。所以我认为是这个线程并没有进入阻塞态,而是一直循环在检测输入流的数据,一旦有数据便会从read()返回,不知道理解的对还是不对?

以下是服务器端的代码:
[code="java"] import java.io.*;
import java.net.*;
public class Server{
public static void main(String args[]) {
ServerSocket server=null;
try{
server=new ServerSocket(4700);
//创建一个ServerSocket在端口4700监听客户请求(已经建立监听)
}catch(Exception e) {
System.out.println("can not listen to:"+e);
//出错,打印出错信息
}
Socket socket=null;
try{
while(true){
socket=server.accept();
//使用accept()阻塞等待客户请求,
//请求到来则产生一个Socket对象,并继续执行
Thread t = new Thread(new Processor(socket));
t.start();
}
}catch(Exception e) {
System.out.println("Error."+e);
}
}
}

class Processor implements Runnable{
    private Socket socket;      
    public Processor(Socket socket){
        this.socket = socket;
    }       
    public void run() {
        try{
            String line;
            BufferedReader is=new BufferedReader(new InputStreamReader(socket.getInputStream()));
            //由Socket对象得到输入流,并构造相应的BufferedReader对象
            PrintWriter os=new PrintWriter(socket.getOutputStream());
            //由Socket对象得到输出流,并构造PrintWriter对象
            BufferedReader sin=new BufferedReader(new InputStreamReader(System.in));
            //由系统标准输入设备构造BufferedReader对象
            System.out.println("Client:"+is.readLine());
            //在标准输出上打印从客户端读入的字符串
            line=sin.readLine();
            //从标准输入读入一字符串
            while(!line.equals("bye")){
            //如果该字符串为 "bye",则停止循环
                os.println(line);
                //向客户端输出该字符串
                os.flush();
                //刷新输出流,使Client马上收到该字符串
                System.out.println("Server:"+line);
                //在系统标准输出上打印读入的字符串
                System.out.println("Client:"+is.readLine());
                //从Client读入一字符串,并打印到标准输出上
                line=sin.readLine();
                //从系统标准输入读入一字符串
            } //继续循环
            os.close(); //关闭Socket输出流
            is.close(); //关闭Socket输入流
            socket.close(); //关闭Socket
        }catch(Exception e){
            e.printStackTrace();
        }
    }
}[/code] 
  • 写回答

1条回答

  • iteye_9518 2013-02-08 09:23
    关注

    同步和异步是针对应用程序和内核的交互而言的,同步指的是用户进程触发IO操作并等待或者轮询的去查看IO操作是否就绪,而异步是指用户进程触发IO操作以后便开始做自己的事情,而当IO操作已经完成的时候会得到IO完成的通知。
    而阻塞和非阻塞是针对于进程在访问数据的时候,根据IO操作的就绪状态来采取的不同方式,说白了是一种读取或者写入操作函数的实现方式,阻塞方式下读取或者写入函数将一直等待,而非阻塞方式下,读取或者写入函数会立即返回一个状态值。

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥50 汇编语言除法溢出问题
  • ¥65 C++实现删除N个数据列表共有的元素
  • ¥15 Visual Studio问题
  • ¥15 state显示变量是字符串形式,但是仍然红色,无法引用,并显示类型不匹配
  • ¥20 求一个html代码,有偿
  • ¥100 关于使用MATLAB中copularnd函数的问题
  • ¥20 在虚拟机的pycharm上
  • ¥15 jupyterthemes 设置完毕后没有效果
  • ¥15 matlab图像高斯低通滤波
  • ¥15 针对曲面部件的制孔路径规划,大家有什么思路吗