Redis源码分析之anet网络通信的封装
生活随笔
收集整理的這篇文章主要介紹了
Redis源码分析之anet网络通信的封装
小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
anet是redis對(duì)tcp/ip網(wǎng)絡(luò)中socket api接口的一個(gè)全面的封裝,針對(duì)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讀數(shù)據(jù) 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()函數(shù)創(chuàng)建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);根據(jù)上面的接口名稱和注釋,做過網(wǎng)絡(luò)編程的同學(xué)就能很快發(fā)現(xiàn)redis的anet部分只是對(duì)tcp socket api接口的一次封裝。
其中有幾個(gè)主要的方法根據(jù)我自己的理解進(jìn)行分析:
設(shè)置tcp_nodelay的方法包裝成了連個(gè)接口,分別是打開與關(guān)閉
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); }使用者根據(jù)自己的實(shí)際情況選擇合適的調(diào)用接口。
里面有個(gè)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 infoif ((rv = getaddrinfo(host, NULL, &hints, &info)) != 0) {anetSetError(err, "%s", gai_strerror(rv));return ANET_ERR;}if (info->ai_family == AF_INET) {// ipv4struct 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; }一般情況下,自己編程時(shí)只考慮到了ipv4的情況,但是未考慮ipv6的情況,現(xiàn)在看這些代碼覺得作者還是挺細(xì)心周到的。
總體感覺這部分內(nèi)容比較容易,暫時(shí)寫到這里。
總結(jié)
以上是生活随笔為你收集整理的Redis源码分析之anet网络通信的封装的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 软件开发模型-螺旋模型
- 下一篇: 基于Springboot+MYSQL实现