首页 > 编程语言 >网络编程学习2

网络编程学习2

时间:2023-08-23 21:11:27浏览次数:39  
标签:epoll int 编程 网络 学习 描述符 线程 pthread fd

TCP服务端处理多客户端任务:
原来是通过开启子进程来服务不同的客户端,当客户端退出时就关闭该子进程
多路复用:
使用一个进程(有且只有一个主进程)同时监控若干个文件描述符,这种读写模式称为多路复用
多用于TCP的服务端,用于监控客户端的连接和数据的收发
优点:不需要频繁的创建和销毁进程,从而节约了内存资源、时间资源,也避免了进程之间的竞争、等待
缺点:要求单个客户端的任务不能太耗时,否则其他在等待的客户端就会感知“卡顿”
适用场景:适合并发量大、但任务短小的场景,例如:Web服务器

实现多路复用相关函数:
select:
fd_set 是文件描述符的集合,就是一种数据类型,使用以下函数进行操作:
操作:
void FD_SET(int fd, fd_set *set);
功能:向集合set中添加fd
void FD_CLR(int fd, fd_set *set);
功能:从集合set中删除fd
int FD_ISSET(int fd, fd_set *set);
功能:判断集合set中是否存在fd
返回值:存在返回1,不存在返回0
void FD_ZERO(fd_set *set);
功能:清空集合set,最好在一开始先清空集合再使用

int select(int nfds, fd_set *readfds, fd_set *writefds,fd_set *exceptfds, struct timeval *timeout);
功能:同时监控若干个文件描述符的读、写、异常操作是否发生

nfds:被监控的文件描述符中最大值+1
readfds:监控读操作的文件描述符集合
writefds:监控写操作的文件描述符集合
execptfds:监控异常操作的文件描述符集合
timeout:设置超时时间

struct timeval {
    long    tv_sec;         //秒
    long    tv_usec;        //微秒
};

NULL  一直阻塞,直到某个被监控的描述符发生了对应的操作才返回
0秒0微秒    非阻塞,直接返回
大于0秒     等待该时间,超时了会返回0
            如果设置时间,返回时该参数会变成剩余时间

返回值:成功返回发生相应操作的文件描述符个数
超时返回0,错误返回-1

注意:readfds、writefds、exceptfds这三个参数既是输入也是输出,在调用时需要往里面存放想要监控的文件描述符
当监控到发生操作时,该函数会给这三个参数只返回发生相应操作的文件描述符,存储在这三个参数中,需要调用者逐个判断
获取

select设计不合理的地方:
1、每次调用select都需要向它传递要监控的描述符的集合
2、当调用结束后如果想要知道哪些描述符发生了操作,需要拿着所有被监控的描述符对着集合进行逐一测试

select的优点:
是最早出现的多路复用函数,几乎所有的操作系统都支持,系统的兼容性高

pselect:
只是select功能的部分增强,没有本质的区别、缺点一致
int pselect(int nfds, fd_set *readfds, fd_set *writefds,
fd_set *exceptfds, const struct timespec *timeout,const sigset_t *sigmask);

功能、原理与上select大致类似
区别:
1、超时时间结构类型不同、pselect的精读更高
2、pselect的超时时间参数不会改变,因此无法获取剩余时间,但是select的会改变,可以获取剩余时间,但是
select每次都需要重新设置
3、pselect监控时可以通过sigmask参数设置想要屏蔽的信号,可以保障pselect在监控的过程中不会被信号中断

poll:

 struct pollfd {
           int   fd;         //被监控的文件描述符
           short events;     //想要监控的事件
           short revents;    //实际监控到的发生的事件
            //有以下事件:
              POLLIN    普通优先级的读事件
              POLLPRI   高优先级的读事件
              POLLOUT   普通优先级的写事件
              POLLRDHUP     对方socket关闭
              POLLERR   错误事件,无需监控也可发生
              POLLHUP   对方挂起事件,无需监控也可以发生
              POLLNVAL  非法描述符事件,无需监控也可发生

       };


int poll(struct pollfd *fds, nfds_t nfds, int timeout);
功能:监控文件描述符是否发生了相应的事件

