Redis源码分析之anet网络通信的封装
生活随笔
收集整理的這篇文章主要介紹了
Redis源码分析之anet网络通信的封装
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
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 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; }一般情況下,自己編程時只考慮到了ipv4的情況,但是未考慮ipv6的情況,現在看這些代碼覺得作者還是挺細心周到的。
總體感覺這部分內容比較容易,暫時寫到這里。
總結
以上是生活随笔為你收集整理的Redis源码分析之anet网络通信的封装的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 软件开发模型-螺旋模型
- 下一篇: 前端工程化之FaaS SSR方案