1、epoll_create函数
  函数声明:int epoll_create(int size)
  该
函数生成一个epoll专用的文件描述符。它其实是在内核申请一空间,用来存放你想关注的socket
fd上是否发生以及发生了什么事件。size就是你在这个epoll fd上能关注的最大socket
fd数。随你定好了,前提是有足够的空间。

2. socket 函数

  函数原型 int socket(int domain, int type, int protocol);
  应用程序调用socket函数来创建一个能够进行网络通信的套接字,即套接口描述文件字,它是一个整数,如同文件描述符一样,是内核一个I/O结构的索引。通过socket函数,我们指定一个套接口的协议相关的属性, 为进行使用socket api做好准备。
   第一个参数指定一个协议簇,也往往被称为协议域。系统存在许多可以的协议簇,常见有AF_INET──指定为IPv4协议,AF_INET6──指定为 IPv6,AF_LOCAL──指定为UNIX 协议域等等。它值都是系统预先定义的宏,系统支持哪些协议我们才可以使用,否则会调用失败。协议簇是网络层的协议。
  
第二个参数指定一个套接口的类型,套接口可能的类型有:SOCK_STREAM、SOCK_DGRAM、SOCK_SEQPACKET、SOCK_RAW等等,它们 分别表明字节流、数据报、有序分组、原始套接口。这实际上是指定内核为我们提供的服务抽象,比如我们要一个字节流。需要注意的,并不是每一种协议簇都支持 这里的所有的类型,所以类型与协议簇要匹配。;
  第三个参数指定应用程序所使用的传输协议,也就是诸如TCP或UDP协议等等,系统针对每一个协议簇与类型提供了一个默认的协议,通常我们通过把protocol设置为0来使用这 个默认的值。注意这里的协议与上面的协议簇是两个不同的概念,前者是指网络层的协议,由于它对于到传输层会出现许多协议,比如IPv4可以用来实现TCP 或UDP等等传输层协议,所以称为协议簇。相应的传输层的协议就简单地称为协议。常见的协议有TCP、UDP、SCTP,要指定它们分别使用宏 IPPROTO_TCP、IPPROTO_UPD、IPPROTO_SCTP来指定。

  该函数如果调用成功就返回新创建的套接字的描述符,如果失败就返回
INVALID_SOCKET。套接字描述符是一个整数类型的值。每个进程的进程空间里都有一个套接字描述符表,该表中存放着套接字描述符和套接字数据结
构的对应关系。该表中有一个字段存放新创建的套接字的描述符,另一个字段存放套接字数据结构的地址,因此根据套接字描述符就可以找到其对应的套接字数据结构。每个进程在自己的进程空间里都有一个套接字描述符表但是套接字数据结构都是在操作系统的内核缓冲里。

3.  fcntl函数

  函数原型:

  #include <unistd.h>
  #include <fcntl.h>
  int fcntl(int fd, int cmd);
  int fcntl(int fd, int cmd, long arg);
  int fcntl(int fd, int cmd, struct flock *lock);

  功能:改变一个已打开的文件的属性,可以重新设置读、写、追加、非阻塞等标志(这些标志称为File

  这个函数和open 一样,也是用可变参数实现的,可变参数的类型和个数取决于前面的cmd 参数。

  针对第2个参数,int cmd

  fcntl函数有五种功能:
  • 复制一个现存的描述符(cmd=F_DUPFD)    。
  • 获得/设置文件描述符标记(cmd=F_GETFD或F_SETFD)   。
  • 获得/设置文件状态标志(cmd=F_GETFL或F_SETFL) 。
  • 获得/设置异步I/O有权(cmd=F_GETOWN或F_SETOWN) 。
  • 获得/设置记录锁(cmd=F_GETLK,F_SETLK或F_SETLKW)。

  将涉及与进程表项中各文件描述符相关联的文件描述符标志, 以及每个文件表项中的文件状态标志,

  一~复制文件描述符
  • F_DUPFD 复制文件描述符filedes,新文件描述符作为函数值返回。它是尚未打开的各
  描述符中大于或等于第三个参数值(取为整型值)中各值的最小值。新描述符与 filedes 共享同
  一文件表项。但是,新描述符有它自己的一套文件描述符标志,其 F D _ C L O E X E C
  文件描述符标志则被清除。
  • F_GETFD 对应于filedes 的文件描述符标志作为函数值返回。当前只定义了一个文件描
  述符标志FD_CLOEXEC。
  • F_SETFD 对于filedes 设置文件描述符标志。新标志值按第三个参数 (取为整型值)设置。
  应当了解很多现存的涉及文件描述符标志的程序并不使用常数 F D _ C L O E X E C,而是将此
  标志设置为0(系统默认,在exec时不关闭)或1(在exec时关闭)。

  二~文件描述符号,套接口 属性相关
  • F_GETFL 对应于filedes 的文件状态标志作为函数值返回。在说明 open函数时,已说明
  了文件状态标志   不幸的是,三个存取方式标志 (O_RDONLY,O_WRONLY,以及O_RDWR)并不各占1位。(正
  如前述,这三种标志的值各是 0、1和2,由于历史原因。这三种值互斥 — 一个文件只能有这
  三种值之一。 )因此首先必须用屏蔽字 O_ACCMODE相与 取得存取方式位,然后将结果与这三种值
  相比较。
  • F_SETFL 将文件状态标志设置为第三个参数的值 (取为整型值)。 可以更改的几个标志是:
  O_APPEND,O_NONBLOCK,O_SYNC和O_ASYNC。

  fcntl的文件状态标志共有7个,O_RDONLY,O_WRONLY,O_RDWR,O_APPEND,O_NONBLOCK,O_SYNC和O_ASYNC

  三~信号驱动I/O , 带外数据,设置套接口接受信号的属主
  SIGIO,跟信号驱动I/O有关
  SIGURG, 和接受带外数据有关
  • F_GETOWN 取当前接收SIGIO和SIGURG信号的进程ID或进程组ID。12.6.2节将论述这
  两种4.3+BSD异步I/O信号。
  • F_SETOWN 设置接收SIGIO和SIGURG信号的进程ID或进程组ID。正的arg指定一个进
  程ID,负的arg表示等于arg绝对值的一个进程组ID

3、epoll_ctl函数
     函数声明:int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event)
    
该函数用于控制某个文件描述符上的事件,可以注册事件,修改事件,删除事件。
    参数:epfd:由 epoll_create 生成的epoll专用的文件描述符;
                op:要进行的操作例如注册事件,可能的取值EPOLL_CTL_ADD 注册、EPOLL_CTL_MOD
                        改、EPOLL_CTL_DEL 删除
                fd:关联的文件描述符;
                event:指向epoll_event的指针;
    如果调用成功返回0,不成功返回-1

4、epoll_wait函数
  函数声明:int epoll_wait(int epfd,struct epoll_event * events,int maxevents,int timeout)
  该函数用于轮询I/O事件的发生;
  参数:
  epfd:由epoll_create 生成的epoll专用的文件描述符;
  epoll_event:用于回传代处理事件的数组;
  maxevents:每次能处理的事件数;
  timeout:等待I/O事件发生的超时值;
    返回发生事件数。

介绍linux下的epoll(7)方法,其有着良好的就绪事件通知机制。我们将会使用C来展现一个完整的TCP服务器实现代码。 Epoll是被linux2.6开始引进的,但是不被其他的类UNIX系统支持,它提供了一种类似select或poll函数的机制:

   1.Select(2)只能够同时管理FD_SETSIZE数目的文件描述符

2. poll(2)没有固定的描述符上限这一限制,但是每次必须遍历所有的描述符来检查就绪的描述符,这个过程的时间复杂度为O(N)。

epoll没有select这样对文件描述符上限的限制,也不会像poll那样进行线性的遍历。因此epoll处理大并发连接有着更高的性能。

    Epoll相关操作函数介绍:

1. epoll_create(2) or epoll_create1(2)(有着不同的参数值)用来创建epoll实例。

/usr/include/sys/epoll.h
extern int epoll_create (int __size) ;
RETURN:>0, 成功;-1, 出错

函数描述:

(1) epoll_create返回的是一个文件描述符,也就是说epoll是以特殊文件的方式体现给用户

(2) __size提示操作系统,用户可能要使用多少个文件描述符,该参数已经废弃,填写一个大于0的正整数

2.  epoll_ctl(2)用来增加或移除被epoll所监听的文件描述符。

int epoll_ctl(int epfd, int op, int fd, struct 	epoll_event *event);
RETURN:0,成功;-1,出错

函数描述:

(1) epfd为epoll_create创建的epoll描述符

(2) epoll_ctl函数对epoll进行op类型的操作,op选项为

EPOLL_CTL_ADD,对fd描述符注册event事件

EPOLL_CTL_MOD,对fd描述符的event事件进行修改

EPOLL_CTL_DEL,删除已注册的event事件

3. epoll_wait(2)用来等待发生在监听描述符上的事件。它会一直阻塞直到事件发生。

#include <sys/epoll.h>
int epoll_wait(int epfd, struct epoll_event *events,
int maxevents, int timeout);
RETURN:>0,发生事件个数;=0,时间到;-1,出错

函数描述:

epoll_wait与select函数类似,同步地等待事件发生

(1) epfd,标识epoll的文件描述符

(2) events,指向传入操作系统的一个epoll_event数组

(3) maxevents,表示传入数组的大小,必须大于0

当有事件发生,Linux会填写events结构,返回给应用程序。由于epoll_wait同步等待,有可能被信号中断,返回EINTR错误

更多的函数介绍请参照man。

Epoll的两种模式:

1. 水平触发(LT):使用此种模式,当数据可读的时候,epoll_wait()将会一直返回就绪事件。如果你没有处理完全部数据,并且再次在该 epoll实例上调用epoll_wait()才监听描述符的时候,它将会再次返回就绪事件,因为有数据可读。ET只支持非阻塞socket。

2. 边缘触发(ET):使用此种模式,只能获取一次就绪通知,如果没有处理完全部数据,并且再次调用epoll_wait()的时候,它将会阻塞,因为就绪事件已经释放出来了。

ET的效能更高,但是对程序员的要求也更高。在ET模式下,我们必须一次干净而彻底地处理完所有事件。LT两种模式的socket都支持。

传递给epoll_ctl(2)的Epoll事件结构体如下所示:

typedefunionepoll_data
{
void*ptr;
intfd;
__uint32_t u32;
__uint64_t u64;
}epoll_data_t; structepoll_event
{
__uint32_t events;/* Epoll events */
epoll_data_t data;/* User data variable */
};

对于每一个监听的描述符,能够关联一个整形数据或指向用户数据的指针。

epoll的事件类型:

enum EPOLL_EVENTS
{
EPOLLIN = 0x001,
#define EPOLLIN EPOLLIN
EPOLLPRI = 0x002,
#define EPOLLPRI EPOLLPRI
EPOLLOUT = 0x004,
#define EPOLLOUT EPOLLOUT
EPOLLRDNORM = 0x040,
#define EPOLLRDNORM EPOLLRDNORM
EPOLLRDBAND = 0x080,
#define EPOLLRDBAND EPOLLRDBAND
EPOLLWRNORM = 0x100,
#define EPOLLWRNORM EPOLLWRNORM
EPOLLWRBAND = 0x200,
#define EPOLLWRBAND EPOLLWRBAND
EPOLLMSG = 0x400,
#define EPOLLMSG EPOLLMSG
EPOLLERR = 0x008,
#define EPOLLERR EPOLLERR
EPOLLHUP = 0x010,
#define EPOLLHUP EPOLLHUP
EPOLLRDHUP = 0x2000,
#define EPOLLRDHUP EPOLLRDHUP
EPOLLONESHOT = (1 << 30),
#define EPOLLONESHOT EPOLLONESHOT
EPOLLET = (1 << 31)
#define EPOLLET EPOLLET
};

– EPOLLIN,读事件

– EPOLLOUT,写事件

– EPOLLPRI,带外数据,与select的异常事件集合对应

– EPOLLRDHUP,TCP连接对端至少写写半关闭

– EPOLLERR,错误事件

– EPOLLET,设置事件为边沿触发

– EPOLLONESHOT,只触发一次,事件自动被删除

epoll在一个文件描述符上只能有一个事件,在一个描述符上添加多个事件,会产生EEXIST的错误。同样,删除epoll的事件,只需描述符就够了

epoll_ctl(epfd, EPOLL_CTL_DEL, fd, NULL);

这里有一个比较重要的问题:从epoll_wait返回的events中,该如何知道是哪个描述符上的事件:在注册epoll事件的时候,一定要填写epoll_data,否则我们将分不清触发的是哪个描述符上的事件。

linux网络编程之网络函数详解的更多相关文章

  1. Linux网络编程--洪水攻击详解

    洪水攻击详解 ①注解:洪水攻击(FLOOD ATTACK)是指利用计算机网络技术向目标主机发送大量无用的数据报文,使得目标主机忙于处理无用的数据报文而无法提供正常服务的网络行为. 主要原理:利用了网络 ...

  2. Java网络编程和NIO详解7:浅谈 Linux 中NIO Selector 的实现原理

    Java网络编程和NIO详解7:浅谈 Linux 中NIO Selector 的实现原理 转自:https://www.jianshu.com/p/2b71ea919d49 本系列文章首发于我的个人博 ...

  3. Java网络编程和NIO详解6:Linux epoll实现原理详解

    Java网络编程和NIO详解6:Linux epoll实现原理详解 本系列文章首发于我的个人博客:https://h2pl.github.io/ 欢迎阅览我的CSDN专栏:Java网络编程和NIO h ...

  4. Java网络编程和NIO详解开篇:Java网络编程基础

    Java网络编程和NIO详解开篇:Java网络编程基础 计算机网络编程基础 转自:https://mp.weixin.qq.com/s/XXMz5uAFSsPdg38bth2jAA 我们是幸运的,因为 ...

  5. Java网络编程和NIO详解8:浅析mmap和Direct Buffer

    Java网络编程与NIO详解8:浅析mmap和Direct Buffer 本系列文章首发于我的个人博客:https://h2pl.github.io/ 欢迎阅览我的CSDN专栏:Java网络编程和NI ...

  6. Java网络编程和NIO详解9:基于NIO的网络编程框架Netty

    Java网络编程和NIO详解9:基于NIO的网络编程框架Netty 转自https://sylvanassun.github.io/2017/11/30/2017-11-30-netty_introd ...

  7. Java网络编程和NIO详解5:Java 非阻塞 IO 和异步 IO

    Java网络编程和NIO详解5:Java 非阻塞 IO 和异步 IO Java 非阻塞 IO 和异步 IO 转自https://www.javadoop.com/post/nio-and-aio 本系 ...

  8. Java网络编程和NIO详解2:JAVA NIO一步步构建IO多路复用的请求模型

    Java网络编程与NIO详解2:JAVA NIO一步步构建IO多路复用的请求模型 知识点 nio 下 I/O 阻塞与非阻塞实现 SocketChannel 介绍 I/O 多路复用的原理 事件选择器与 ...

  9. Java网络编程和NIO详解3:IO模型与Java网络编程模型

    Java网络编程和NIO详解3:IO模型与Java网络编程模型 基本概念说明 用户空间与内核空间 现在操作系统都是采用虚拟存储器,那么对32位操作系统而言,它的寻址空间(虚拟存储空间)为4G(2的32 ...

随机推荐

  1. [MATLAB] 利用遗传算法函数求目标函数的最优解

    最近接触到了遗传算法以及利用遗传算法求最优解,所以就把这些相关的内容整理记录一下. 一.遗传算法简介(摘自维基百科) 遗传算法(英语:genetic algorithm (GA))是计算数学中用于解决 ...

  2. Linux宕机最安全的重启方法(你肯定不知道)

    Linux 内核虽然号称“不死族”,几乎不会崩溃或者死机,但是特殊情况下,还是有一定几率会宕机的.因为 Linux 广泛用于生产环境,所以每一次宕机都会引起相当大的损失.本文介绍在它死机至后,一种温柔 ...

  3. Emotional Mastery——英语学习小技巧之一

    How can we control or manage our emotion ,so that we feel better and feel stronger when we're learni ...

  4. zyUpload界面绝佳、体验超棒的HTML5上传插件

    一.为毛线开发它 经过了两个星期做出了两个基于HTML5的多文件上传插件,之前在做网站的时候用到文件上传这一个功能,但是大多说都是基于Flash的,正好最近HTML5很火,而且渐渐壮大起来,感觉搞前端 ...

  5. 君子性非异也,善假于物也 - Threejs 引入TrackballControls 查看场景

    君子性非异也,善假于物也 - Threejs 引入TrackballControls 查看场景 太阳火神的漂亮人生 (http://blog.csdn.net/opengl_es) 本文遵循" ...

  6. python代码的书写要求

    刚刚接触python,python是对缩进要求很严格的语言,对于我这种平时tab,空格乱用的菜鸟来说简直是吃劲苦头阿,经常出现IndentationError.在这里我就结合自己的经历说说书写格式,如 ...

  7. 使用Swift的代理,闭包来封装一个公用协议减少垃圾代码

    iOS开发中,如果不进行适当的封装,使用协议或者继承类来进行开发,你就会遇到传说中的ViewController(以后简称VC) Hell的问题…… 比如说,我们先声网App中为了调用接口,做简单的判 ...

  8. c++打印环境变量

    直接上代码:cpp版本 #include <stdio.h> #include <stdlib.h> #include <string.h> extern char ...

  9. JavaScript之ClassName属性学习

    在前面的style属性学习中,知道了通过style属性可以控制元素的样式,从而实现了行为层通过DOM的style属性去干预变现层显示的目地,但是这种就是不好的,而且为了实现通过DOM脚本设置的样式,你 ...

  10. socketio 握手前中断报错

    前两天折腾了下socketio,部署完发现通过nginx代理之后前端的socket无法和后端通信了,于是暴查一通,最后解决问题: location / { proxy_pass http://127. ...