fds:pollfd结构连续内存的首地址
nfds:连续内存fds的成员数量
timeout:超时时间,单位毫秒
返回值:成功返回相应操作的文件描述符的个数
超时返回0,失败返回-1

epoll:
int epoll_create(int size);
功能:创建一个epoll对象,该对象用于保存要监控的描述符
size:epoll对象能够保存的描述符数量
返回值:成功返回epoll对象

int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);
功能:控制epoll对象,添加、删除监控的描述符
epfd:要操作的epoll对象描述符
op:
    EPOLL_CTL_ADD   添加描述符
    EPOLL_CTL_MOD   修改描述符要监控的事件
    EPOLL_CTL_DEL   删除描述符
fd:epoll对象中要控制的描述符
event:事件描述符
    struct epoll_event {
        uint32_t     events;      //要监控的事件 功能参考poll
        epoll_data_t data;        //
    };

    typedef union epoll_data {
           void        *ptr;
           int          fd;
           uint32_t     u32;
           uint64_t     u64;
       } epoll_data_t;

    功能:成功0 失败-1

int epoll_wait(int epfd, struct epoll_event *events,int maxevents, int timeout);
功能:开始监控epoll对象中的文件描述符,并返回产生事件的文件描述符
epfd:要监控的epoll对象描述符
events:输出型参数,用于获取发生事件的描述符数组
maxevents:最多监控的描述符的数量
timeout:超时时间 毫秒
返回值:成功返回发生事件的描述符的数量
        0表示超时,-1表示错误

epoll与select比较的优点:
    1、只需要设置一次要监控的描述符即可
    2、epoll会把发生了事件的描述符返回到结构数组,只需要遍历该数组就可以处理所有发生了事件的描述符,但是select返回到
    集合中,需要遍历全部被监控的描述符才能处理

epoll条件触发和边缘触发:
    条件触发:当文件缓冲区中有要读取的数据时就会触发事件,也是epoll的默认触发

    边缘触发:当数据产生了发送的动作时,就会触发且只触发一次,就算文件缓冲区中要有
    需要读取的数据也不再触发事件
        1、把要监控的描述符的事件增加 EPOLLET 边缘触发选项
        2、循环读取数据,直到读取玩为止 while
        3、recv读取时,必须以非阻塞的方式读取MSG_DONTWAIT,否则就一直阻塞,形成了死锁
        4、当recv返回-1表示数据读取完毕,0表示断开

    优点:相比较于条件触发,边缘触发能够大大降低触发的次数,从而提高epoll的效率。

线程管理
一、基本概念
1、线程是进程的执行路线,它是进程内部的控制序列。线程是进程的一部分,进程是一个资源单位,
而线程是执行单位,线程是进程执行的实体,负责真正的执行。
2、线程是轻量级的,没有自己的代码段、数据段、bss段、堆、环境变量、命令行参数、文件描述符、
信号处理函数、当前工作目录等资源,进程中的所有线程都共享以上资源
3、每个线程都有自己独立的栈内存、线程ID、错误码、信号掩码、程序计数器、调度的优先级
4、一个进程可以包含多个线程(多条不同的执行路线),但是至少要保证有一个线程,进程刚创建
成功时必定有一个线程,也称为主线程
5、ps -T -p 查看进程pid的线程信息,还可以htop命令查看
6、线程是进程的实体,可以作为系统独立的任务调度和分配的基本单位
7、线程有不同的状态,系统提供的线程的控制接口,例如:创建、销毁、控制等
8、进程中的所有线程都在同一个虚拟地址空间中工作,进程中的所有资源对于它的线程来说都是共享的
尽管线程有属于自己的栈内存等资源,但是没有添加保护机制的,对于其他线程而言这些资源是可见的,
当多个线程协同工作时需要解决的首要问题是资源竞争的问题(上锁)
9、线程的系统开销小、任务的切换速度快、同进程的多个线程之间不需要数据交换
也就不需要类似进程间通信的机制进行线程间通信,因此使用线程相对简单高效
10、线程之间有优先级之分

二、POSIX线程
1、早期的UNIX和早期的Linux是没有线程概念的,微软的Windows系统首先使用的线程概念,之后UNIX和Linux
也逐渐增加使用线程
2、早期各个厂商都提供自己私有的线程库,各自的接口实现差异比较大,不易于移植,世界标准化组织1995年指定了
统一的线程接口规范,遵循这套标准的线程统称为POSIX线程,简称pthread
3、pthread包含一个头文件,pthread.h和一个共享库libpthread.so,使用的时候是-lpthread 编译参数

三、线程的管理

int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
                        void *(*start_routine) (void *), void *arg);
功能:创建线程
thread:输出型参数,用于获取线程ID,
attr:线程属性,一般无设置属性给NULL即可
start_routine;线程的执行入口函数,类似于该线程的主函数
arg:传递给入口函数的参数
返回值:成功0,失败返回错误编码

注意:入口函数的参数和返回值要确保它们的持久化,方法1:使用全局变量参数,方法2:赶在参数释放前,
把参数的值立即保存到入口函数的栈内存中

注意:从表面上看当主线程结束后,子线程也会随之一起结束,但实际上子线程之所以结束,但实际上是因为
主线程执行main函数中隐藏的return语句,导致整个进程结束,所有线程都属于进程的一部分,会随着进程一起被
结束回收

注意:子线程执行入口函数结束后,子线程也结束了

int pthread_join(pthread_t thread, void **retval);
功能:等待线程结束,并获取结束时入口函数的返回值、释放线程资源

thread:要等待的线程ID
retval:用于获取线程结束时返回值的地址
返回值:成功0,失败返回错误编码,如果线程还未结束则阻塞

int pthread_equal(pthread_t t1, pthread_t t2);
功能:判断两个线程id是否相同,相同返回非零,不相同返回零
注意:部分系统中的线程ID是以结构实现的,因此不能直接使用==运算符


pthread_t pthread_self(void);
功能:获取当前线程的线程ID

四、线程的执行轨迹
同步方式:可结合状态(joinable)
在使用默认属性创建线程时,线程属于joinable态,该类线程必须在另一个
线程中使用pthread_join函数等待其结束并释放线程资源,如果该类线程
在结束时没有任何线程执行pthread_join回收其资源,那么该线程就变
成了“僵尸线程”。每个“僵尸线程”都会消耗一些系统资源,当有太多的
“僵尸线程”存在时,可能会导致创建线程失败

异步方式:分离状态(detach)
    当把线程设置为detach态时,线程结束无需经过pthread_join函数回收
    资源,由系统负责回收资源
注意:为了避免线程资源的泄露,要么显示地调用pthread_join回收资源,或者
设置为detach态

int pthread_detach(pthread_t thread);
功能:让线程分离,变成detach态
thread:想要变成detach态的线程id
    两种方式:
    1、线程自己调用:
        pthread_detach(pthread_self());
    2、其他线程(创建者)
        pthread_detach(threadid);

注意:如果先执行了pthread_join进入等待后,才对线程进行分离,join
不会立即结束,而是一直等到线程结束才返回

任务:实现多线程版本的TCP多客户端服务器

五、线程的终止
1、线程执行完入口函数的最后一行代码
2、线程调用pthread_exit函数,结束该线程
void pthread_exit(void *retval);
功能:向本线程发出取消请求,如果响应该请求,则线程终止
retval:线程入口函数的返回值,会返回给pthread_join
3、如果进程结束(前三种情况),那么它所有的线程都会随之结束
4、向指定的线程发出取消请求
int pthread_cancel(pthread_t thread);
默认情况下都会响应取消请求
thread:要杀死的线程id

六、线程的属性
pthread_attr_t的定义:
typedef struct
{
int detachstate; 线程的分离状态
int schedpolicy; 线程调度策略
struct sched_param schedparam; 线程的调度参数
int inheritsched; 线程的继承性
int scope; 线程的作用域
size_t guardsize; 线程栈末尾的警戒缓冲区大小
int stackaddr_set;
void * stackaddr; 线程栈的位置
size_t stacksize; 线程栈的大小
}pthread_attr_t;
通过pthread_attr_setxxx 设置线程相关属性
通过pthread_attr_getxxx获取线程相关属性

