bind addrlen用于判断是ipv4还是6

image-20240823172840917

  • 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(...);

更新时间: