Linux网络编程学习心得.3

发布时间:2023年12月29日

1.半关闭

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

#include <sys/socket.h>

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复用): 内核监听多个文件描述符的属性(读写缓冲区)变化

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

5.?select epoll ?poll?

windwos ??使用select ??select跨平台

poll 少用

epoll ??linux?

6.select函数的API?

#include <sys/select.h>

?/* According to earlier standards */

???????#include <sys/time.h>

???????#include <sys/types.h>

???????#include <unistd.h>

???????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实现的原理和优缺点

实现原理:

优缺点:

优点: 跨平台

缺点:

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

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

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

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

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

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

?8.poll和poll的API

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

请求和返回是分离

?poll API

#include <poll.h>

?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?

实现原理:

epollAPI?

?a> 创建红黑树

????#include <sys/epoll.h>

??????int epoll_create(int size);

????参数:

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

????返回: ?返回树的句柄

b> ?上树 ?下树 修改节点

????epoll_ctl

#include <sys/epoll.h>

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 <sys/epoll.h>

???????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)返回文件描述变化个数

文章来源:https://blog.csdn.net/weixin_55605689/article/details/135270326
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。