在这个模式下,老陈就如同一个同步阻塞的tcp client,不断地等待着女儿寄来的信件。只有当邮递员将信投递到收发室,老陈才能收到信件,这就像是tcp client在等待着服务器端发送数据过来。
二、同步非阻塞模型
老陈开始觉得等待女儿的来信有些无聊,于是决定不再一直呆在收发室里等待,而是每隔一段时间就去看看有没有信件。这就是linux的同步非阻塞模式;在这个模式中,应用程序会反复调用系统调用来检查是否有数据准备好,不会一直阻塞等待。Socket设置为非阻塞模式时,如果socket没有准备好I/O操作,调用会立即返回,不会一直等待,通过不断轮询来检查socket状态,来实现数据的接收和发送。如图 2 所示:
这样,老陈就可以在等待信件的同时,还可以做一些其他的事情,不再像同步阻塞模式那样一直呆在收发室等待。
三、多路复用模型
老陈觉得每次去看信件还是有些麻烦,于是想到了让邮递员在投递信件的同时通知他一声,这样他就不用一直等待了。这就是linux的多路复用模式;在这个模式中,应用程序使用select、poll、epoll等系统调用来监视多个文件描述符,当其中任何一个文件描述符准备好进行I/O操作时,就会通知应用程序进行处理。通过这种方式,可以同时监视多个socket,当任何一个socket准备好进行I/O操作时,就可以立即处理,提高了效率。如图 3 所示:
这样,老陈就可以在不断地监视信件的同时,还可以处理其他的事务,不再需要每次都亲自去看看有没有信件。
四、异步模型
最后,老陈想到了一个更好的方法,他委托了一个专门的代收员来帮他收取信件,只需要在信件到达时收取即可,不再需要自己亲自去监视。这就是linux的异步模式;在这个模式中,应用程序执行一个异步系统调用后,可以立即返回,不需要等待I/O操作完成,当操作完成后,内核会通知应用程序。Socket设置为异步模式时,应用程序不需要一直等待I/O操作完成,可以继续执行其他任务,当I/O操作完成时,内核会主动通知应用程序进行处理。如图 4 所示:
这样,老陈就可以完全不用关心信件的收取问题,只需要在信件到达时去拿即可,大大提高了效率和便利性。
总结来说,linux的SocketI/O模型就像老陈与女儿通过邮递员来传递信件一样,通过不同的模式,可以实现不同的I/O操作方式,提高了效率和便利性。无论是同步阻塞模式、同步非阻塞模式、多路复用模式还是异步模式,都有各自的优劣和适用场景,可以根据实际需求选择最合适的模式来进行I/O操作。希望通过这个生动的比喻,能够更好地理解和掌握linux的SocketI/O模型。