深入redis内部---网络编程
Redis在anet.h和anet.c中封装了底层套接字实现: 1.anetTcpServer,建立网络套接字服务器,完成对socket(),bind(),listen()等操作的封装,返回socket的fd。 anetTcpServer( *err, port, * sa; //见1.1结构体
} ?1.1 结构体sockaddr_in sin_family;
unsigned sin_port;
in_addr sin_addr;
unsigned sin_zero[];
};
1.2 创建socket,封装了socket实现 anetCreateSocket( *err, s,on = ((s = socket(domain,SOCK_STREAM,)) == -
</span><span style="color: #008000;">/*</span><span style="color: #008000;"> Make sure connection-intensive things like the redis benchmark
* will be able to close/open sockets a zillion of times </span><span style="color: #008000;">*/</span>
<span style="color: #0000ff;">if</span> (setsockopt(s,SOL_SOCKET,SO_REUSEADDR,&on,<span style="color: #0000ff;">sizeof</span>(on)) == -<span style="color: #800080;">1</span><span style="color: #000000;">) { //设置选项
anetSetError(err,</span><span style="color: #800000;">"</span><span style="color: #800000;">setsockopt SO_REUSEADDR: %s</span><span style="color: #800000;">"</span><span style="color: #000000;">,strerror(errno));
</span><span style="color: #0000ff;">return</span><span style="color: #000000;"> ANET_ERR;
}
</span><span style="color: #0000ff;">return</span><span style="color: #000000;"> s;
} 1.3 memset函数 在C中 .h>
htons(unsigned 函数说明:htons()用来将参数指定的16 位hostshort 转换成网络字符顺序.
返回值:返回对应的网络字符顺序. <div class="para">定义函数:int inet_aton(const char string,struct <a href="http://baike.baidu.com/view/2907631.htm" target="_blank">in_addraddr); 1.5 监听,封装了bind和listen实现 anetListen( *err, s, sockaddr * (bind(s,sa,len) == -
</span><span style="color: #008000;">/*</span><span style="color: #008000;"> Use a backlog of 512 entries. We pass 511 to the listen() call because
* the kernel does: backlogsize = roundup_pow_of_two(backlogsize + 1);
* which will thus give us a backlog of 512 entries </span><span style="color: #008000;">*/</span>
<span style="color: #0000ff;">if</span> (listen(s,<span style="color: #800080;">511</span>) == -<span style="color: #800080;">1</span><span style="color: #000000;">) { //监听
anetSetError(err,</span><span style="color: #800000;">"</span><span style="color: #800000;">listen: %s</span><span style="color: #800000;">"</span><span style="color: #000000;">,strerror(errno));
close(s);
</span><span style="color: #0000ff;">return</span><span style="color: #000000;"> ANET_ERR;
}
</span><span style="color: #0000ff;">return</span><span style="color: #000000;"> ANET_OK;
} ?2.tcp连接建立堵塞和非堵塞网络套接字连接。 anetTcpConnect( *err, *addr,<span style="color: #0000ff;">int anetTcpNonBlockConnect(<span style="color: #0000ff;">char *err,ANET_CONNECT_NONBLOCK);
} <span style="color: #008000;">//<span style="color: #008000;">具体实现 <span style="color: #0000ff;">#define ANET_CONNECT_NONE 0 <span style="color: #0000ff;">#define ANET_CONNECT_NONBLOCK 1 <span style="color: #0000ff;">static <span style="color: #0000ff;">int anetTcpGenericConnect(<span style="color: #0000ff;">char *err,<span style="color: #0000ff;">int<span style="color: #000000;"> flags) { <span style="color: #0000ff;">int<span style="color: #000000;"> s; <span style="color: #0000ff;">struct<span style="color: #000000;"> sockaddr_in sa;
} 2.1 结构体hostent * ** **
其中,h_name?–?地址的正式名称。? h_aliases?–?空字节-地址的预备名称的指针。? h_addrtype?–地址类型;?通常是AF_INET。?? h_length?–?地址的比特长度。? h_addr_list?–?零字节-主机网络地址指针。网络字节顺序。? h_addr?-?h_addr_list中的第一地址。?gethostbyname()?成功时返回一个指向结构体?hostent?的指针,或者?是个空?(NULL)?指针。 2.2 设置非堵塞 anetNonBlock( *err,
</span><span style="color: #008000;">/*</span><span style="color: #008000;"> Set the socket non-blocking.
* Note that fcntl(2) for F_GETFL and F_SETFL can't be
* interrupted by a signal. </span><span style="color: #008000;">*/</span>
<span style="color: #0000ff;">if</span> ((flags = <span style="color: #ff0000;">fcntl</span>(fd,F_GETFL)) == -<span style="color: #800080;">1</span><span style="color: #000000;">) {
anetSetError(err,</span><span style="color: #800000;">"</span><span style="color: #800000;">fcntl(F_GETFL): %s</span><span style="color: #800000;">"</span><span style="color: #000000;">,strerror(errno));
</span><span style="color: #0000ff;">return</span><span style="color: #000000;"> ANET_ERR;
}
</span><span style="color: #0000ff;">if</span> (fcntl(fd,F_SETFL,flags | O_NONBLOCK) == -<span style="color: #800080;">1</span><span style="color: #000000;">) {
anetSetError(err,</span><span style="color: #800000;">"</span><span style="color: #800000;">fcntl(F_SETFL,O_NONBLOCK): %s</span><span style="color: #800000;">"</span><span style="color: #000000;">,strerror(errno));
</span><span style="color: #0000ff;">return</span><span style="color: #000000;"> ANET_ERR;
}
</span><span style="color: #0000ff;">return</span><span style="color: #000000;"> ANET_OK;
} 2.3 文件控制fcntl
(fcntl(socket_descriptor,flags | O_NONBLOCK) <
((flags = fcntl(sock_descriptor,F_GETFL,)) <
3. tcp接收,在网络套接字上新增连接 anetTcpAccept( *err, *ip, *= ((fd = (err,&salen)) ==
</span><span style="color: #0000ff;">if</span><span style="color: #000000;"> (ip) strcpy(ip,inet_ntoa(sa.sin_addr));
</span><span style="color: #0000ff;">if</span> (port) *port =<span style="color: #000000;"> ntohs(sa.sin_port);
</span><span style="color: #0000ff;">return</span><span style="color: #000000;"> fd;
} 封装了accept函数 anetGenericAccept( *err, sockaddr *sa,socklen_t *(= (fd == - (errno ==
4. 其它方法 ? anetEnableTcpNoDelay:将tcp连接设为非延迟性的,即屏蔽Nagle算法。使用setsockopt方法实现。 ??anetDisableTcpNoDelay:和上面的方法作用相反。使用setsockopt方法实现。 ? anetTcpKeepAlive:开启连接检测,避免对方宕机或者网络中断时fd一直堵塞。使用setsockopt方法实现。 ? anetRead和anetWrite:套接字的读写。 ?参考资料 Redis源代码分析.pdf----未知来源 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |