Linux网络编程学习心得.3

1.半关闭

主动方发生在FIN_WAIT_2状态,这个状态时,主动方不可以在应用层发送数据了,但是应用层还可以接收数据,这个状态称为半关闭

#include

int shutdown(int sockfd, int how);

sockfd: 需要关闭的socket的描述符

how:    允许为shutdown操作选择以下几种方式:

    SHUT_RD(0):    关闭sockfd上的读功能,此选项将不允许sockfd进行读操作。

                   该套接字不再接收数据,任何当前在套接字接受缓冲区的数据将被无声的丢弃掉。

    SHUT_WR(1):     关闭sockfd的写功能,此选项将不允许sockfd进行写操作。进程不能在对此套接字发出写操作。

    SHUT_RDWR(2):   关闭sockfd的读写功能。相当于调用shutdown两次:首先是以SHUT_RD,然后以SHUT_WR。

2.心跳包

如果对方异常断开,本机检测不到,一直等待,浪费资源

需要设置tcp的保持连接,作用就是每隔一定的时间间隔发送探测分节,如果连续发送多个探测分节对方还未回,就将次连接断开

int  keepAlive = 1;

setsockopt(listenfd, SOL_SOCKET, SO_KEEPALIVE, (void*)&keepAlive, sizeof(keepAlive));

心跳包:  最小粒度

乒乓包:  携带比较多的数据的心跳包

3.设置端口复用

int opt = 1;

    setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));

注意: 程序中设置某个端口重新使用,在这之前的其他网络程序将不能使用这个端口

4.高并发服务器

阻塞等待  消耗资源

非阻塞忙轮询 消耗cpu

多路IO

多路IO转接(多路IO复用): 内核监听多个文件描述符的属性(读写缓冲区)变化

如果某个文件描述符的读缓冲区变化了,这个时候就是可以读了,将这个事件告知应用层

Linux网络编程学习心得.3_第1张图片

5. select epoll  poll 

windwos   使用select   select跨平台

poll 少用

epoll   linux 

6.select函数的API 

#include >

 /* According to earlier standards */

       #include

       #include

       #include

       int select(int nfds, fd_set *readfds, fd_set *writefds,

                  fd_set *exceptfds, struct timeval *timeout);

功能: 监听多个文件描述符的属性变化(读,写,异常)

       void FD_CLR(int fd, fd_set *set);

       int  FD_ISSET(int fd, fd_set *set);

       void FD_SET(int fd, fd_set *set);

       void FD_ZERO(fd_set *set);

参数:

    nfds  : 最大文件描述符+1

    readfds : 需要监听的读的文件描述符存放集合

    writefds :需要监听的写的文件描述符存放集合   NULL

    exceptfds : 需要监听的异常的文件描述符存放集合  NULL

    timeout: 多长时间监听一次   固定的时间,限时等待   NULL 永久监听

    struct timeval {

               long    tv_sec;         /* seconds */ 秒

               long    tv_usec;        /* microseconds */微妙

           };

  返回值: 返回的是变化的文件描述符的个数

注意: 变化的文件描述符会存在监听的集合中,未变化的文件描述符会从集合中删除

    select文件描述符请求剩余,之后在遍历,备份

7.select实现的原理和优缺点

实现原理:

Linux网络编程学习心得.3_第2张图片

优缺点:

优点: 跨平台

缺点:

文件描述符1024的限制   由于 FD_SETSIZE的限制

只是返回变化的文件描述符的个数,具体哪个那个变化需要遍历

每次都需要将需要监听的文件描述集合由应用层符拷贝到内核

大量并发,少了活跃,select效率低

假设现在 4-1023个文件描述符需要监听,但是5-1000这些文件描述符关闭了?

假设现在 4-1023个文件描述符需要监听,但是只有 5,1002 发来消息- 无解

 8.poll和poll的API

优点: 相对于select没有最大1024文件描述符限制

请求和返回是分离

Linux网络编程学习心得.3_第3张图片

 poll API

#include

 int poll(struct pollfd *fds, nfds_t nfds, int timeout);

