bind addrlen用于判断是ipv4还是6
-
socket作用是创建一个对象,以文件描述符的形式包含了网络通信所需的信息,同时维护了输入与输出缓冲区,分别用于临时存储从网络接受的数据与准备发到网络的数据;
-
bind作用是给socket创建的对象绑定ip与端口
-
listen(服务端)作用是对bind完的socket创建的对象监听外部链接请求。操作系统知道是服务端后就不再启用结合搜与发送缓冲区,转而在内核区域维护两个队列结构
-
accept作用是,服务端从socket创建的对象的全连接队列中,取出下一个已经完成三次握手的一个连接,若队列为空,accept陷入阻塞,若有新的到来,即读就绪
-
connect作用是客户端向服务端发送连接请求,并初始化一个连接,可不bind指定端口,客户端会随机选择一个临时端口号。connect预期是完成tcp三次握手
-
recv和send函数类似于有flags参数的read与write
- send与recv只是将数据在用户态,与内核态中的缓冲区之间传输,send时由操作系统决定什么时候把缓冲区的数据发出去
epoll效率比较高
epoll创建对象,在epoll对象中监听集合和就绪集合分离
epoll对象直接在内核态
每次添加epoll监听,都直接把文件描述符的相关信息,放到内核态的epoll对象的监听集合中所以epoll对象的监听集合,不需要反复型用户态拷贝到内核(甚至他都不需要拷贝)
监听集合使用红黑树(比较适合大量监听),就络集合使用线性表(比较适合,少量就绪)
监听完毕,需要把就绪集合从内核态拷贝回用户态,以供用户使用
epoll监听的文件描述符个数不像select有1024限制,而是随着内存的变化而变化
epoll是一种被动通知机制,不需要像select一样反复历询问是否就绪
epoll_event
是一个件及其相关的文件描述符。所谓临时,就是比如:// Add socketFd to epoll ev.events = EPOLLIN; ev.data.fd = socketFd; epoll_ctl(epoll_fd, EPOLL_CTL_ADD, socketFd, &ev); // Add STDIN_FILENO to epoll //不需要再次给ev.events复制,都是EPOLLIN ev.data.fd = STDIN_FILENO;//直接覆盖socketFd,因为是临时的 epoll_ctl(epoll_fd, EPOLL_CTL_ADD, STDIN_FILENO, &ev);
- epoll用时只需从数组中取出,适合海量监听,少量就绪
- select则每次都要遍历。
不timewait就可再连接
setsockopt 函数需要在
bind函数`之前执行, socket函数之后
socket(...)
// ...
int reuse = 1;
setsockopt(socketFd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse));
// ...
bind(...);