目录
Socket::bindAddress(const InetAddress &localaddr)
Socket::accept(InetAddress *peeraddr)
Socket成员变量:
就是一个Socketfd。
Socket成员函数:
Socket就是对一个fd进行封装,包括:
1. 通过构造函数,获取外面传进来的一个listenfd;
2. bindAddress:绑定ip地址和端口,用户传入的;
3. listen:监听
4. accept:从监听队列中拿通信fd;
5. shutdownWrite: 将写端关闭(Tcp通信是一个双向通信,每一段都可读可写)
6. setTcpNoDelay:通过setsockopt更改Tcp的选项
构造函数、析构函数:

Socket::bindAddress(const InetAddress &localaddr)
底层就是bind函数
Socket::listen()

Socket::accept(InetAddress *peeraddr)

accept4()
额外提供了选项来设置新套接字的属性。
int accept4(int sockfd, struct sockaddr *addr, socklen_t *addrlen, int flags);
它的参数含义如下:
sockfd:表示监听套接字的文件描述符。
addr:一个指向 sockaddr 结构的指针,用于接收连接方的地址信息。
addrlen:一个指向 socklen_t 类型变量的指针,用于指定 addr 缓冲区的大小。
flags:用于设置新创建套接字的选项,常用的选项包括 SOCK_NONBLOCK(非阻塞模式)和 SOCK_CLOEXEC(执行 exec 系统调用时自动关闭套接字)。
accept4和accept区别:
执行方式:
accept是阻塞调用,会一直等待直到有新的连接到达;而accept4可以设置为非阻塞模式,即使没有新连接到达,它也会立即返回。
accept4可以在调用时指定SOCK_CLOEXEC标志,使返回的新连接套接字自动设置O_CLOEXEC。
Socket::shutdownWrite()

设置套接字选项:

Socket.h
#pragma once
#include "noncopyable.h"
class InetAddress;
//封装socket fd
class Socket : noncopyable
{
public:
explicit Socket(int sockfd)
: sockfd_(sockfd)
{}
~Socket();
int fd() const { return sockfd_; }
void bindAddress(const InetAddress &localaddr);
void listen();
int accept(InetAddress *peeraddr);
void shutdownWrite();
void setTcpNoDelay(bool on);//直接发送,数据不进行TCP缓存
void setReuseAddr(bool on);
void setReusePort(bool on);
void setKeepAlive(bool on);
private:
const int sockfd_;
};
Socket.cc
#include "Socket.h"
#include "Logger.h"
#include "InetAddress.h"
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <strings.h>
#include <netinet/tcp.h>
#include <sys/socket.h>
Socket::~Socket()
{
close(sockfd_);//调用系统的close
}
void Socket::bindAddress(const InetAddress &localaddr)
{
if (0 != ::bind(sockfd_, (sockaddr*)localaddr.getSockAddr(), sizeof(sockaddr_in)))
{
LOG_FATAL("bind sockfd:%d fail \n", sockfd_);
}
}
void Socket::listen()
{
if (0 != ::listen(sockfd_, 1024))
{
LOG_FATAL("listen sockfd:%d fail \n", sockfd_);
}
}
int Socket::accept(InetAddress *peeraddr)//peeraddr:输出参数
{
/**
* 1. accept函数的参数不合法
* 2. 对返回的connfd没有设置非阻塞
* Reactor模型 one loop per thread
* poller + non-blocking IO
*/
sockaddr_in addr;
socklen_t len = sizeof addr;
bzero(&addr, sizeof addr);
int connfd = ::accept4(sockfd_, (sockaddr*)&addr, &len, SOCK_NONBLOCK | SOCK_CLOEXEC);
if (connfd >= 0)
{
peeraddr->setSockAddr(addr);
}
return connfd;
}
void Socket::shutdownWrite()//只关闭写端
{
if (::shutdown(sockfd_, SHUT_WR) < 0)
{
LOG_ERROR("shutdownWrite error");
}
}
void Socket::setTcpNoDelay(bool on)
{
int optval = on ? 1 : 0;
::setsockopt(sockfd_, IPPROTO_TCP, TCP_NODELAY, &optval, sizeof optval);
}
void Socket::setReuseAddr(bool on)
{
int optval = on ? 1 : 0;
::setsockopt(sockfd_, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof optval);
}
void Socket::setReusePort(bool on)
{
int optval = on ? 1 : 0;
::setsockopt(sockfd_, SOL_SOCKET, SO_REUSEPORT, &optval, sizeof optval);
}
void Socket::setKeepAlive(bool on)
{
int optval = on ? 1 : 0;
::setsockopt(sockfd_, SOL_SOCKET, SO_KEEPALIVE, &optval, sizeof optval);
}
该文章详细介绍了Socket类的成员变量和函数,包括构造和析构函数,以及bindAddress、listen、accept、accept4、shutdownWrite等关键方法。此外,还讨论了accept4与accept的区别,并展示了如何设置套接字选项如TCP_NO_DELAY、REUSE_ADDR等。
8176

被折叠的 条评论
为什么被折叠?



