1、TCP半关闭状态:主动发起关闭方才会处于的状态,被动方不会
TIME_WAIT:主动发起关闭方会处于的状态2MSL超时:大约一分钟左右:不确定对方是否收到自己的ACK(回应FIN):等满2MSL:确保主动关闭方发送的最后一个ACK到达对方
shutdown();实现半关闭,还可以指定关闭状态:使用close()只是描述符引用计数减1,shutdown全关
TIME_WAIT状态不能再次监听同一个端口
端口复用:setsockopt():使处于TIME_WAIT状态的时,依旧可以监听
int opt=1;
setsockopt(listenfd,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(opt));
2、多路I/O转接服务器:不再由应用程序自己监视客户端连接,取而代之由内核代替应用程序监视
主要方法有3种:
1)select
#include <sys/select.h>
#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);
参1:所监听的所有文件描述符中,最大的文件描述符+1
fd_set:文件描述符事件集合(位图)
参2、3、4:所监听的文件描述符可读、可写、异常事件(读用的比较多):!传入传出参数
参5:超时:时间结构体
返回值:成功:返回监听的所有监听集合中,满足条件的总数:读+写+异常
失败:返回-1,设置errono
void FD_ZERO(fd_set *set);//将set清空
void FD_CLR(int fd, fd_set *set);//将fd从set中清楚
int FD_ISSET(int fd, fd_set *set);//判断fd是否在集合中
void FD_SET(int fd, fd_set *set);//将fd加入到set中
缺点:
1、同时监听的文件描述符:文件描述符上限:1024
2、返回的是发生变化的总数,判断是谁比较难 自定义数据结构:数组
3、监听集合和满足监听条件集合是一个,将原有集合保存
2)poll:select升级版
优点:1、突破1024上限 2、监听、返回集合分离 3、搜索范围变小
#include <poll.h>
int poll(struct pollfd *fds, nfds_t nfds, int timeout);
struct pollfd {
int fd; /* file descriptor */
short events; /* requested events */
short revents; /* returned events */
};
参1:结构体数组首地址
参2:数组里面监听的元素的个数
fd[0].fd=listenfd;
fd[0].events=POLLIN/POLLOUT/POLLERR
fd[0].revents(返回参数)
参2:-1:阻塞等 0:立即返回,不等待 >0等待时间
3)epoll:LINUX下select/poll增强版
#include <sys/epoll.h>
int epoll_create(int size);
创建一个epoll句柄,参数size用来告诉内核坚挺的文件描述符个数,和系统有关
返回一个文件描述符,指向一个红黑树树根节点
#include <sys/epoll.h>
int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);
控制某个epoll监控上的文件描述符上的事件:注册、修改、删除
epfd:文件描述符
opt:EPOLL_CTL_AD EPOLL_CTL_MOD EPOLL_CTL_DEL
fd:对谁操作
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 */
};
events: EPOLLIN/ EPOLLOUT/ EPOLLERR
成功返回0,失败返回-1并设置errono
#include <sys/epoll.h>
int epoll_wait(int epfd, struct epoll_event *events,
int maxevents, int timeout);
等待所监听的文件描述符上有事件的产生,类似于select()的调用
struct epoll_event *events:数组!!!(传出参数):数组每一个元素都是结构体
成功返回有多少个文件描述符就绪,时间到时返回0,出错返回-1
void* ptr:可以封装函数指针
typedef union epoll_data {
void *ptr;
int fd;
uint32_t u32;
uint64_t u64;
} epoll_data_t;
epoll:边沿触发 ET模式/水平触发 LT模式
epoll非阻塞IO:1、fctl 2、open(对于socket不适用):边沿触发,非阻塞IO效率高
flag=fcntl(connfd,F_GETFL);
flag|=O_NONBLOCK;
fcntl(connfd,F_SETFL,flag);
3、epoll反应堆(libevent-跨平台、精炼 epoll 回调 核心思想实现)
4、心跳包(乒乓包:加简单数据)协议:应用层 3、设置TCP属性:很少用
5、线程池!!!