1. 两台主机是如何通信的
这里,我们不探讨两台主机是如何进行网络连接的,而是探讨两台主机在建立了网络连接后,是如何通过网络进行通信的。如果学习过《计算机网络》的话,你一定知道类似下面的这张图“数据在各层之间传递的过程”。这张图是站在计算机网络协议栈的角度,来说明了两台计算机上的两个进程是如何通信的。既然是协议,协议就是规则,是抽象的。所以通过这个图,我们只知道数据是如何抽象地在网络协议层之间流动的;并且知道两台主机之间的数据传输,实质上是通过它们之间的“物理传输媒体”实现的,简单理解为网线就行,因为这不是我们讨论的重点。但是,在一台主机内部,我应用程序的数据是如何流动到网线的?从网线获取的数据又是如何来到我的应用程序的?这两个问题的答案从这张图上是得不到的。因为这涉及到操作系统的知识。
2. 进程的数据是如何跑到网线上的(基于Linux)
这张图反映的是操作系统的知识。简单来说用户进程把要发送的数据放在用户缓冲区,然后调用系统调用write从而进入内核,进入内核之后的事情就是操作系统负责啦,操作系统会把你用户缓冲区中的数据复制到内核缓冲区,再将内核缓冲区的数据复制到网卡,再从通过“网线插口”传递到网线上。如果用户进程接收数据,流程反过来就行了。(这张图来自哪本书,求告知呀)
3. 套接字(Socket)是啥
我们先来看看如果没有套接字会怎么样。可以看出,程序员编写程序时,将直接面对这些复杂的协议,即低效又容易出错。
有了套接字之后,这样的:
所以,Socket是应用层与TCP/IP协议族之间软件抽象层,它是一组接口。在设计模式中,Socket其实就是一个门面模式,它把复杂的TCP/IP协议族隐藏在Socket接口后面,用户只需要调用简单的Socket提供的接口,而复杂的网络协议由socket去实现。我们无需深入理解tcp/udp协议,socket已经为我们封装好了,我们只需要遵循socket的规定去编程,写出的程序自然就是遵循网络协议标准的。
4. 用户进程和套接字的关系
要实现两台主机上两个进程之间的通信,我们的用户进程或者说应用程序,只需要和Socket打交道。Socket会把用户进程的数据发送出去,也会接收到你需要的数据然后拿给用户进程。所以说,人们常说的IO模型,BIO、NIO和AIO,select、poll和epoll这些概念,都是用户进程和套接字打交道的方式,人们探究的就是这两者之间怎么打交道才能使得用户进程更加高效。