标签:epoll,int,编程,网络,学习,描述符,线程,pthread,fd
From: https://www.cnblogs.com/c-learnmore/p/17652777.html

相关文章

  • STM23学习记录2:外部中断,串口通信,定时器
    外部中断:向量表:异常+中断所有端口的PIN0对应着EXTI0中短线,PIN1对应EXTI1中断线,依次类推16个外部中断线,对应7个外部中断入口地址配置中断优先级的4位要同时完成抢占优先级和响应优先级(子优先级或副优先级)的配置:两组优先级2+2,2^2抢占,2^2响应比较常用使用NVIC_PriorityGroupCon......
  • 学习笔记:什么是Wasserstein distance
    简单地说,就是衡量两个概率分布之间的差异。也可以说是将一个概率分布转换成另一个概率分布要花费多少代价。图1:在一维空间中的三个概率分布比如,上图中有三个概率分布f,g,h,我们可以说f与g之间的距离比f与h之间的距离更小。上述只是感性上的认知,那么如何计算出准确......
  • OS(二十四):网络操作系统
    计算机网络是指通过数据通信系统把地理上分散的自主计算机系统连接起来,以达到数据通信和资源共享目的的一种计算机系统。自主计算机,是指具有独立处理能力的计算机。在计算机网络上配置网络操作系统NOS(NetworkOperatingSystem),是为了管理网络中的共享资源,实现用户......
  • c# .NET 高级编程 高并发必备技巧(二) - 分布式锁
    上一篇文章简单的介绍了单机的情况下如何进行加锁,防止高并发带来的问题。然而现实中,一般会高并发的应用,很少会单机部署。当用户量达到一定的程度,分布式、集群部署是必然的选择。在分布式部署的情况下,之前的单机锁还会有效吗?代码还是之前的代码:privatestaticobjectlck=......
  • Mysql学习
    ​Mysql​数据库(DataBase,简称DB):存储和管理数据的仓库。数据库管理系统(DataBaseManagementSystem,简称DBMS)DBMS是操作和管理数据库的大型软件。将来我们只需要操作这个软件,就可以通过这个软件来操纵和管理数据库了。此时又出现一个问题:DBMS这个软件怎么知道要操作的......
  • SQL注入基础学习5
    SQL注入基础学习5二、靶场实操(开始先学习手工,后面的话,可以采用sqlmap等自动化工具)靶场采用sqli-labs21、第21关第21关是也是属于cookie注入的登陆后查看页面或者报头信息(如图一),会发现,输入时uname=admin1,但是页面上显示的YWRtaW4x说明被编码了,试一下bsae64解码(如图二),图......
  • openGauss学习笔记-48 openGauss 高级数据管理-函数
    openGauss学习笔记-48openGauss高级数据管理-函数openGauss常用的函数如下:48.1数学函数abs(x)描述:绝对值。返回值类型:和输入相同。示例:openGauss=#SELECTabs(-17.4);abs------17.4(1row)cbrt(dp)描述:立方根。返回值类型:doubleprecision示例:openGauss......
  • 深度学习(十二)——神经网络:搭建小实战和Sequential的使用
    一、torch.nn.Sequential代码栗子官方文档:Sequential—PyTorch2.0documentation#UsingSequentialtocreateasmallmodel.When`model`isrun,#inputwillfirstbepassedto`Conv2d(1,20,5)`.Theoutputof#`Conv2d(1,20,5)`willbeusedastheinputto......
  • Kafka入门到精通学习路线图 技术文章
    Kafka入门到精通学习路线图技术文章Kafka是一个分布式流式处理平台,被广泛应用于大规模数据处理和实时数据流分析的场景中。以下是一个从入门到精通的学习路线图,帮助你系统地学习和掌握Kafka的相关技术。1.学习Kafka的概念和基础知识:-了解Kafka的起源和背景,掌握Kafka的基本概......
  • 网络安全-修改基础接口配置(MSTP负载均衡)
    [s3-GigabitEthernet0/0/1]disthis#interfaceGigabitEthernet0/0/1portlink-typeaccessportdefaultvlan10#return[s3-GigabitEthernet0/0/1]portde [s3-GigabitEthernet0/0/1]portdefaultvlan1\^Error:Wrongparam......