功能: 监听多个文件描述符的属性变化

参数:

    fds : 监听的数组的首元素地址

    nfds: 数组有效元素的最大下标+1

    timeout : 超时时间 -1是永久监听 >=0 限时等待

数组元素:

struct pollfd

            struct pollfd {

               int   fd;         /* file descriptor */ 需要监听的文件描述符

               short events;     /* requested events */需要监听文件描述符什么事件  EPOLLIN 读事件   EPOLLOUT写事件

               short revents;    /* returned events */ 返回监听到的事件    EPOLLIN 读事件   EPOLLOUT写事

           };

9.poll相对与sellect的优缺点

优点:

没有文件描述符1024的限制

 请求和返回是分离的

缺点和select一样:

每次都需要将需要监听的文件描述符从应用层拷贝到内

每次都需要将数组中的元素遍历一遍才知道那个变化了

大量并发,少量活跃效率低

10.epoll的工作原理和epollAPI 

实现原理:

Linux网络编程学习心得.3_第4张图片

epollAPI 

 a> 创建红黑树

    #include

      int epoll_create(int size);

    参数:

    size :  监听的文件描述符的上限,  2.6版本之后写1即可,

    返回:  返回树的句柄

b>  上树  下树 修改节点

    epoll_ctl

#include

int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);

参数:

    epfd : 树的句柄

    op : EPOLL_CTL_ADD 上树   EPOLL_CTL_DEL 下树 EPOLL_CTL_MOD 修改

    fd : 上树,下树的文件描述符(lfd,cfd)

    event :   上树的节点

    typedef union epoll_data {

               void        *ptr;

               int          fd;

               uint32_t     u32;

               uint64_t     u64;

           } epoll_data_t;

           struct epoll_event {

               uint32_t     events;      /* Epoll events */  需要监听的事件

               epoll_data_t data;        /* User data variable */ 需要监听的文件描述符

           };

将cfd上树

   int epfd =  epoll_create(1);

struct epoll_event ev;

ev. data.fd = cfd;

ev.events = EPOLLIN;

epoll_ctl(epfd, EPOLL_CTL_ADD,cfd, &ev);

c> 监听

    #include

       int epoll_wait(int epfd, struct epoll_event *events,

                      int maxevents, int timeout);

    功能: 监听树上文件描述符的变化

    epfd : 数的句柄

    events : 接收变化的节点的数组的首地址

    maxevents :  数组元素的个数

    timeout : -1 永久监听  大于等于0 限时等待

返回值: 返回的是变化的文件描述符个数

总结: 

半关闭,主动方关闭了,应用层不能发送数据了,但是能接受数据,这种状态为半关闭状态

对方如果断开连接,一直等待,浪费资源,探测分节就是心跳包用来检测tcp的连接

设置端口复用,可以将端口重复使用

之前的阻塞等待,像是一个事件创建一个还要去遍历,非阻塞忙轮询,就像雇佣了一个人来回查看是否有新的事件,多路io端口复用是内核检测文件描述符的变化,再告知应用层

select(Windows),epoll(Linux),poll都是检测的,

要知道select的函数如何写,并且需要了解如何去构造,我们需要自己构造文件描述符的集合,并且需要遍历,

select实现原理:需要把文件描述符的集合拷贝内核空间,再拷贝回去应用空间,而且需要遍历每一位,读文件还需要遍历,文件描述符太少,只是返回文件描述符的个数,具体变化还需要处理,

poll没有文件描述符1024限制,监听文件描述的变化,EPOLLIN读事件,EPOLLOUT写事件。

poll优点就是修改了文件描述符的限制1024,其他缺点和select一样

 epoll创建一个红黑树,将要监听的文件描述符上树,监听,监听到的文件描述符变化,发给数组接收,创建一个红黑树epoll_create,返回树的句柄,epoll_ctl(句柄,epoll_ctl_add(上树),epoll_ctl_dev(下树),文件描述符,上树的节点)上树,下树,监听epoll_wait(句柄,事件,数组元素个数,-1)返回文件描述变化个数

你可能感兴趣的:(linux,网络,运维)