MySQL源码中处理客户端不同地址族的源码
来源:互联网 发布:白银大非农数据分析 编辑:程序博客网 时间:2024/06/09 16:22
在ws2def.h文件中定义的结构:
typedef struct sockaddr_storage {
ADDRESS_FAMILYss_family; // addressfamily
CHAR __ss_pad1[_SS_PAD1SIZE]; // 6 byte pad, thisis to make
// implementationspecific pad up to
// alignment fieldthat follows explicit
// in the datastructure
__int64 __ss_align; // Fieldto force desired structure
CHAR __ss_pad2[_SS_PAD2SIZE]; // 112 byte pad toachieve desired size;
// _SS_MAXSIZEvalue minus size of
// ss_family,__ss_pad1, and
// __ss_alignfields is 112
} SOCKADDR_STORAGE_LH,*PSOCKADDR_STORAGE_LH, FAR *LPSOCKADDR_STORAGE_LH;
微软说明:
The SOCKADDR_STORAGE structure stores socket addressinformation. Since the SOCKADDR_STORAGE structure is sufficiently large tostore address information for IPv4, IPv6, or other address families, its usepromotes protocol-family and protocol-version independence and simplifies cross-platformdevelopment. Use the SOCKADDR_STORAGEstructure in place of the sockaddr structure.可用用来存储不同协议族的地址结构,在跨平台的环境中,用来代替sockaddr结构。sockaddr不能用于夸平台结构中吗?不会吧。
其中:
#define _SS_MAXSIZE 128 //Maximum size
#define _SS_ALIGNSIZE (sizeof(__int64)) // Desired alignment
#if(_WIN32_WINNT >=0x0600)
#define _SS_PAD1SIZE (_SS_ALIGNSIZE - sizeof(USHORT))
#define _SS_PAD2SIZE (_SS_MAXSIZE - (sizeof(USHORT) + _SS_PAD1SIZE+ _SS_ALIGNSIZE))
#else
#define _SS_PAD1SIZE (_SS_ALIGNSIZE - sizeof(short))
#define _SS_PAD2SIZE (_SS_MAXSIZE - (sizeof(short) + _SS_PAD1SIZE/
+ _SS_ALIGNSIZE))
#endif //(_WIN32_WINNT >= 0x0600)
可以看出,整个sockaddr_storage结构大小为128个字节。
而在MySQL中st_vio结构中对IP地址就是使用该结构,而不是以往使用的addr_in了,这是为了处理IPv4和IPv6而定义的吧。
看看下面在MySQL中获取客户端的处理流程吧
通过客户端套接字à获取客户端sockaddr->获取客户端IP和端口
调用函数getpeername->getnameinfo
源码如下:
/**
Return IP address and port of a VIO clientsocket.
The function returns an IPv4 address if IPv6support is disabled.
The function returns an IPv4 address if theclient socket is associated
with an IPv4-compatible or IPv4-mapped IPv6address. Otherwise, the native
IPv6 address is returned.
*/
my_bool vio_peer_addr(Vio *vio, char *ip_buffer, uint16 *port,
size_tip_buffer_size)
{
DBUG_ENTER("vio_peer_addr");
DBUG_PRINT("enter", ("Clientsocked fd: %d", (int) vio->sd));
if (vio->localhost)//是本机的话,当然简单了
{
/*
Initialize vio->remote andvio->addLen. Set vio->remote to IPv4 loopback
address.
*/
struct in_addr *ip4=&((struct sockaddr_in*) &(vio->remote))->sin_addr;
vio->remote.ss_family=AF_INET;
vio->addrLen= sizeof (struct sockaddr_in);
ip4->s_addr= htonl(INADDR_LOOPBACK);
/* Initializeip_buffer and port. */
strmov(ip_buffer, "127.0.0.1");
*port=0;
}
else
{
int err_code;
char port_buffer[NI_MAXSERV];
struct sockaddr_storage addr_storage;
struct sockaddr *addr=(struct sockaddr*) &addr_storage;
size_socketaddr_length= sizeof(addr_storage);
/* Get sockaddrby socked fd. */
err_code=getpeername(vio->sd, addr, &addr_length);
if (err_code)
{
DBUG_PRINT("exit", ("getpeername()gave error: %d", socket_errno));
DBUG_RETURN(TRUE);
}
/* Normalize IPaddress. */
vio_get_normalized_ip(addr, addr_length,
(struct sockaddr *)&vio->remote,&vio->addrLen);
/* Get IP address& port number. */
err_code=vio_getnameinfo((structsockaddr *) &vio->remote,
ip_buffer, ip_buffer_size,
port_buffer, NI_MAXSERV,
NI_NUMERICHOST | NI_NUMERICSERV);
if (err_code)
{
DBUG_PRINT("exit", ("getnameinfo()gave error: %s",
gai_strerror(err_code)));
DBUG_RETURN(TRUE);
}
*port= (uint16) strtol(port_buffer, NULL,10);
}
DBUG_PRINT("exit", ("ClientIP address: %s; port: %d",
(constchar *) ip_buffer,
(int)*port));
DBUG_RETURN(FALSE);
}
针对不同协议族进行处理:
/**
Convert a sock-address (AF_INET or AF_INET6)into the "normalized" form,
which is the IPv4 form for IPv4-mapped orIPv4-compatible IPv6 addresses.
@note Background: when IPv4 and IPv6 are usedsimultaneously, IPv4
addresses may be written in a form ofIPv4-mapped or IPv4-compatible IPv6
addresses. That means, one address (a.b.c.d)can be written in three forms:
- IPv4: a.b.c.d;
- IPv4-compatible IPv6: ::a.b.c.d;
- IPv4-mapped IPv4: ::ffff:a.b.c.d;
Having three forms of one address makes it alittle difficult to compare
addresses with each other (theIPv4-compatible IPv6-address of foo.bar
will be different from the IPv4-mappedIPv6-address of foo.bar).
@note This function can be made public whenit's needed.
@param src [in] source IP address (AF_INET orAF_INET6).
@param src_length [in] length of the src.
@param dst [out] a buffer to store normalized IPaddress
(sockaddr_storage).
@param dst_length [out] actual length of thenormalized IP address.
*/
static void vio_get_normalized_ip(conststruct sockaddr*src,
int src_length,
struct sockaddr *dst,
int *dst_length)
{
switch (src->sa_family){
case AF_INET:
memcpy(dst, src, src_length);
*dst_length=src_length;
break;
#ifdef HAVE_IPV6
case AF_INET6:
{
const struct sockaddr_in6*src_addr6= (conststruct sockaddr_in6*) src;
const struct in6_addr *src_ip6= &(src_addr6->sin6_addr);
const uint32 *src_ip6_int32=(uint32 *) src_ip6->s6_addr;
if (IN6_IS_ADDR_V4MAPPED(src_ip6)|| IN6_IS_ADDR_V4COMPAT(src_ip6))
{
struct sockaddr_in *dst_ip4=(struct sockaddr_in*) dst;
/*判断该地址是否是从IPv4转换而来的,如果是,则转换成IPv4地址
This is an IPv4-mapped orIPv4-compatible IPv6 address. It should
be converted to the IPv4 form.
*/
*dst_length=sizeof (struct sockaddr_in);
memset(dst_ip4, 0, *dst_length);
dst_ip4->sin_family= AF_INET;
dst_ip4->sin_port= src_addr6->sin6_port;
/*
In an IPv4 mapped or compatibleaddress, the last 32 bits represent
the IPv4 address. The byte orders forIPv6 and IPv4 addresses are
the same, so a simple copy is possible.
*/
dst_ip4->sin_addr.s_addr=src_ip6_int32[3];
}
else
{
/* This is a"native" IPv6 address. */
memcpy(dst, src, src_length);
*dst_length=src_length;
}
break;
}
#endif /* HAVE_IPV6 */
}
}
IPv6地址结构:
typedef struct sockaddr_in6 {
ADDRESS_FAMILYsin6_family; //AF_INET6.
USHORT sin6_port; //Transport level port number.
ULONG sin6_flowinfo; // IPv6 flowinformation.
IN6_ADDRsin6_addr; // IPv6address.
union {
ULONGsin6_scope_id; // Set ofinterfaces for a scope.
SCOPE_IDsin6_scope_struct;
};
} SOCKADDR_IN6_LH,*PSOCKADDR_IN6_LH, FAR*LPSOCKADDR_IN6_LH;
下面就到了返回套接字地址的IP和端口了,MySQL函数调用如下:
/**
This is a wrapper for the systemgetnameinfo(), because different OS
differ in the getnameinfo() implementation:
- Solaris 10 requires that the 2nd argument(salen) must match the
actual size of the struct sockaddr_storagepassed to it;
- Mac OS X has sockaddr_in::sin_len andsockaddr_in6::sin6_len and
requires them to be filled.
*/
int vio_getnameinfo(const struct sockaddr *sa,
char*hostname, size_thostname_size,
char*port, size_tport_size,
intflags)
{
int sa_length= 0;
switch (sa->sa_family){
case AF_INET:
sa_length=sizeof (struct sockaddr_in);
#ifdef HAVE_SOCKADDR_IN_SIN_LEN
((struct sockaddr_in *) sa)->sin_len= sa_length;
#endif /* HAVE_SOCKADDR_IN_SIN_LEN */
break;
#ifdef HAVE_IPV6
case AF_INET6:
sa_length=sizeof (struct sockaddr_in6);
# ifdef HAVE_SOCKADDR_IN6_SIN6_LEN
((struct sockaddr_in6 *) sa)->sin6_len= sa_length;
# endif /* HAVE_SOCKADDR_IN6_SIN6_LEN*/
break;
#endif /* HAVE_IPV6 */
}
return getnameinfo(sa,sa_length,
hostname,hostname_size,
port,port_size,
flags);//使用该函数完成调用
}
个人学习笔记,可能写得较乱,哈哈
- MySQL源码中处理客户端不同地址族的源码
- mysql源码地址
- 【源码共享】C#+ASP.NET中在客户端取硬盘序列号和网卡MAC地址的源码
- mysql 源码学习笔记:客户端连接处理流程
- 开源中国客户端源码下载地址
- 重要的源码地址
- 本地取机器的mac地址,取客户端ip,mac地址方法(源码)
- python源码中中文注释的处理
- MySQL 服务器监听客户端连接源码
- 通过崩溃地址查找出源码中出错的行数
- android 开发中经常使用到的库源码地址
- 关于SIP的源码地址
- 关于SIP的源码地址
- 关于SIP的源码地址
- 关于SIP的源码地址
- omcat6源码的下载地址
- 获取mac地址的源码
- iphone的IP地址源码
- scroll view 原理
- UITableView 详细讲解
- dell e6400 安装 mac os
- 熟悉UIWebView
- 使用JS制作弹出框的几个小问题
- MySQL源码中处理客户端不同地址族的源码
- 【补足基础】C++中引用传递与指针传递区别【转】
- 2011.6.18 图论,有向图的十字链表
- iphone开发者证书装多台电脑的方法
- 2011.6.18 图的十字链表
- 熟悉UIWebView
- 闲着无聊-AC一个水题
- iphone开发者证书下载 安装
- 熟悉UIWebView