osi七层模型:
物-数-网-传-会-表-应
链路层-网络层-传输层-应用层
TCP三次握手和四次挥手全过程及为什么要三次握手解答
链路层:ARP/RARP
获取下一跳mac地址
网络层:IP/ICMP/IGMP
传输层:TCP/UDP
应用层: HTTP/FTP
NAT
两个子网ip同时强求外网相同的资源
打洞机制???
腾讯视频聊天
公-公:直接访问
公-私:NAT映射
私-私:NAT映射、打洞机制
socket
1 | struct sockaddr_in{ |
bind传参需要传sockaddr
网络字节序转换
htonl host–>network
htons
ntohl
ntohs
ip地址转换函数
192.168.1.23–>usnigned int –>htonl
192.168.1.23——————>htonl
int inet_pton();//点分十进制直接转二进制
const char* inet_ntop();//二进制直接转点分十进制
socket()
int socket(int domain,int type,int protocol);
bind() 服务器(客户端不调用系统会自己分配资源)
绑定ip和端口号
int bind(int sockfd,const struct sockaddr* addr,socklen_t addrlen);
listen() 服务器
设置同时允许多少个客户端和我建立链接)
int listen(int sockfd,int backlog)
accept() 服务器(阻塞)
int accept(int sockfd,struct sockaddr addr ,sockleen_t addrlen)
sockfd: socket文件描述符
addr: 传出参数,返回链接客户端地址信息,含IP地址和端口号
addrlen: 传入传出参数,传入sizeof(addr)大小,函数返回时返回真正接受到地址结构体的大小
返回值:成功返回新的socket文件描述符,用于和客户端通信,失败返回-1,设置errno
connect() 客户端
int connnect(int sockfd,const struct sickaddr *addr,socklen_t addrlen)
client
server
socket–>bind–>listen–>accept–>read–>write–>close
socket–>connect–>write–>read–>close
nc 命令
多路I/O转接服务器
服务器的内核帮助 来监听客户端请求
第一种select()
select(),驱使内核来监听,解放应用程序,建立在应用程序与客户端已经链接的前提下
int select(int nfds,fd_set readfds,fd_set writefd,fd_set writefd,fd_set exceptfds,struct timeval* timeout);
参数1:所监听所有文件描述符中,最大的文件描述符+1;
参数2/3/4:所监听的文件描述符“可读”事件集合 readfds()
所监听的文件描述符“可写”事件集合 writefds()
所监听的文件描述符“可读”事件集合 readfds()
参数5:超时时间
返回值:成功:监听的所有文件描述符中满足监听条件(读/写/异常)的总数
失败:
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集合中
第二种poll()
可以通过修改 /proc/sys/fs/file-max 修改打开文件描述符上限
int poll(struct pollfd* fds,nfds_t nfds,int timeout);
参数一:结构体数组的首地址 监听与返回分离
struct pollfd{
int fd;
short events;
short revents;
}
参数2:数组中有多少文件描述符需要被监听
参数3:-1:永久阻塞等,0:立即返回,>0:等待指定毫秒数
第三种epoll()
select/poll的增强版,它能显著提高程序在大量并发连接中只有少量活跃情况下的系统cpu利用率,因为他会服用文件描述符集合来传递结果,而不用迫使开发者每次等待时间之前都必须重新准备要被监听的文件描述符集合,另一点原因就是获取事件的时候,它无需遍历整个被监听集合,只要遍历哪些被内核I/O事件异步唤醒而加入Ready队列的描述符集合就行了。
epoll_create()
int epoll_create(int size);
//告诉linux内核,你需要给我创建一个多大的epoll模型,底层调用kalloc函数开辟存储空间(size大小的红黑树)
//返回一个文件描述符,这个描述符指向红黑树的树根,(二分查找)
epoll_ctl()
int epoll_ctl(int epfd,int op,int fd,struct epoll_event* event)
//控制红黑树的增删改查
参数2:(红黑树的增删改查)
参数4: 监控文件描述符的结构in,out,error
struct epoll_event{
uint32_t events;
epoll_data_t data;
}
epoll_wait()
阻塞监听
int epoll_wait(int epfd,struct epoll_event* events,int maxevents,int timeout)
参数1;红黑树根节点
参数2:传出符合条件的集合
返回值:返回缩监听文件描述符符合条件的个数1
2
线程池:
条件变量
pthread_singal()/broadcast()
pthread_cond_wait()