anet是redis对tcp/ip网络中socket api接口的一个全面的封装,针对server/client端。封装的api的接口如下,注释了主要的接口:
// tcp连接
int anetTcpConnect(char *err, char *addr, int port);
// 非阻塞连接
int anetTcpNonBlockConnect(char *err, char *addr, int port);
// 非阻塞绑定
int anetTcpNonBlockBindConnect(char *err, char *addr, int port, char *source_addr);
// 非阻塞绑定
int anetTcpNonBlockBestEffortBindConnect(char *err, char *addr, int port, char *source_addr);
//unix socket connect
int anetUnixConnect(char *err, char *path);
// unix non-block connect
int anetUnixNonBlockConnect(char *err, char *path);
// socket读数据
int anetRead(int fd, char *buf, int count);
// 解析所有的东西
int anetResolve(char *err, char *host, char *ipbuf, size_t ipbuf_len);
// 解析ip
int anetResolveIP(char *err, char *host, char *ipbuf, size_t ipbuf_len);
// ipv4下socket()函数创建socket
int anetTcpServer(char *err, int port, char *bindaddr, int backlog);
// ipv6下create socket
int anetTcp6Server(char *err, int port, char *bindaddr, int backlog);
// unix create socket and bind
int anetUnixServer(char *err, char *path, mode_t perm, int backlog);
// tcp socket accept()
int anetTcpAccept(char *err, int serversock, char *ip, size_t ip_len, int *port);
// unix socket accept()
int anetUnixAccept(char *err, int serversock);
// socket write data to buffer
int anetWrite(int fd, char *buf, int count);
// set socket to non-block mode
int anetNonBlock(char *err, int fd);
// set socket to block mode
int anetBlock(char *err, int fd);
// set socket mode to tcp_nodelay
int anetEnableTcpNoDelay(char *err, int fd);
// shutdown tcp_nodelay mode
int anetDisableTcpNoDelay(char *err, int fd);
// open keepalive mode
int anetTcpKeepAlive(char *err, int fd);
// set socket send timeout value
int anetSendTimeout(char *err, int fd, long long ms);
int anetPeerToString(int fd, char *ip, size_t ip_len, int *port);
int anetKeepAlive(char *err, int fd, int interval);
// get socket port and name
int anetSockName(int fd, char *ip, size_t ip_len, int *port);
int anetFormatAddr(char *fmt, size_t fmt_len, char *ip, int port);
int anetFormatPeer(int fd, char *fmt, size_t fmt_len);
int anetFormatSock(int fd, char *fmt, size_t fmt_len);
根据上面的接口名称和注释,做过网络编程的同学就能很快发现redis的anet部分只是对tcp socket api接口的一次封装。
其中有几个主要的方法根据我自己的理解进行分析:
设置tcp_nodelay的方法包装成了连个接口,分别是打开与关闭
static int anetSetTcpNoDelay(char *err, int fd, int val)
{
if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &val, sizeof(val)) == -1)
{
anetSetError(err, "setsockopt TCP_NODELAY: %s", strerror(errno));
return ANET_ERR;
}
return ANET_OK;
}
int anetEnableTcpNoDelay(char *err, int fd)
{
return anetSetTcpNoDelay(err, fd, 1);
}
int anetDisableTcpNoDelay(char *err, int fd)
{
return anetSetTcpNoDelay(err, fd, 0);
}
使用者根据自己的实际情况选择合适的调用接口。
里面有个ipv4和ipv6的考虑挺周全的,接口如下:
int anetGenericResolve(char *err, char *host, char *ipbuf, size_t ipbuf_len,
int flags)
{
struct addrinfo hints, *info;
int rv;
memset(&hints,0,sizeof(hints));
if (flags & ANET_IP_ONLY) hints.ai_flags = AI_NUMERICHOST;
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM; /* specify socktype to avoid dups */
// hostname info
if ((rv = getaddrinfo(host, NULL, &hints, &info)) != 0) {
anetSetError(err, "%s", gai_strerror(rv));
return ANET_ERR;
}
if (info->ai_family == AF_INET) {
// ipv4
struct sockaddr_in *sa = (struct sockaddr_in *)info->ai_addr;
inet_ntop(AF_INET, &(sa->sin_addr), ipbuf, ipbuf_len);
} else {
// IPv6的解法
struct sockaddr_in6 *sa = (struct sockaddr_in6 *)info->ai_addr;
inet_ntop(AF_INET6, &(sa->sin6_addr), ipbuf, ipbuf_len);
}
freeaddrinfo(info);
return ANET_OK;
}
一般情况下,自己编程时只考虑到了ipv4的情况,但是未考虑ipv6的情况,现在看这些代码觉得作者还是挺细心周到的。
总体感觉这部分内容比较容易,暂时写到这里。