网络编程
文章平均质量分 92
网络编程
_Rye_
左手代码右手诗
一行代码一行诗
展开
-
35 | 答疑:编写高性能网络编程框架时,都需要注意哪些问题?
而且,我们的 channel_map 还不会太占用内存,在最开始的时候,整个 channel_map 的指针数组大小为 0,当这个 channel_map 投入使用时,会根据实际使用的套接字的增长,按照 32、64、128 这样的速度成倍增长,这样既保证了实际的需求,也不会一下子占用太多的内存。就像是设计了一个抽象类,这个抽象类代表了框架给你提供的一个编程入口,你可以继承这个抽象类,完成一些方法的填充,这些方法和框架类一起工作,就可以表现出一定符合逻辑的行为。为什么一定要加一把锁呢?原创 2023-10-21 23:39:38 · 53 阅读 · 0 评论 -
34 | 自己动手写高性能HTTP服务器(三):TCP字节流处理和HTTP协议实现
这一讲我们主要讲述了整个编程框架的字节流处理能力,引入了 buffer 对象,并在此基础上通过增加 HTTP 的特性,包括 http_server、http_request、http_response,完成了 HTTP 高性能服务器的编写。实例程序利用框架提供的能力,编写了一个简单的 HTTP 服务器程序。原创 2023-10-21 23:38:01 · 192 阅读 · 0 评论 -
33 | 自己动手写高性能HTTP服务器(二):I/O模型和多线程模型实现
在这一讲里,我们重点讲解了框架中涉及多线程的两个重要问题,第一是主线程如何等待多个子线程完成初始化,第二是如何通知处于事件分发中的子线程有新的事件加入、删除、修改。第一个问题通过使用锁和信号量加以解决;第二个问题通过使用 socketpair,并将 sockerpair 作为 channel 注册到 event loop 中来解决。原创 2023-10-21 23:36:54 · 120 阅读 · 0 评论 -
32 | 自己动手写高性能HTTP服务器(一):设计和思路
下面,我们详细讲解一下以 event_loop 为核心的反应堆模式设计。这里有一张 event_loop 的运行详图,你可以对照这张图来理解。原创 2023-10-21 23:21:34 · 321 阅读 · 0 评论 -
31丨性能篇答疑:epoll源码深度剖析
在这次答疑中,希望通过深度分析 epoll 的源码实现,帮你理解 epoll 的实现原理。epoll 维护了一棵红黑树来跟踪所有待检测的文件描述字,黑红树的使用减少了内核和用户空间大量的数据拷贝和内存分配,大大提高了性能。原创 2023-10-21 23:02:12 · 53 阅读 · 0 评论 -
30 | 真正的大杀器:异步I/O探索
和同步 I/O 相比,异步 I/O 的读写动作由内核自动完成,不过,在 Linux 下目前仅仅支持简单的基于本地文件的 aio 异步操作,这也使得我们在编写高性能网络程序时,首选 Reactor 模式,借助 epoll 这样的 I/O 分发技术完成开发;而 Windows 下的 IOCP 则是一种异步 I/O 的技术,并由此产生了和 Reactor 齐名的 Proactor 模式,借助这种模式,可以完成 Windows 下高性能网络程序设计。原创 2023-10-21 23:01:25 · 97 阅读 · 0 评论 -
29 | 渐入佳境:使用epoll和多线程模型
本讲我们将程序框架切换到了 epoll 的版本,和 poll 版本相比,只是底层的框架做了更改,上层应用程序不用做任何修改,这也是程序框架强大的地方。和 poll 相比,epoll 从事件集合和就绪列表两个方面加强了程序性能,是 Linux 下高性能网络程序的首选。原创 2023-10-21 23:00:29 · 354 阅读 · 0 评论 -
28 | I/O多路复用进阶:子线程使用poll处理连接I/O事件
本讲主要讲述了主从 reactor 模式,主从 reactor 模式中,主 reactor 只负责连接建立的处理,而把已连接套接字的 I/O 事件分发交给从 reactor 线程处理,这大大提高了客户端连接的处理能力。从 Netty 的实现上来看,也遵循了这一原则。原创 2023-10-21 20:54:17 · 57 阅读 · 0 评论 -
27 | I/O多路复用遇上线程:使用poll单线程处理所有I/O事件
这一讲我们总结了几种不同的 I/O 模型和线程模型设计,并比较了各自不同的优缺点。从这一讲开始,我们将使用自己编写的编程框架来完成业务开发,这一讲使用了 poll 来处理所有的 I/O 事件,在下一讲里,我们将会看到如何把 acceptor 的连接事件和已连接套接字的 I/O 事件交由不同的线程处理,而这个分离,不过是在应用程序层简单的参数配置而已。原创 2023-10-21 19:39:05 · 64 阅读 · 0 评论 -
26 | 使用阻塞I/O和线程模型:换一种轻量的方式
这一讲,我们使用了线程来构建服务器端程序。一种是每次动态创建线程,另一种是使用线程池提高效率。和进程相比,线程的语义更轻量,使用的场景也更多。线程是高性能网络服务器必须掌握的核心知识,希望能够通过本讲的学习,牢牢掌握它。原创 2023-10-21 19:37:28 · 53 阅读 · 0 评论 -
25 | 使用阻塞I/O和进程模型:最传统的方式
使用阻塞 I/O 和进程模型,为每一个连接创建一个独立的子进程来进行服务,是一个非常简单有效的实现方式,这种方式可能很难满足高性能程序的需求,但好处在于实现简单。在实现这样的程序时,我们需要注意两点:要注意对套接字的关闭梳理;要注意对子进程进行回收,避免产生不必要的僵尸进程。原创 2023-10-21 19:36:32 · 55 阅读 · 0 评论 -
24 | C10K问题:高并发模型设计
支持单机 1 万并发的问题被称为 C10K 问题,为了解决 C10K 问题,需要重点考虑两个方面的问题:如何和操作系统配合,感知 I/O 事件的发生?如何分配和使用进程、线程资源来服务上万个连接?基于这些组合,产生了一些通用的解决方法,在 Linux 下,解决高性能问题的利器是非阻塞 I/O 加上 epoll 机制,再利用多线程能力。原创 2023-10-21 19:35:25 · 99 阅读 · 0 评论 -
23 | Linux利器:epoll的前世今生
Linux 中 epoll 的出现,为高性能网络编程补齐了最后一块拼图。epoll 通过改进的接口设计,避免了用户态 - 内核态频繁的数据拷贝,大大提高了系统性能。在使用 epoll 的时候,我们一定要理解条件触发和边缘触发两种模式。条件触发的意思是只要满足事件的条件,比如有数据需要读,就一直不断地把这个事件传递给用户;而边缘触发的意思是只有第一次满足条件的时候才触发,之后就不会再传递同样的事件了。原创 2023-10-21 19:33:48 · 105 阅读 · 0 评论 -
22 | 非阻塞I/O:提升性能的加速器
非阻塞 I/O 可以使用在 read、write、accept、connect 等多种不同的场景,在非阻塞 I/O 下,使用轮询的方式引起 CPU 占用率高,所以一般将非阻塞 I/O 和 I/O 多路复用技术 select、poll 等搭配使用,在非阻塞 I/O 事件发生时,再调用对应事件的处理函数。这种方式,极大地提高了程序的健壮性和稳定性,是 Linux 下高性能网络编程的首选。原创 2023-10-21 19:33:02 · 106 阅读 · 0 评论 -
21 | poll:另一种I/O多路复用
poll 是除了 select 之外,另一种普遍使用的 I/O 多路复用技术,和 select 相比,它和内核交互的数据结构有所变化,另外,也突破了文件描述符的个数限制。返回值:若有就绪描述符则为其数目,若超时则为0,若出错则为-1这个函数里面输入了三个参数,第一个参数是一个 pollfd 的数组。int fd;原创 2023-10-21 07:15:07 · 54 阅读 · 0 评论 -
20 | 大名⿍⿍的select:看我如何同时感知多个I/O事件
在第 11 讲中,我们设计了这样一个应用程序,该程序从标准输入接收数据输入,然后通过套接字发送出去,同时,该程序也通过套接字接收对方发送的数据流。我们可以使用 fgets 方法等待标准输入,但是一旦这样做,就没有办法在套接字有数据的时候读出数据;我们也可以使用 read 方法等待套接字有数据返回,但是这样做,也没有办法在标准输入有数据的情况下,读入数据并发送给对方。I/O 多路复用的设计初衷就是解决这样的场景。原创 2023-10-20 21:12:49 · 63 阅读 · 0 评论 -
编写程序
在读出客户端的命令之后,就进入处理环节。这里,为了显得稍微不一样,通过了 popen 的方法,执行了 ls 的 bash 命令,把 bash 命令的结果通过文件字节流的方式读出,再将该字节流通过套接字传给客户端。客户端的代码主要考虑的是使用 select 同时处理标准输入和套接字,我看到有同学使用 fgets 来循环等待用户输入,然后再把输入的命令通过套接字发送出去,当然也是可以正常工作的,只不过不能及时响应来自服务端的命令结果,所以,我还是推荐使用 select 来同时处理标准输入和套接字。原创 2023-10-20 21:12:16 · 56 阅读 · 0 评论 -
19丨提高篇答疑:如何理解TCP四次挥手?
在大多数情况下,这是由应用进程调用 close 而发生的,值得注意的是,一个进程无论是正常退出(exit 或者 main 函数返回),还是非正常退出(比如,收到 SIGKILL 信号关闭,就是我们常常干的 kill -9),所有该进程打开的描述符都会被系统关闭,这也导致 TCP 描述符对应的连接上发出一个 FIN 包。设计良好的程序,在 128 固定值的情况下也是可以支持成千上万的并发连接的,这取决于 I/O 分发的效率,以及多线程程序的设计。在后面的性能篇里,我们的目标就是设计这样的程序。原创 2023-10-20 21:11:26 · 44 阅读 · 0 评论 -
18 | 防人之心不可无:检查数据的有效性
总结一下: 在网络编程中,是否做好了对各种异常边界的检测,将决定我们的程序在恶劣情况下的稳定性,所以,我们一定要时刻提醒自己做好应对各种复杂情况的准备,这里的异常情况包括缓冲区溢出、指针错误、连接超时检测等。原创 2023-10-20 20:51:22 · 53 阅读 · 0 评论 -
17 | TCP并不总是“可靠”的?
在实际情景中,我们会碰到各种异常的情况。在这里我把这几种异常情况归结为两大类:第一类,是对端无 FIN 包发送出来的情况;第二类是对端有 FIN 包发送出来。而这两大类情况又可以根据应用程序的场景细分,接下来我们详细讨论。在这一讲中,我们意识到 TCP 并不是那么“可靠”的。我把故障分为两大类,一类是对端无 FIN 包,需要通过巡检或超时来发现;另一类是对端有 FIN 包发出,需要通过增强 read 或 write 操作的异常处理,帮助我们发现此类异常。原创 2023-10-20 20:27:54 · 137 阅读 · 0 评论 -
16 | 如何理解TCP的“流”?
和我们预想的不太一样,TCP 数据流特性决定了字节流本身是没有边界的,一般我们通过显式编码报文长度的方式,以及选取特殊字符区分报文边界的方式来进行报文格式的设计。而对报文解析的工作就是要在知道报文格式的情况下,有效地对报文信息进行还原。原创 2023-10-20 18:47:35 · 296 阅读 · 0 评论 -
15 | 怎么老是出现“地址已经被使用”?
今天我们分析了“Address already in use”产生的原因和解决方法。只要记住一句话,在所有 TCP 服务器程序中,调用 bind 之前请设置 SO_REUSEADDR 套接字选项。这不会产生危害,相反,它会帮助我们在很快时间内重启服务端程序,而这一点恰恰是很多场景所需要的。原创 2023-10-20 18:04:53 · 690 阅读 · 0 评论 -
14丨UDP也可以是“已连接”?
在今天的内容里,我对 UDP 套接字调用 connect 方法进行了深入的分析。之所以对 UDP 使用 connect,绑定本地地址和端口,是为了让我们的程序可以快速获取异步错误信息的通知,同时也可以获得一定性能上的提升。原创 2023-10-20 17:21:59 · 73 阅读 · 0 评论 -
13 | 小数据包应对之策:理解TCP协议中的动态数据传输
今天的内容我重点讲述了 TCP 流量控制的生产者 - 消费者模型,需要记住以下几点:发送窗口用来控制发送和接收端的流量;阻塞窗口用来控制多条连接公平使用的有限带宽。小数据包加剧了网络带宽的浪费,为了解决这个问题,引入了如 Nagle 算法、延时 ACK 等机制。在程序设计层面,不要多次频繁地发送小报文,如果有,可以使用 writev 批量发送。原创 2023-10-20 14:49:35 · 130 阅读 · 0 评论 -
12 | 连接无效:使用Keep-Alive还是应用心跳来检测?
通过今天的文章,我们能看到虽然 TCP 没有提供系统的保活能力,让应用程序可以方便地感知连接的存活,但是,我们可以在应用程序里灵活地建立这种机制。一般来说,这种机制的建立依赖于系统定时器,以及恰当的应用层报文协议。比如,使用心跳包就是这样一种保持 Keep Alive 的机制。原创 2023-10-20 14:07:34 · 170 阅读 · 0 评论 -
11 | 优雅地关闭还是粗暴地关闭 ?
在这一讲中,我们讲述了 close 函数关闭连接的方法,使用 close 函数关闭连接有两个需要明确的地方。close 函数只是把套接字引用计数减 1,未必会立即关闭连接;close 函数如果在套接字引用计数达到 0 时,立即终止读和写两个方向的数据传送。基于这两点,在期望关闭连接其中一个方向时,应该使用 shutdown 函数。原创 2023-10-20 11:50:33 · 57 阅读 · 0 评论 -
10 | TIME_WAIT:隐藏在细节下的魔鬼
在今天的内容里,我讲了 TCP 的四次挥手,重点对 TIME_WAIT 的产生、作用以及优化进行了讲解,需要记住以下三点:TIME_WAIT 的引入是为了让 TCP 报文得以自然消失,同时为了让被动关闭方能够正常关闭;不要试图使用SO_LINGER设置套接字选项,跳过 TIME_WAIT;现代 Linux 系统引入了更安全可控的方案,可以帮助我们尽可能地复用 TIME_WAIT 状态的连接。原创 2023-10-20 11:24:53 · 49 阅读 · 0 评论 -
09丨答疑篇:学习网络编程前,需要准备哪些东西?
接下来轮到 TCP 协议栈工作,创建 Packet 报文,并把报文发送到传输队列中(qdisc),传输队列是一个典型的 FIFO 队列,队列的最大值可以通过 ifconfig 命令输出的 txqueuelen 来查看。接下来再看接收端,报文首先到达网卡,由网卡保存在自己的接收缓存中,接下来报文被发送至网络驱动和网卡之间的 RX ring,网络驱动从 RX ring 获取报文 ,然后把报文发送到上层。既然希望通过学习,可以进行网络编程实战,那么就得有一个环境,可以运行文章中的例子,并加以活学活用。原创 2023-10-20 10:39:51 · 61 阅读 · 0 评论 -
08 | 工欲善其事必先利其器:学会使用各种工具
上一讲我们讲到了本地套接字,加上前面介绍的 TCP、UDP 套接字,你会发现我们已经比较全面地接触了套接字。其实在平常使用套接字开发和测试过程中,我们总会碰到这样或那样的问题。学会对这些问题进行诊断和分析,其实需要不断地积累经验。而 Linux 平台下提供的各种网络工具,则为我们进行诊断分析提供了很好的帮助。在这一讲里,我将会选择几个重点的工具逐一介绍。原创 2023-10-20 09:48:02 · 57 阅读 · 0 评论 -
07 | What? 还有本地套接字?
本地套接字一般也叫做 UNIX 域套接字,最新的规范已经改叫本地套接字。在前面的 TCP/UDP 例子中,我们经常使用 127.0.0.1 完成客户端进程和服务器端进程同时在本机上的通信,那么,这里的本地套接字又是什么呢?本地套接字是一种特殊类型的套接字,和 TCP/UDP 套接字不同。TCP/UDP 即使在本地地址通信,也要走系统网络协议栈,而本地套接字,严格意义上说提供了一种单主机跨进程间调用的手段,减少了协议栈实现的复杂度,效率比 TCP/UDP 套接字都要高许多。原创 2023-10-20 09:14:23 · 62 阅读 · 0 评论 -
06 | 嗨,别忘了UDP这个小兄弟
在这一讲里,我介绍了 UDP 程序的例子,我们需要重点关注以下两点:UDP 是无连接的数据报程序,和 TCP 不同,不需要三次握手建立一条连接。UDP 程序通过 recvfrom 和 sendto 函数直接收发数据报报文。原创 2023-10-19 23:59:16 · 66 阅读 · 0 评论 -
05 | 使用套接字进行读写:开始交流吧
这一讲重点讲述了通过 send 和 read 来收发数据包,你需要牢记以下两点:对于 send 来说,返回成功仅仅表示数据写到发送缓冲区成功,并不表示对端已经成功收到。对于 read 来说,需要循环读取数据,并且需要考虑 EOF 等异常条件。原创 2023-10-19 23:43:33 · 83 阅读 · 0 评论 -
04 | TCP三次握手:怎么使用套接字格式建立连接?
这一讲我们分别从服务端和客户端的角度,讲述了如何创建套接字,并利用套接字完成 TCP 连接的建立。服务器端通过创建 socket,bind,listen 完成初始化,通过 accept 完成连接的建立。客户端通过创建 socket,connect 发起连接建立请求。在下一讲里,我们将真正地开始客户端 - 服务端数据交互的过程。原创 2023-10-19 23:32:53 · 168 阅读 · 0 评论 -
03丨套接字和地址:像电话和电话号码一样理解它们
这一讲我们重点讲述了什么是套接字,以及对应的套接字地址格式。套接字作为网络编程的基础,概念异常重要。套接字的设计为我们打开了网络编程的大门,实际上,正是因为 BSD 套接字如此成功,各大 Unix 厂商(包括开源的 Linux)以及 Windows 平台才会很快照搬了过来。在下一讲中,我们将开始创建并使用套接字,建立连接,进一步开始我们的网络编程之旅。原创 2023-10-19 23:15:38 · 98 阅读 · 0 评论 -
02 | 网络编程模型:认识客户端-服务器网络模型的基本概念
这一讲我们主要介绍了客户端 - 服务器网络编程模型,初步介绍了 IP 地址、端口、子网掩码和域名等基础概念,以下知识点你需要重点关注一下:网络编程需要牢牢建立起“客户端”和“服务器”模型,两者编程的方法和框架是明显不同的。TCP 连接是客户端 - 服务器的 IP 和端口四元组唯一确定的,IP 是一台机器在网络世界的唯一标识。有两种截然不同的传输层协议,面向连接的“数据流”协议 TCP,以及无连接的“数据报”协议 UDP。从下一讲开始,我们将开始使用套接字编写我们的第一个客户端 - 服务器程序。原创 2023-10-19 17:00:25 · 156 阅读 · 0 评论 -
01 | 追古溯源:TCP/IP和Linux是如何改变世界的?
我们正处于一个属于我们的时代里,我们也正在第一线享受着这个时代的红利。在我看来,人类历史上还从来没有一项技术可以像互联网一样深刻地影响人们生活的方方面面。而具体到互联网技术里,有两件事最为重要,一个是 TCP/IP 协议,它是万物互联的事实标准;另一个是 Linux 操作系统,它是推动互联网技术走向繁荣的基石。今天,我就带你穿越时间的走廊,看一看 TCP/IP 事实标准和 Linux 操作系统是如何一步一步发展到今天的。原创 2023-10-19 14:13:26 · 105 阅读 · 0 评论