Yesterday after analyzing the Redis event-driven model very easily, today I'm going to look at Anet's code, Anet is a small encapsulation of Redis's network operations for Client/server. The official explanation for this file in the code is:
/* anet.c--basic TCP socket stuff made a bit less boring
* Based on simple basic TCP socket connection
The back of the made a bit less boring what this means here, let me a little confused, but the front is the focus, Basic TCP socket, based on the TCP protocol socket connection. The Anet.h API is as follows:
int Anettcpconnect (char *err, char *addr, int port); /* TCP Default connection */int anettcpnonblockconnect (char *err, char *addr, int port); /* TCP non-blocking Connection */int anetunixconnect (char *err, char *path); /* Anet default connection mode for UNIX mode */int anetunixnonblockconnect (char *err, char *path); /* anet UNIX mode non-blocking connection mode */int anetread (int fd, char *buf, int count); /* Anet network read files to buffer operation */int anetresolve (char *err, Char *host, Char *ipbuf, size_t Ipbuf_len); /* Parse All things */int Anetresolveip (char *err, Char *host, Char *ipbuf, size_t Ipbuf_len);
* * Resolve IP address alone/int anettcpserver (char *err, int port, char *bindaddr, int backlog);
int Anettcp6server (char *err, int port, char *bindaddr, int backlog);
int Anetunixserver (char *err, char *path, mode_t perm, int backlog);
int anettcpaccept (char *err, int serversock, char *ip, size_t ip_len, int *port);
int anetunixaccept (char *err, int serversock); int anetwrite (int fd, char *buf, int count); /* Anet writes file operation from buffer via network/int Anetnonblock (char *err, int fd); /* Anet method to set non-blocking */int Anetenabletcpnodelay (char *err, int fd); /* Enable TCP without delay */int Anetdisabletcpnodelay (char *err, int fd); /* Disable TCP connection without delay */int anettcpkeepalive (char *err, int fd); /* Set TCP to maintain active connection status.
Applies to all systems/int anetpeertostring (int fd, char *ip, size_t ip_len, int *port); int anetkeepalive (char *err, int fd, int interval);
/* Set the TCP connection to live, to detect the dead node, the interval option is only applicable to the Linux system */int anetsockname (int fd, char *ip, size_t ip_len, int *port);
We can still see a lot of familiar methods, Read,write,accept.connect and so on in any programming language. After reading this anet, the most intuitive feeling is that the author of this network operation library is for the C language System network Library of a simple package, because it is directly called the Library method function implementation. The author made a small encapsulation on the basis of his business needs. such as non-blocking settings;
/* Anet Set non-blocking method *
/int Anetnonblock (char *err, int fd)
{
int flags;
/* Set the socket non-blocking.
* Note this fcntl (2) for F_GETFL and F_SETFL can ' t
is * interrupted by a signal. */
if (flags = FCNTL (FD, F_GETFL ) = = = 1) {
anetseterror (err, "Fcntl (F_GETFL):%s", Strerror (errno));
return anet_err;
}
Call the Fcntl method to set the Non-blocking method
if (Fcntl (FD, F_SETFL, Flags | O_nonblock = = = 1) {
anetseterror (err, "Fcntl (f_setfl,o_nonblock):%s", Strerror (errno));
return anet_err;
}
return ANET_OK;
}
The Fcntl method is a direct function of the method. In the entire network operation file, let me feel a little bit of the bright spot is still some place
(1). can set block connection or none_blocked mode of connect;
/* TCP Default Connection */
int anettcpconnect (char *err, char *addr, int port)
{return
anettcpgenericconnect err,addr, Port,anet_connect_none);
}
/* TCP non-blocking Connection *
/int Anettcpnonblockconnect (char *err, char *addr, int port)
{return
anettcpgenericconnect ( Err,addr,port,anet_connect_nonblock);
}
(2). Can set the connection of the delay delay or not. :
/* Set TCP connection Nodelay no delay/
static int Anetsettcpnodelay (char *err, int fd, int val)
{
if setsockopt (FD, I Pproto_tcp, Tcp_nodelay, &val, sizeof (val)) = = 1)
{
anetseterror (err, "setsockopt tcp_nodelay:%s", Strerror (errno));
return anet_err;
}
return ANET_OK;
}
/* Enable TCP without delay */
int anetenabletcpnodelay (char *err, int fd)
{return
anetsettcpnodelay (err, FD, 1);
}
/* Disable TCP connection no delay *
/int Anetdisabletcpnodelay (char *err, int fd)
{return
anetsettcpnodelay (err, FD , 0);
}
Perhaps in some cases the delay is higher, there can be no delay.
(3). There are different processing methods for IP address with IPv4 and IPv6 address. The author's thinking is very comprehensive. This problem is taken into account when resolve parsing the address:
/* Anetgenericresolve () is called from Anetresolve () and ANETRESOLVEIP () to * do the actual work.
It resolves the hostname "host" and set the string * representation to the buffer pointed by "ipbuf". * * IF flags are set to anet_ip_only the function only resolves hostnames * that are actually already IPv4 or IPv6 addr Esses. This turns the function * into a validating/normalizing function.
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 *//parse hostname if (rv = getaddrinfo (host, NULL, &hints, &info))!= 0) {
Anetseterror (Err, "%s", Gai_strerror (RV));
return anet_err;
}
Resolves a ipV4 address based on a type or an ipV6 address if (info->ai_family = = af_inet) {struct sockaddr_in *sa = (struct SOCKADDR_
in *) info->ai_addr;
Inet_ntop (Af_inet, & (SA->SIN_ADDR), Ipbuf, Ipbuf_len);
else {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;
}
There are also some common methods, similar to the way we usually write code, such as Accept () method:
/* Socket Connection operation *
/static int anetgenericaccept (char *err, int s, struct sockaddr *sa, socklen_t *len) {
int fd;
while (1) {
//through while loop waiting for connection
FD = Accept (S,sa,len);
if (fd = = 1) {
if (errno = = eintr)
continue;
else {
Anetseterror (err, "Accept:%s", Strerror (errno));
Return Anet_err
}
}
break;
return FD;
}