Acceptor 用于 accept 一个 TCP 连接,accept 接受成功后通知 TCP 连接的使用者。Acceptor 主要是供 TcpServer 使用的,其生命期由后者控制。一个 Acceptor 相当于持有服务端的一个 socket 描述符,该 socket 可以 accept 多个 TCP 客户连接,这个 accept 操作就是 Acceptor 实现的。 这里用到了一些封装好的 socket 和地址结构,如 class InetAddress 表示 sockaddr_in 的封装,如可以通过ip地址和port端口生成一个sockaddr_in; class Socket封装了部分关于socket套接字的操作,如Socket::bindAddress(InetAddress&) 将socket和一个sockaddr_in地址绑定,Socket::accept(InetAddress& peerAddr)将一个socket允许连接一个客户端地址peerAddr,Socket::listen()监听socket,Socket::shutdownWrite 继续阅读 >>


杜肖孟 18/01/12 22:43:03
主要涉及到的类和实现文件有: Endian.h 提供了字节序转换的函数。 Socket.h/Socket.cc socketfd 的封装,提供了绑定地址、开始listen、接受连接等操作,并可设置套接字选项。 InetAddress.h/InetAddress.cc 套接字地址的封装,提供了多种方式初始化一个地址,还提供方法从地址中拿到 ip 和 port。 SocketsOps.h/SocketsOps.cc 封装了 socket 相关的一些操作,提供给 Socket 和 InetAddress 用。 这部分就是基本的 TCP 套接字编程和套接字选项的知识,代码逻辑也很简单,推荐看下 UNP卷一 的相关章节。 下面逐一看下这几个相关的文件。 字节序转换部分(Endian.h) #ifndef MUDUO_NET_ENDIAN_H #define MUDUO_NET_ENDIAN_H #include <stdint.h> #include <endian.h> namespace muduo { namespace net { na 继续阅读 >>


杜肖孟 18/01/09 15:14:11
muduo 的定时器功能由三个 class 实现,TimerId、Timer 和 TimerQueue。 TimerId 类 它唯一标识一个 Timer 定时器。TimerId Class 同时保存Timer* 和 sequence_,这个 sequence_ 是每个 Timer 对象有一个全局递增的序列号 int64_t sequence_,用原子计数器(AtomicInt64)生成。 它主要用于注销定时器,这样就可以区分地址相同的先后两个 Timer 对象。 namespace muduo { namespace net { class Timer; /// /// An opaque identifier, for canceling Timer. /// /* 带有唯一标识的Timer,主要用于取消Timer */ class TimerId : public muduo::copyable { public: TimerId() : timer_(NULL), sequence_(0) { } TimerId(Timer* 继续阅读 >>


杜肖孟 18/01/07 15:41:05
本文分析一下Reactor模式的实现,关键是三个类:Channel、Poller、EventLoop。 事件分发类 Channel Channel 是 selectable IO channel,负责注册与响应IO事件,包括注册给Poller的 fd 及其监听的事件,以及事件发生了所调的回调函数。 每个Channel对象自始至终只负责一个 fd 的事件分发,封装了一系列该 fd 对应的操作,使用了回调函数,包括可读、可写、关闭和错误处理四个。 首先给定Channel所属的 loop,及其要处理的 fd;接着注册 fd 上需要监听的事件,如果是常用的读写事件的话,可以直接调用接口函数enableReading或enableWriting来注册对应fd上的事件,disable*是销毁指定的事件;然后通过 set*Callback 来设置事件发生时的回调。 注册事件时函数调用关系,如下:Channel::update()->EventLoop::updateChannel(Channel*)->Poller::updateChannel(Channel*),最终向 继续阅读 >>


杜肖孟 18/01/06 18:36:02
(1)网络应用程序体系结构: 1、客户——服务器结构:这个结构的话就是服务器是中心,客户与中心服务器连接。客户端之间不会相互通信,并且服务器有一个固定的公共的IP地址。 2、p2p结构:(这个结构与客户——服务器结构的区别就是在这个结构中不存在中心服务器)括号里是我自己写出的P2P结构的理解,是错误的,实际上,在P2P结构中客户端对位于中心的服务器依赖很小甚至没有依赖,客户端和客户端是可以相互通信的,像树的分支一样。位于中心的服务器用于追踪用户的IP地址。 (2)进程间通信: 1、套接字:进程通过套接字向网络发送接收报文。在同一台主机内:套接字是应用层和网络层之间的接口,套接字也称为应用程序和网络之间的应用程序编程接口, 2、进程寻址:为了找到接收进程,我们需要两个信息:目的主机的地址和目的主机上接收进程的标识符。前者可以运用IP地址,而后者可以运用目的端口号。 3、应用层协议将为应用程序提供服务,那么提供服务可以按四个要求来讨论:可靠传输,吞吐量,定时,安全性: <1>可靠传输:可靠传输就是保证数据可以完整并且无差错的到达接收方 <2>吞吐量: 继续阅读 >>


梁梦迪 17/12/26 21:53:55
cookie AND session 首先cookie是用来标识用户身份以及追踪用户状态的,下面我用自己的话来描述一下cookie的工作流程~ 某一天,mendy第一次登录baidu这个网站。Baidu发现mendy是第一次登录,于是baidu会创建一个唯一的标识码给mendy,同时baidu会以这个标识码作为索引将标识码添加到后端的数据库中(这个标识码可能是cookie:1008),接下来,baidu会在http response中添加set-cookie:cookie:1008返回给mendy的浏览器。mendy的浏览器会将这个cookie信息添加到它的cookie文件中,下次mendy再一次访问baidu的时候,会从cookie文件中找到对应的cookie信息添加到http请求报文中发送给baidu服务器,(cookie包括过期时间,路径,域,名字,值。如果不设置cookie的过期时间,默认过期时间是浏览器的会话期间。如果不设置过期时间,cookie是存储在内存中的,如果设置了过期时间,cookie就会存储在硬盘上直到过期为止.cookie的范围就是路径+域,如果某个cook 继续阅读 >>


梁梦迪 17/12/26 21:53:16
…. 1、先来回忆一下因特网网络层最基本的概念,采用自上而下的结构 (1)应用层 应用程序及应用层协议所在的位置(HTTP,FTP),位于这一层的分组叫报文 (2)运输层 应用层产生的报文到了这层,运输层给上一层的报文加上运输层头部(允许接收端的运输层向上一层应用程序交付报文信息,差错控制信息,在应用程序两个端点间传输) (3)网络层 运输层产生的报文段在这一层加上网络层头信息,包括目的地和源的地址,这一层产生的分组叫数据报文(从一台主机移动到另一台主机,完成这一层还需要链路层的帮助)。 (4)链路层 这一层的作用主要是运输,大概过程就是,网络的一个节点将数据报文传递给链路层,链路层再将该数据报文传送给网络层的另一个节点。这一层产生的分组叫帧。(将一个帧从一个网络元素移动到另一个网络元素) (5)物理层 这一层主要就是一些物理媒介。(将帧中的每一个比特从一个节点移动到下一个节点)。 2、网络中的网络 网络中的网络说白了我觉得就是ISP的互联…… (1)网络结构1: 有一个全球承载ISP,所有的接入ISP都连接在全球承载ISP上。这样做就实现了ISP互联了 继续阅读 >>


梁梦迪 17/12/26 21:51:48
1、什么是因特网? 我们平时使用的电脑,手机都可以称为端系统。因特网就是利用路由器(分组交换机)和链路将各个终端互联起来。 2、一些基本概念 (1)分组: 一个主机要向另外一个主机发送数据时,数据被分成很多段,每段前面还会加上特定的首部字节,这样的数据包就称为分组。 (2)因特网服务提供商(ISP): 主机就是通过ISP连接进互联网的,。ISP是一个由多个分组交换机和段通信链路组成的网络。各ISP都是互联的,初级ISP由高级国家ISP互联,高级ISP通过高速光纤链路互联的高速路由器组成.看了第一章后面的部分,其实ISP提供的主要服务就是另电脑啊,手机啊这些接入因特网,接入的方法就有下面提到的DSL,电缆,WIFI等等。 3、对因特网的另外一种理解 可以将因特网理解为为应用服务程序提供平台。那么一台主机如何向另外一台主机发送数据呢?这是因为与因特网连接的端系统提供了一个应用程序编程接口(API),该API规定了传输数据的方法,API是发送数据必须遵守的一套规则。 4、什么是协议 协议规定了两个或多个通信实体交换报文的格式和次序,以及一些相关动作。 5、接入网 接入 继续阅读 >>


梁梦迪 17/12/26 21:50:53
G - Coding Contest  HDU - 5988  A coding contest will be held in this university, in a huge playground. The whole playground would be divided into N blocks, and there would be M directed paths linking these blocks. The i-th path goes from the uiui-th block to the vivi-th block. Your task is to solve the lunch issue. According to the arrangement, there are sisi competitors in the i-th block. Limited to the size of table, bibi bags of 继续阅读 >>


楚东方 17/11/28 23:17:48
前言 你以为我鸽了其实我没有鸽,这也算是一种鸽。 继续来填坑啦。 在上两篇中,我们都是使用的链表进行保存定时事件,当我们需要增加一个或者删除一个事件时都需要O(n)的时间复杂度,本篇我们通过时间轮(time wheel)这种数据结构来对其进行优化,而libco也是通过时间轮来进行处理的,所以就拿着它的代码来讲啦。 正文 Libco的作为一个协程库,相当于在用户态完成了逻辑流的切换,这里的调度便是一旦遇到阻塞的系统调用(如read)时,将其注册到epoll_wait中并切换逻辑流,等待其I/O事件的到达,一旦到达则进行处理,将同步阻塞I/O换成了I/O多路复用。 而这里便是将I/O事件当作定时事件来处理,将I/O事件设置超时事件,如果超时则直接处理,避免一直等待的情况。 libco管理定时事件便是使用时间轮这种数据结构,通过一种hash的思想使得添加定时事件的时间复杂度降到O(1),大大提高了效率。 我们先来看看时间轮是怎样的东西。 时间轮是个啥 在之前我们通过链表,按照超时时间进行升序或者降序的排列,这样添加事件就需要O(N)的时间复 继续阅读 >>


康艺杰 17/11/09 22:19:30