关于linux网络相关的基础知识点,最热的两个就是socket和epoll,接下来我就用最简单的方式把他俩说清楚便于大家理解!
Socket
Socket 是一种进程间通信的方法,它允许位于同一主机(计算机)或使用网络连接起来的不同主机上的应用程序之间交换数据。
Socket起源于Unix,而Unix/Linux基本哲学之一就是“一切皆文件”,都可以用“打开open> 读写write/read > 关闭close”模式来操作。Socket就是该模式的一个实现,socket即是一种特殊的文件,一些socket函数就是对其进行的操作(读/写IO、打开、关闭)
Socket实现细节
当有客户端连接服务端时,服务端 Socket 文件中会写入这个客户端 Socket 的文件描述符。进程可以通过 accept() 方法,从服务端 Socket 文件中读出客户端的 Socket 文件描述符,从而拿到客户端的 Socket 文件。
程序猿实现一个网络服务器的时候,会先手动去创建一个服务端 Socket 文件。服务端的 Socket 文件依然会存在操作系统内核之中,并且会绑定到某个 IP 地址和端口上。以后凡是发送到这台机器、目标 IP 地址和端口号的连接请求,在形成了客户端 Socket 文件之后,文件的文件描述符都会被写入到服务端的 Socket 文件中。
应用只要调用 accept 方法,就可以拿到这些客户端的 Socket 文件描述符,这样服务端的应用就可以方便地知道有哪些客户端连接了进来。而每个客户端对这个应用而言,都是一个文件描述符。如果需要读取某个客户端的数据,就读取这个客户端对应的 Socket 文件。如果要向某个特定的客户端发送数据,就写入这个客户端的 Socket 文件。
epoll
与 socket 的交互,最核心的场景就是网络 IO 的处理, epoll 会协助我们高效完成。我们新建立一个网络 socket 的时候,交给 epoll 就可以了,当网络 IO 有数据到来时它会通知我们,当我们要往网络 IO 写数据时,epoll 也会自动帮我们发送,本质上epoll实现了IO 多路复用。
Epoll数据结构如下:
· rbr:被 epoll 所管理的所有 socket 都存储在红黑树中。
· rdllist:存储着所有就绪的 socket(所谓"就绪",意思指有网络数据到来,或者有数据要发送出去。)
就绪列表是 epoll 能够高效的核心,对于每一个就绪的 socket,会直接放入 rdllist 中,epoll_wait 获取到就绪的 socket 时,直接从 rdllist 中进行获取就可以了,无需再进行查找。epoll 是基于事件回调机制地,当 epoll 所管理地 socket 有数据到来时,会触发事件回调函数,将就绪的 socket 放置在 rdllist 中,并且通知 epoll_wait 所在的进程来处理数据。epoll的优点如下:
- 支持海量并发连接。
- 使用时间复杂度为 O(logn)的红黑树管理所有的 socket。
- 提高 CPU 的使用率,高效地使用 CPU 时间片处理所管理的 socket 连接。
- 基于事件回调机制处理消息,而不是主动轮询机制。
除了epoll,内核还提供了select和poll,但是二者效率较差,这里就不再进行介绍了。
最后的总结
不同的客户端与服务端通信通过Socket实现,而epoll使得通信变更加高效!