三次握手过程中 TCP 的状态变化 三次握手的过程和本质 三种状态 socket 函数 listen 函数 connect 函数 accept 函数 值-结果参数 connect 函数在三次握手中的返回情况 总结一下近日所学的关于 TCP 建立连接 三次握手 的过程中, TCP 的 状态变化, 以及在这个过程中所用的 socket 函数, 对于各种情况会如何处理 涉及到 connect listen accept 函数 三次握手过程中 TCP 的状态变化 三次握手的过程和本质 如下图, 是一个 TCP 建立和断开连接的过程, 我们今天只讨论建立连接的三次握手过程 主动申请连接的一方(通常为客户端), 发送一个 SYN 报文段, 服务器在收到客户端发来的 SYN 报文段后, 回复一个 SYN 报文段, 并发送一个 ACK 以确认客户端的 SYN, 为了确认服务器的 SYN, 客户端也会回复一个 ACK 经 继续阅读 >>


吕子健 18/09/04 14:58:46
I/O多路复用的理解 先讲一个大家都比较熟悉的例子吧 小时候咱们都喜欢看《亮剑》、《雪豹》这一类的抗日剧,里面八路军在自己的驻地周围都会24小时分布一些暗哨,每当有鬼子要进行扫荡或者清剿的时候暗哨就会赶紧告诉驻地的八路军,有敌人过来了,赶紧抄家伙干仗了。其实这就和咱们要讲的I/O多路复用有异曲同工之处。 在我们接触I/O多路复用以前,在处理一些比较多的连接或者请求的时候大多数人会去使用类似下面这种方式去处理: while(1) { int cli_fd = accept(listen_fd, (struct sockaddr*)&addrCli, sizeof(addrCli)); ...../*开启一个线程或者开启一个进程*/ } 这么做看着十分的清爽,而且实现起来也相当的简单,但是服务器的主程序会一直阻塞在accept这个函数上,然后会一直去等待connect的到来,这种方法虽然十分的简单,但是在轮询的过程中耗费了大量的CPU时间,并且效率还十分的低下,因此我们要想 继续阅读 >>


李佳灏 18/08/14 16:27:10
信号是由用户、系统或者进程发送给目标进程的信息,用来通知目标进程的状态改变或系统异常。 发送信号 kill #include <sys/types.h> #include <signal.h> int kill(pid_t pid, int sig); 该函数可以把sig信号发送给pid指定的目标进程 pid 参数 含义 pid > 0 信号发送给PID为pid的进程 pid = 0 信号发送给本进程组内的其他进程 pid = -1 信号发送给除init进程外的所有进程,但发送者需要拥有对目标发送信号的权限 pid < -1 信号发送给组ID为-pid的进程组中的所有成员 特别的如果sig为0的时候,kill函数不发送任何信号。 kill函数成功时返回0,失败返回-1,并设置errno errno 含义 EINVAL 无效的信号 EPERM 继续阅读 >>


李佳灏 18/08/13 15:26:36
生产者——消费者模型顾名思义,就是一个或多个线程往仓库生产东西,另外的线程从仓库拿东西,在咱们的线程池中也有所应用。咱们看看维基的解释: 生产者消费者问题(英语:Producer-consumer problem),也称有限缓冲问题(英语:Bounded-buffer problem),是一个多线程同步问题的经典案例。该问题描述了共享固定大小缓冲区的两个线程——即所谓的“生产者”和“消费者”——在实际运行时会发生的问题。生产者的主要作用是生成一定量的数据放到缓冲区中,然后重复此过程。与此同时,消费者也在缓冲区消耗这些数据。该问题的关键就是要保证生产者不会在缓冲区满时加入数据,消费者也不会在缓冲区中空时消耗数据。 说了这么多,大家还是有点晕乎乎的,咱们看代码吧 #include<stdio.h> #include<unistd.h> #include<string.h> #include<pthread.h> //1 : 1 #defi 继续阅读 >>


李佳灏 18/08/13 08:34:37
特点 Linux 内核于内核2.6.25提供了一种创建定时器的 API, 那就是 Linux 特有的 timerfd API, 并且该定时器可以从文件描述符中读取其创建的定时器到期通知. 这也意味着, 可以将文件描述符通过多路复用监听并读取, 而其他的定时器想要将一个 (或多个) 定时器与一组文件描述符放在一起同时监听可不是一件容易的事. 函数接口 timerfd 系列 API 有三个系统调用 : 第一个系统调用, 该系统调用创建一个新的定时器对象 : #include <sys/timerfd.h> int timerfd_create(int clockid, int flags); //成功返回一个指代该对象的文件描述符, 失败返回-1及errno 第一个参数 clockid 可以设置为 CLOCK_REALTIME 和 CLOCK_MONOTONIC CLOCK_REALTIME 可设定的系统级实时时钟. 相对时间,从1970. 继续阅读 >>


吕子健 18/08/10 22:26:11
介绍 时间轮顾名思义,就是将不同时间的定时任务放在一个轮子上,既然是轮子,肯定是会转动的,时间轮内指向槽的指针,以恒定的速度顺时针转动,每转动一步就指向下一个槽。,一次转动称为一次滴答(tick)。一个滴答的时间称为时间轮的槽间隔si,也就是心搏时间。一个时间轮若有N个槽,在它运转一周的时间是N * si。同一个槽上的定时器它们的定时时间相差N * si的整数倍。 对于时间轮来说,要提高精度,就要使si值足够小;要提高执行效率,则要求N值足够大。如图所示: 由图可知定时器在时间轮的槽上是以链表的形式存储的(双向链表),并且相同一条链(也就是同一个槽)上的定时器:它们的定时时间相差N*si的整数倍。时间轮就是利用这个关系将定时器散列到不同的链中。在插入槽中的时候采用的是头插的方法,这样可以减少不必要的遍历时间。但是正是因为一股脑的头插(无序),也造成了在我们每次转动的时候都不得不去遍历一遍链表。 对于时间轮来说,添加一个定时器的时间复杂度为O(1),删除一个定时器的时间复杂度也是O(1),执行一 继续阅读 >>


李佳灏 18/08/09 16:49:07
选择gettimeofday()函数的原因:精度比timer()函数高很多,time函数只精确到秒,而gettimeofday精确到微妙,足以满足各种所需,虽然有精度比它更高的,但是它的系统调用开销相对更小 函数原型 #include<sys/time.h> int gettimeofday(struct timeval* tv, struct timezone* tz); 成功返回0, 失败返回-1, 出错返回errno 参数意义 tv是指向下面这个结构体的一个指针 struct timeval { time_t tv_sec; suseconds_t tv_usec; } time_t 和suseconds_t 都是lont int 类型, tv_sec 表示Epoch 秒数, 而tv_usec 是额外的微妙精度 tz 是一个历史产物, 早期的UNIX实现用来获取系统的时区信息, 目前已经被废弃了, 应始终将其置为NULL. 继续阅读 >>


吕子健 18/08/03 17:16:10
在《Linux高性能服务器编程》一书中为了帮助大家将书中的知识融汇到实际项目中,作者特意编写了一个较为完整的负载均衡服务器程序springsnail。里面用到了进程池、有限状态机这些知识点。自己是在网上找到的这个程序的源码,起初接触的时候,总共1400多行代码里面没有一行注释,网上也没有一篇博客去对这个项目进行解析,因此写这篇博客供大家一起分享学习。springsnail源码(带注释) 咱们从main函数开始,我们要介绍几个c语言中的两个宏 __FILE__:用以指示本行语句所在源文件的文件名 __LINE__:用以指示本行语句在源文件中的位置信息 这两个参数在后面咱们程序的调试中有着非常正要的作用。并且整个程序的日志系统也是依靠这两个宏和可变参的log()函数完成的。 接着大家需要了解getopt函数这个函数可以通过提取命令行参数对命令行参数进行解析。 接着后面是解析xml文件的一长串代码 vector< host > balance_srv; 继续阅读 >>


李佳灏 18/08/02 12:33:17
   前言,记得某一次开会的时候,学长学姐就说过让我们去看fork源码,结果一直没有时间去看(其实是懒),这不,正好碰上这次开进程的讲座,就在讲座之前看了一波源码,也算是了了一波自己阅读源码的心愿 。   首先我们得基本了解一下,task_struct 与 thread_info结构是怎么一回事。 1. linux中的PCB的实体(task_struct) 其实标题已经说的很清楚了。它就是我们常说的进程控制块。 PCB通常记载进程之相关信息,包括: 进程状态:可以是new、ready、running、waiting或 blocked等。 程序计数器:接着要运行的指令地址。 CPU寄存器:如累加器、变址寄存器、堆栈指针以及一般用途寄存器、状况代码等, 主要用途在于中断时暂时存储数据,以便稍后继续利用;其数量及类别因计算机体系结构有所差异。 CPU排班法:优先级、排班队列等指针以及其他参数。 存储器管理:如标签页表等。 会计信息:如CPU与实际时间之使用数量、 继续阅读 >>


刘生玺 18/08/01 17:21:40
关于mysql的基础知识可以参考 mysql基础 首先,需要确保已安装mysql-server,mysql-client,mysql-devel。 一、常用类型介绍 1. MYSQL 用于定义一个mysql对象,便于后续操作确定要操作的数据库是哪一个。 MYSQL mysql; //mysql标记对应某个数据库 2. MYSQL_ROW 用于定义一个行对象,其内容含有一行的数据。 MYSQL_ROW row; //row[i]可用于输出该行第i个字段的数据 3. MYSQL_FIELD 用于定义一个存储字段信息的对象。 MYSQL_FIELD *field; //field->name存储对应字段名称 4. MYSQL_RES 用于定义一个存储数据库检索信息结果的对象。 MYSQL_RES *result; 二、常用函数介绍 其实在操作mysql数据库时,最常使用的函数有以下几个: 1. mysql_init() 用于初始化 继续阅读 >>


王良 18/07/21 15:29:35